diff options
Diffstat (limited to 'libjava/java/util/Timer.java')
-rw-r--r-- | libjava/java/util/Timer.java | 615 |
1 files changed, 0 insertions, 615 deletions
diff --git a/libjava/java/util/Timer.java b/libjava/java/util/Timer.java deleted file mode 100644 index 715f06c..0000000 --- a/libjava/java/util/Timer.java +++ /dev/null @@ -1,615 +0,0 @@ -/* Timer.java -- Timer that runs TimerTasks at a later time. - Copyright (C) 2000, 2001 Free Software Foundation, Inc. - -This file is part of GNU Classpath. - -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 -General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU Classpath; see the file COPYING. If not, write to the -Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -02110-1301 USA. - -Linking this library statically or dynamically with other modules is -making a combined work based on this library. Thus, the terms and -conditions of the GNU General Public License cover the whole -combination. - -As a special exception, the copyright holders of this library give you -permission to link this library with independent modules to produce an -executable, regardless of the license terms of these independent -modules, and to copy and distribute the resulting executable under -terms of your choice, provided that you also meet, for each linked -independent module, the terms and conditions of the license of that -module. An independent module is a module which is not derived from -or based on this library. If you modify this library, you may extend -this exception to your version of the library, but you are not -obligated to do so. If you do not wish to do so, delete this -exception statement from your version. */ - -package java.util; - -/** - * Timer that can run TimerTasks at a later time. - * TimerTasks can be scheduled for one time execution at some time in the - * future. They can be scheduled to be rescheduled at a time period after the - * task was last executed. Or they can be scheduled to be executed repeatedly - * at a fixed rate. - * <p> - * The normal scheduling will result in a more or less even delay in time - * between successive executions, but the executions could drift in time if - * the task (or other tasks) takes a long time to execute. Fixed delay - * scheduling guarantees more or less that the task will be executed at a - * specific time, but if there is ever a delay in execution then the period - * between successive executions will be shorter. The first method of - * repeated scheduling is preferred for repeated tasks in response to user - * interaction, the second method of repeated scheduling is preferred for tasks - * that act like alarms. - * <p> - * The Timer keeps a binary heap as a task priority queue which means that - * scheduling and serving of a task in a queue of n tasks costs O(log n). - * - * @see TimerTask - * @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 static final int DEFAULT_SIZE = 32; - - /** Whether 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); - heap = new_heap; - } - } - - /** - * 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.elements = 0; - this.notify(); - } - - } // 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; - - /** - * 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 (ThreadDeath death) - { - // If an exception escapes, the Timer becomes invalid. - queue.stop(); - throw death; - } - catch (Throwable t) - { - // If an exception escapes, the Timer becomes invalid. - queue.stop(); - } - } - - // 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(); - } - - try - { - queue.enqueue(task); - } - catch (IllegalStateException ise) - { - // Ignore. Apparently the Timer queue has been stopped. - } - } - } - } - } // Scheduler - - // Number of Timers created. - // Used for creating nice Thread names. - private static int nr; - - // 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 daemon Thread as Scheduler, with normal - * priority and a default name. - */ - public Timer() - { - this(false); - } - - /** - * Creates a new Timer with a daemon Thread as scheduler if daemon is true, - * with normal priority and a default name. - */ - public Timer(boolean daemon) - { - this(daemon, Thread.NORM_PRIORITY); - } - - /** - * Creates a new Timer with a daemon Thread as scheduler if daemon 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 daemon Thread as scheduler if daemon 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() throws Throwable - { - queue.setNullOnEmpty(true); - } -} |