aboutsummaryrefslogtreecommitdiff
path: root/libjava
diff options
context:
space:
mode:
authorTom Tromey <tromey@redhat.com>2001-02-09 23:28:55 +0000
committerTom Tromey <tromey@gcc.gnu.org>2001-02-09 23:28:55 +0000
commit932670198f01eab28395bc628962f0e339bd2982 (patch)
treef3b7bdbe68d45481ed0248db636deddbb8a80942 /libjava
parent0e206b71aab6068420185d98893ee2de8545737a (diff)
downloadgcc-932670198f01eab28395bc628962f0e339bd2982.zip
gcc-932670198f01eab28395bc628962f0e339bd2982.tar.gz
gcc-932670198f01eab28395bc628962f0e339bd2982.tar.bz2
* java/util/Timer.java: New version from Classpath.
From-SVN: r39573
Diffstat (limited to 'libjava')
-rw-r--r--libjava/ChangeLog4
-rw-r--r--libjava/java/util/Timer.java921
2 files changed, 496 insertions, 429 deletions
diff --git a/libjava/ChangeLog b/libjava/ChangeLog
index e1002bf..93a23bc 100644
--- a/libjava/ChangeLog
+++ b/libjava/ChangeLog
@@ -1,3 +1,7 @@
+2001-02-09 Tom Tromey <tromey@redhat.com>
+
+ * java/util/Timer.java: New version from Classpath.
+
2001-02-09 Bryce McKinlay <bryce@albatross.co.nz>
* java/lang/Double.java (doubleToRawLongBits): Now native.
diff --git a/libjava/java/util/Timer.java b/libjava/java/util/Timer.java
index 8c3e993..d00c937 100644
--- a/libjava/java/util/Timer.java
+++ b/libjava/java/util/Timer.java
@@ -1,5 +1,5 @@
/* Timer.java -- Timer that runs TimerTasks at a later time.
- Copyright (C) 2000 Free Software Foundation, Inc.
+ Copyright (C) 2000, 2001 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -7,7 +7,7 @@ GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
-
+
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
@@ -50,476 +50,539 @@ package java.util;
* @since 1.3
* @author Mark Wielaard (mark@klomp.org)
*/
-public class Timer {
-
- /**
- * Priority Task Queue.
- * TimerTasks are kept in a binary heap.
- * The scheduler calls sleep() on the queue when it has nothing to do or
- * has to wait. A sleeping scheduler can be notified by calling interrupt()
- * which is automatically called by the enqueue(), cancel() and
- * timerFinalized() methods.
- */
- private static final class TaskQueue {
-
- /** Default size of this queue */
- private final int DEFAULT_SIZE = 32;
-
- /** Wheter to return null when there is nothing in the queue */
- private boolean nullOnEmpty;
-
- /**
- * The heap containing all the scheduled TimerTasks
- * sorted by the TimerTask.scheduled field.
- * Null when the stop() method has been called.
- */
- private TimerTask heap[];
-
- /**
- * The actual number of elements in the heap
- * Can be less then heap.length.
- * Note that heap[0] is used as a sentinel.
- */
- private int elements;
-
- /**
- * Creates a TaskQueue of default size without any elements in it.
- */
- public TaskQueue() {
- heap = new TimerTask[DEFAULT_SIZE];
- elements = 0;
- nullOnEmpty = false;
- }
-
- /**
- * Adds a TimerTask at the end of the heap.
- * Grows the heap if necessary by doubling the heap in size.
- */
- private void add(TimerTask task) {
- elements++;
- if (elements == heap.length) {
- TimerTask new_heap[] = new TimerTask[heap.length*2];
- System.arraycopy(heap, 0, new_heap, 0, heap.length);
- heap = new_heap;
- }
- heap[elements] = task;
- }
-
- /**
- * Removes the last element from the heap.
- * Shrinks the heap in half if
- * elements+DEFAULT_SIZE/2 <= heap.length/4.
- */
- private void remove() {
- // clear the entry first
- heap[elements] = null;
- elements--;
- if (elements+DEFAULT_SIZE/2 <= (heap.length/4)) {
- TimerTask new_heap[] = new TimerTask[heap.length/2];
- System.arraycopy(heap, 0, new_heap, 0, elements+1);
- }
- }
-
- /**
- * Adds a task to the queue and puts it at the correct place
- * in the heap.
- */
- public synchronized void enqueue(TimerTask task) {
-
- // Check if it is legal to add another element
- if (heap == null) {
- throw new IllegalStateException
- ("cannot enqueue when stop() has been called on queue");
- }
-
- heap[0] = task; // sentinel
- add(task); // put the new task at the end
- // Now push the task up in the heap until it has reached its place
- int child = elements;
- int parent = child / 2;
- while (heap[parent].scheduled > task.scheduled) {
- heap[child] = heap[parent];
- child = parent;
- parent = child / 2;
- }
- // This is the correct place for the new task
- heap[child] = task;
- heap[0] = null; // clear sentinel
- // Maybe sched() is waiting for a new element
- this.notify();
- }
-
- /**
- * Returns the top element of the queue.
- * Can return null when no task is in the queue.
- */
- private TimerTask top() {
- if (elements == 0) {
- return null;
- } else {
- return heap[1];
- }
- }
-
- /**
- * Returns the top task in the Queue.
- * Removes the element from the heap and reorders the heap first.
- * Can return null when there is nothing in the queue.
- */
- public synchronized TimerTask serve() {
- // The task to return
- TimerTask task = null;
-
- while (task == null) {
- // Get the next task
- task = top();
-
- // return null when asked to stop
- // or if asked to return null when the queue is empty
- if ((heap == null) || (task == null && nullOnEmpty)) {
- return null;
- }
-
- // Do we have a task?
- if (task != null) {
- // The time to wait until the task should be served
- long time = task.scheduled-System.currentTimeMillis();
- if (time > 0) {
- // This task should not yet be served
- // So wait until this task is ready
- // or something else happens to the queue
- task = null; // set to null to make sure we call top()
- try {
- this.wait(time);
- } catch (InterruptedException _) {}
- }
- } else {
- // wait until a task is added
- // or something else happens to the queue
- try {
- this.wait();
- } catch (InterruptedException _) {}
- }
- }
-
- // reconstruct the heap
- TimerTask lastTask = heap[elements];
- remove();
-
- // drop lastTask at the beginning and move it down the heap
- int parent = 1;
- int child = 2;
- heap[1] = lastTask;
- while(child <= elements) {
- if (child < elements) {
- if (heap[child].scheduled > heap[child+1].scheduled) {
- child++;
- }
- }
-
- if (lastTask.scheduled <= heap[child].scheduled)
- break; // found the correct place (the parent) - done
-
- heap[parent] = heap[child];
- parent = child;
- child = parent*2;
- }
-
- // this is the correct new place for the lastTask
- heap[parent] = lastTask;
-
- // return the task
- return task;
- }
-
-
- /**
- * When nullOnEmpty is true the serve() method will return null when
- * there are no tasks in the queue, otherwise it will wait until
- * a new element is added to the queue. It is used to indicate to
- * the scheduler that no new tasks will ever be added to the queue.
- */
- public synchronized void setNullOnEmpty(boolean nullOnEmpty) {
- this.nullOnEmpty = nullOnEmpty;
- this.notify();
- }
-
- /**
- * When this method is called the current and all future calls to
- * serve() will return null. It is used to indicate to the Scheduler
- * that it should stop executing since no more tasks will come.
- */
- public synchronized void stop() {
- this.heap = null;
- this.notify();
- }
-
- } // TaskQueue
+public class Timer
+{
+ /**
+ * Priority Task Queue.
+ * TimerTasks are kept in a binary heap.
+ * The scheduler calls sleep() on the queue when it has nothing to do or
+ * has to wait. A sleeping scheduler can be notified by calling interrupt()
+ * which is automatically called by the enqueue(), cancel() and
+ * timerFinalized() methods.
+ */
+ private static final class TaskQueue
+ {
+ /** Default size of this queue */
+ private final int DEFAULT_SIZE = 32;
+
+ /** Wheter to return null when there is nothing in the queue */
+ private boolean nullOnEmpty;
/**
- * The scheduler that executes all the tasks on a particular TaskQueue,
- * reschedules any repeating tasks and that waits when no task has to be
- * executed immediatly. Stops running when canceled or when the parent
- * Timer has been finalized and no more tasks have to be executed.
+ * The heap containing all the scheduled TimerTasks
+ * sorted by the TimerTask.scheduled field.
+ * Null when the stop() method has been called.
*/
- private static final class Scheduler implements Runnable {
-
- // The priority queue containing all the TimerTasks.
- private TaskQueue queue;
-
- /**
- * Creates a new Scheduler that will schedule the tasks on the
- * given TaskQueue.
- */
- public Scheduler(TaskQueue queue) {
- this.queue = queue;
- }
-
- public void run() {
- TimerTask task;
- while((task = queue.serve()) != null) {
- // If this task has not been canceled
- if (task.scheduled >= 0) {
-
- // Mark execution time
- task.lastExecutionTime = task.scheduled;
-
- // Repeatable task?
- if (task.period < 0) {
- // Last time this task is executed
- task.scheduled = -1;
- }
-
- // Run the task
- try {
- task.run();
- } catch (Throwable t) {/* ignore all errors */}
- }
-
- // Calculate next time and possibly re-enqueue
- if (task.scheduled >= 0) {
- if (task.fixed) {
- task.scheduled += task.period;
- } else {
- task.scheduled = task.period +
- System.currentTimeMillis();
- }
- queue.enqueue(task);
- }
- }
- }
- } // Scheduler
-
- // Number of Timers created.
- // Used for creating nice Thread names.
- private static int nr = 0;
-
- // The queue that all the tasks are put in.
- // Given to the scheduler
- private TaskQueue queue;
-
- // The Scheduler that does all the real work
- private Scheduler scheduler;
-
- // Used to run the scheduler.
- // Also used to checked if the Thread is still running by calling
- // thread.isAlive(). Sometimes a Thread is suddenly killed by the system
- // (if it belonged to an Applet).
- private Thread thread;
-
- // When cancelled we don't accept any more TimerTasks.
- private boolean canceled;
-
- /**
- * Creates a new Timer with a non deamon Thread as Scheduler, with normal
- * priority and a default name.
- */
- public Timer() {
- this(false);
- }
+ private TimerTask heap[];
/**
- * Creates a new Timer with a deamon Thread as scheduler if deamon is true,
- * with normal priority and a default name.
+ * The actual number of elements in the heap
+ * Can be less then heap.length.
+ * Note that heap[0] is used as a sentinel.
*/
- public Timer(boolean daemon) {
- this(daemon, Thread.NORM_PRIORITY);
- }
+ private int elements;
/**
- * Creates a new Timer with a deamon Thread as scheduler if deamon is true,
- * with the priority given and a default name.
+ * Creates a TaskQueue of default size without any elements in it.
*/
- private Timer(boolean daemon, int priority) {
- this(daemon, priority, "Timer-" + (++nr));
+ public TaskQueue()
+ {
+ heap = new TimerTask[DEFAULT_SIZE];
+ elements = 0;
+ nullOnEmpty = false;
}
/**
- * Creates a new Timer with a deamon Thread as scheduler if deamon is true,
- * with the priority and name given.E
+ * Adds a TimerTask at the end of the heap.
+ * Grows the heap if necessary by doubling the heap in size.
*/
- private Timer(boolean daemon, int priority, String name) {
- canceled = false;
- queue = new TaskQueue();
- scheduler = new Scheduler(queue);
- thread = new Thread(scheduler, name);
- thread.setDaemon(daemon);
- thread.setPriority(priority);
- thread.start();
+ private void add(TimerTask task)
+ {
+ elements++;
+ if (elements == heap.length)
+ {
+ TimerTask new_heap[] = new TimerTask[heap.length * 2];
+ System.arraycopy(heap, 0, new_heap, 0, heap.length);
+ heap = new_heap;
+ }
+ heap[elements] = task;
}
/**
- * Cancels the execution of the scheduler. If a task is executing it will
- * normally finish execution, but no other tasks will be executed and no
- * more tasks can be scheduled.
+ * Removes the last element from the heap.
+ * Shrinks the heap in half if
+ * elements+DEFAULT_SIZE/2 <= heap.length/4.
*/
- public void cancel() {
- canceled = true;
- queue.stop();
+ private void remove()
+ {
+ // clear the entry first
+ heap[elements] = null;
+ elements--;
+ if (elements + DEFAULT_SIZE / 2 <= (heap.length / 4))
+ {
+ TimerTask new_heap[] = new TimerTask[heap.length / 2];
+ System.arraycopy(heap, 0, new_heap, 0, elements + 1);
+ heap = new_heap;
+ }
}
/**
- * Schedules the task at Time time, repeating every period
- * milliseconds if period is positive and at a fixed rate if fixed is true.
- *
- * @exception IllegalArgumentException if time is negative
- * @exception IllegalStateException if the task was already scheduled or
- * canceled or this Timer is canceled or the scheduler thread has died
+ * Adds a task to the queue and puts it at the correct place
+ * in the heap.
*/
- private void schedule(TimerTask task,
- long time,
- long period,
- boolean fixed) {
-
- if (time < 0)
- throw new IllegalArgumentException("negative time");
-
- if (task.scheduled == 0 && task.lastExecutionTime == -1) {
- task.scheduled = time;
- task.period = period;
- task.fixed = fixed;
- } else {
- throw new IllegalStateException
- ("task was already scheduled or canceled");
- }
-
- if (!this.canceled && this.thread != null) {
- queue.enqueue(task);
- } else {
- throw new IllegalStateException
- ("timer was canceled or scheduler thread has died");
- }
- }
-
- private static void positiveDelay(long delay) {
- if (delay < 0) {
- throw new IllegalArgumentException("delay is negative");
- }
- }
-
- private static void positivePeriod(long period) {
- if (period < 0) {
- throw new IllegalArgumentException("period is negative");
- }
+ public synchronized void enqueue(TimerTask task)
+ {
+ // Check if it is legal to add another element
+ if (heap == null)
+ {
+ throw new IllegalStateException
+ ("cannot enqueue when stop() has been called on queue");
+ }
+
+ heap[0] = task; // sentinel
+ add(task); // put the new task at the end
+ // Now push the task up in the heap until it has reached its place
+ int child = elements;
+ int parent = child / 2;
+ while (heap[parent].scheduled > task.scheduled)
+ {
+ heap[child] = heap[parent];
+ child = parent;
+ parent = child / 2;
+ }
+ // This is the correct place for the new task
+ heap[child] = task;
+ heap[0] = null; // clear sentinel
+ // Maybe sched() is waiting for a new element
+ this.notify();
}
/**
- * Schedules the task at the specified data for one time execution.
- *
- * @exception IllegalArgumentException if date.getTime() is negative
- * @exception IllegalStateException if the task was already scheduled or
- * canceled or this Timer is canceled or the scheduler thread has died
+ * Returns the top element of the queue.
+ * Can return null when no task is in the queue.
*/
- public void schedule(TimerTask task, Date date) {
- long time = date.getTime();
- schedule(task, time, -1, false);
+ private TimerTask top()
+ {
+ if (elements == 0)
+ {
+ return null;
+ }
+ else
+ {
+ return heap[1];
+ }
}
/**
- * Schedules the task at the specified date and reschedules the task every
- * period milliseconds after the last execution of the task finishes until
- * this timer or the task is canceled.
- *
- * @exception IllegalArgumentException if period or date.getTime() is
- * negative
- * @exception IllegalStateException if the task was already scheduled or
- * canceled or this Timer is canceled or the scheduler thread has died
+ * Returns the top task in the Queue.
+ * Removes the element from the heap and reorders the heap first.
+ * Can return null when there is nothing in the queue.
*/
- public void schedule(TimerTask task, Date date, long period) {
- positivePeriod(period);
- long time = date.getTime();
- schedule(task, time, period, false);
+ public synchronized TimerTask serve()
+ {
+ // The task to return
+ TimerTask task = null;
+
+ while (task == null)
+ {
+ // Get the next task
+ task = top();
+
+ // return null when asked to stop
+ // or if asked to return null when the queue is empty
+ if ((heap == null) || (task == null && nullOnEmpty))
+ {
+ return null;
+ }
+
+ // Do we have a task?
+ if (task != null)
+ {
+ // The time to wait until the task should be served
+ long time = task.scheduled - System.currentTimeMillis();
+ if (time > 0)
+ {
+ // This task should not yet be served
+ // So wait until this task is ready
+ // or something else happens to the queue
+ task = null; // set to null to make sure we call top()
+ try
+ {
+ this.wait(time);
+ }
+ catch (InterruptedException _)
+ {
+ }
+ }
+ }
+ else
+ {
+ // wait until a task is added
+ // or something else happens to the queue
+ try
+ {
+ this.wait();
+ }
+ catch (InterruptedException _)
+ {
+ }
+ }
+ }
+
+ // reconstruct the heap
+ TimerTask lastTask = heap[elements];
+ remove();
+
+ // drop lastTask at the beginning and move it down the heap
+ int parent = 1;
+ int child = 2;
+ heap[1] = lastTask;
+ while (child <= elements)
+ {
+ if (child < elements)
+ {
+ if (heap[child].scheduled > heap[child + 1].scheduled)
+ {
+ child++;
+ }
+ }
+
+ if (lastTask.scheduled <= heap[child].scheduled)
+ break; // found the correct place (the parent) - done
+
+ heap[parent] = heap[child];
+ parent = child;
+ child = parent * 2;
+ }
+
+ // this is the correct new place for the lastTask
+ heap[parent] = lastTask;
+
+ // return the task
+ return task;
}
/**
- * Schedules the task after the specified delay milliseconds for one time
- * execution.
- *
- * @exception IllegalArgumentException if delay or
- * System.currentTimeMillis + delay is negative
- * @exception IllegalStateException if the task was already scheduled or
- * canceled or this Timer is canceled or the scheduler thread has died
+ * When nullOnEmpty is true the serve() method will return null when
+ * there are no tasks in the queue, otherwise it will wait until
+ * a new element is added to the queue. It is used to indicate to
+ * the scheduler that no new tasks will ever be added to the queue.
*/
- public void schedule(TimerTask task, long delay) {
- positiveDelay(delay);
- long time = System.currentTimeMillis() + delay;
- schedule(task, time, -1, false);
+ public synchronized void setNullOnEmpty(boolean nullOnEmpty)
+ {
+ this.nullOnEmpty = nullOnEmpty;
+ this.notify();
}
/**
- * Schedules the task after the delay milliseconds and reschedules the
- * task every period milliseconds after the last execution of the task
- * finishes until this timer or the task is canceled.
- *
- * @exception IllegalArgumentException if delay or period is negative
- * @exception IllegalStateException if the task was already scheduled or
- * canceled or this Timer is canceled or the scheduler thread has died
+ * When this method is called the current and all future calls to
+ * serve() will return null. It is used to indicate to the Scheduler
+ * that it should stop executing since no more tasks will come.
*/
- public void schedule(TimerTask task, long delay, long period) {
- positiveDelay(delay);
- positivePeriod(period);
- long time = System.currentTimeMillis() + delay;
- schedule(task, time, period, false);
+ public synchronized void stop()
+ {
+ this.heap = null;
+ this.notify();
}
- /**
- * Schedules the task at the specified date and reschedules the task at a
- * fixed rate every period milliseconds until this timer or the task is
- * canceled.
- *
- * @exception IllegalArgumentException if period or date.getTime() is
- * negative
- * @exception IllegalStateException if the task was already scheduled or
- * canceled or this Timer is canceled or the scheduler thread has died
- */
- public void scheduleAtFixedRate(TimerTask task, Date date, long period) {
- positivePeriod(period);
- long time = date.getTime();
- schedule(task, time, period, true);
- }
+ } // TaskQueue
+
+ /**
+ * The scheduler that executes all the tasks on a particular TaskQueue,
+ * reschedules any repeating tasks and that waits when no task has to be
+ * executed immediatly. Stops running when canceled or when the parent
+ * Timer has been finalized and no more tasks have to be executed.
+ */
+ private static final class Scheduler implements Runnable
+ {
+ // The priority queue containing all the TimerTasks.
+ private TaskQueue queue;
/**
- * Schedules the task after the delay milliseconds and reschedules the task
- * at a fixed rate every period milliseconds until this timer or the task
- * is canceled.
- *
- * @exception IllegalArgumentException if delay or
- * System.currentTimeMillis + delay is negative
- * @exception IllegalStateException if the task was already scheduled or
- * canceled or this Timer is canceled or the scheduler thread has died
+ * Creates a new Scheduler that will schedule the tasks on the
+ * given TaskQueue.
*/
- public void scheduleAtFixedRate(TimerTask task, long delay, long period) {
- positiveDelay(delay);
- positivePeriod(period);
- long time = System.currentTimeMillis() + delay;
- schedule(task, time, period, true);
+ public Scheduler(TaskQueue queue)
+ {
+ this.queue = queue;
}
- /**
- * Tells the scheduler that the Timer task died
- * so there will be no more new tasks scheduled.
- */
- protected void finalize() {
- queue.setNullOnEmpty(true);
+ public void run()
+ {
+ TimerTask task;
+ while ((task = queue.serve()) != null)
+ {
+ // If this task has not been canceled
+ if (task.scheduled >= 0)
+ {
+
+ // Mark execution time
+ task.lastExecutionTime = task.scheduled;
+
+ // Repeatable task?
+ if (task.period < 0)
+ {
+ // Last time this task is executed
+ task.scheduled = -1;
+ }
+
+ // Run the task
+ try
+ {
+ task.run();
+ }
+ catch (Throwable t)
+ {
+ /* ignore all errors */
+ }
+ }
+
+ // Calculate next time and possibly re-enqueue
+ if (task.scheduled >= 0)
+ {
+ if (task.fixed)
+ {
+ task.scheduled += task.period;
+ }
+ else
+ {
+ task.scheduled = task.period + System.currentTimeMillis();
+ }
+ queue.enqueue(task);
+ }
+ }
}
+ } // Scheduler
+
+ // Number of Timers created.
+ // Used for creating nice Thread names.
+ private static int nr = 0;
+
+ // The queue that all the tasks are put in.
+ // Given to the scheduler
+ private TaskQueue queue;
+
+ // The Scheduler that does all the real work
+ private Scheduler scheduler;
+
+ // Used to run the scheduler.
+ // Also used to checked if the Thread is still running by calling
+ // thread.isAlive(). Sometimes a Thread is suddenly killed by the system
+ // (if it belonged to an Applet).
+ private Thread thread;
+
+ // When cancelled we don't accept any more TimerTasks.
+ private boolean canceled;
+
+ /**
+ * Creates a new Timer with a non deamon Thread as Scheduler, with normal
+ * priority and a default name.
+ */
+ public Timer()
+ {
+ this(false);
+ }
+
+ /**
+ * Creates a new Timer with a deamon Thread as scheduler if deamon is true,
+ * with normal priority and a default name.
+ */
+ public Timer(boolean daemon)
+ {
+ this(daemon, Thread.NORM_PRIORITY);
+ }
+
+ /**
+ * Creates a new Timer with a deamon Thread as scheduler if deamon is true,
+ * with the priority given and a default name.
+ */
+ private Timer(boolean daemon, int priority)
+ {
+ this(daemon, priority, "Timer-" + (++nr));
+ }
+
+ /**
+ * Creates a new Timer with a deamon Thread as scheduler if deamon is true,
+ * with the priority and name given.E
+ */
+ private Timer(boolean daemon, int priority, String name)
+ {
+ canceled = false;
+ queue = new TaskQueue();
+ scheduler = new Scheduler(queue);
+ thread = new Thread(scheduler, name);
+ thread.setDaemon(daemon);
+ thread.setPriority(priority);
+ thread.start();
+ }
+
+ /**
+ * Cancels the execution of the scheduler. If a task is executing it will
+ * normally finish execution, but no other tasks will be executed and no
+ * more tasks can be scheduled.
+ */
+ public void cancel()
+ {
+ canceled = true;
+ queue.stop();
+ }
+
+ /**
+ * Schedules the task at Time time, repeating every period
+ * milliseconds if period is positive and at a fixed rate if fixed is true.
+ *
+ * @exception IllegalArgumentException if time is negative
+ * @exception IllegalStateException if the task was already scheduled or
+ * canceled or this Timer is canceled or the scheduler thread has died
+ */
+ private void schedule(TimerTask task, long time, long period, boolean fixed)
+ {
+ if (time < 0)
+ throw new IllegalArgumentException("negative time");
+
+ if (task.scheduled == 0 && task.lastExecutionTime == -1)
+ {
+ task.scheduled = time;
+ task.period = period;
+ task.fixed = fixed;
+ }
+ else
+ {
+ throw new IllegalStateException
+ ("task was already scheduled or canceled");
+ }
+
+ if (!this.canceled && this.thread != null)
+ {
+ queue.enqueue(task);
+ }
+ else
+ {
+ throw new IllegalStateException
+ ("timer was canceled or scheduler thread has died");
+ }
+ }
+
+ private static void positiveDelay(long delay)
+ {
+ if (delay < 0)
+ {
+ throw new IllegalArgumentException("delay is negative");
+ }
+ }
+
+ private static void positivePeriod(long period)
+ {
+ if (period < 0)
+ {
+ throw new IllegalArgumentException("period is negative");
+ }
+ }
+
+ /**
+ * Schedules the task at the specified data for one time execution.
+ *
+ * @exception IllegalArgumentException if date.getTime() is negative
+ * @exception IllegalStateException if the task was already scheduled or
+ * canceled or this Timer is canceled or the scheduler thread has died
+ */
+ public void schedule(TimerTask task, Date date)
+ {
+ long time = date.getTime();
+ schedule(task, time, -1, false);
+ }
+
+ /**
+ * Schedules the task at the specified date and reschedules the task every
+ * period milliseconds after the last execution of the task finishes until
+ * this timer or the task is canceled.
+ *
+ * @exception IllegalArgumentException if period or date.getTime() is
+ * negative
+ * @exception IllegalStateException if the task was already scheduled or
+ * canceled or this Timer is canceled or the scheduler thread has died
+ */
+ public void schedule(TimerTask task, Date date, long period)
+ {
+ positivePeriod(period);
+ long time = date.getTime();
+ schedule(task, time, period, false);
+ }
+
+ /**
+ * Schedules the task after the specified delay milliseconds for one time
+ * execution.
+ *
+ * @exception IllegalArgumentException if delay or
+ * System.currentTimeMillis + delay is negative
+ * @exception IllegalStateException if the task was already scheduled or
+ * canceled or this Timer is canceled or the scheduler thread has died
+ */
+ public void schedule(TimerTask task, long delay)
+ {
+ positiveDelay(delay);
+ long time = System.currentTimeMillis() + delay;
+ schedule(task, time, -1, false);
+ }
+
+ /**
+ * Schedules the task after the delay milliseconds and reschedules the
+ * task every period milliseconds after the last execution of the task
+ * finishes until this timer or the task is canceled.
+ *
+ * @exception IllegalArgumentException if delay or period is negative
+ * @exception IllegalStateException if the task was already scheduled or
+ * canceled or this Timer is canceled or the scheduler thread has died
+ */
+ public void schedule(TimerTask task, long delay, long period)
+ {
+ positiveDelay(delay);
+ positivePeriod(period);
+ long time = System.currentTimeMillis() + delay;
+ schedule(task, time, period, false);
+ }
+
+ /**
+ * Schedules the task at the specified date and reschedules the task at a
+ * fixed rate every period milliseconds until this timer or the task is
+ * canceled.
+ *
+ * @exception IllegalArgumentException if period or date.getTime() is
+ * negative
+ * @exception IllegalStateException if the task was already scheduled or
+ * canceled or this Timer is canceled or the scheduler thread has died
+ */
+ public void scheduleAtFixedRate(TimerTask task, Date date, long period)
+ {
+ positivePeriod(period);
+ long time = date.getTime();
+ schedule(task, time, period, true);
+ }
+
+ /**
+ * Schedules the task after the delay milliseconds and reschedules the task
+ * at a fixed rate every period milliseconds until this timer or the task
+ * is canceled.
+ *
+ * @exception IllegalArgumentException if delay or
+ * System.currentTimeMillis + delay is negative
+ * @exception IllegalStateException if the task was already scheduled or
+ * canceled or this Timer is canceled or the scheduler thread has died
+ */
+ public void scheduleAtFixedRate(TimerTask task, long delay, long period)
+ {
+ positiveDelay(delay);
+ positivePeriod(period);
+ long time = System.currentTimeMillis() + delay;
+ schedule(task, time, period, true);
+ }
+
+ /**
+ * Tells the scheduler that the Timer task died
+ * so there will be no more new tasks scheduled.
+ */
+ protected void finalize()
+ {
+ queue.setNullOnEmpty(true);
+ }
}