- /*
 - * @(#)TimerQueue.java 1.30 00/04/04
 - *
 - * Copyright 1997-2000 Sun Microsystems, Inc. All Rights Reserved.
 - *
 - * This software is the proprietary information of Sun Microsystems, Inc.
 - * Use is subject to license terms.
 - *
 - */
 - package javax.swing;
 - import java.util.*;
 - /**
 - * Internal class to manage all Timers using one thread.
 - * TimerQueue manages a queue of Timers. The Timers are chained
 - * together in a linked list sorted by the order in which they will expire.
 - *
 - * @version 1.30 04/04/00
 - * @author Dave Moore
 - */
 - class TimerQueue implements Runnable
 - {
 - private static final Object sharedInstanceKey =
 - new StringBuffer("TimerQueue.sharedInstanceKey");
 - private static final Object expiredTimersKey =
 - new StringBuffer("TimerQueue.expiredTimersKey");
 - Timer firstTimer;
 - boolean running;
 - /* Lock object used in place of class object for synchronization.
 - * (4187686)
 - */
 - private static final Object classLock = new Object();
 - /**
 - * Constructor for TimerQueue.
 - */
 - public TimerQueue() {
 - super();
 - // Now start the TimerQueue thread.
 - start();
 - }
 - public static TimerQueue sharedInstance() {
 - synchronized (classLock) {
 - TimerQueue sharedInst = (TimerQueue)
 - SwingUtilities.appContextGet(
 - sharedInstanceKey);
 - if (sharedInst == null) {
 - sharedInst = new TimerQueue();
 - SwingUtilities.appContextPut(sharedInstanceKey, sharedInst);
 - }
 - return sharedInst;
 - }
 - }
 - synchronized void start() {
 - if (running) {
 - throw new RuntimeException("Can't start a TimerQueue " +
 - "that is already running");
 - }
 - else {
 - Thread timerThread = new Thread(this, "TimerQueue");
 - try {
 - timerThread.setDaemon(true);
 - }
 - catch (SecurityException e) {
 - }
 - timerThread.setPriority(Thread.NORM_PRIORITY);
 - timerThread.start();
 - running = true;
 - }
 - }
 - synchronized void stop() {
 - running = false;
 - notify();
 - }
 - synchronized void addTimer(Timer timer, long expirationTime) {
 - Timer previousTimer;
 - Timer nextTimer;
 - // If the Timer is already in the queue, then ignore the add.
 - if (timer.running) {
 - return;
 - }
 - previousTimer = null;
 - nextTimer = firstTimer;
 - // Insert the Timer into the linked list in the order they will
 - // expire. If two timers expire at the same time, put the newer entry
 - // later so they expire in the order they came in.
 - while (nextTimer != null) {
 - if (nextTimer.expirationTime > expirationTime) break;
 - previousTimer = nextTimer;
 - nextTimer = nextTimer.nextTimer;
 - }
 - if (previousTimer == null) {
 - firstTimer = timer;
 - }
 - else {
 - previousTimer.nextTimer = timer;
 - }
 - timer.expirationTime = expirationTime;
 - timer.nextTimer = nextTimer;
 - timer.running = true;
 - notify();
 - }
 - synchronized void removeTimer(Timer timer) {
 - Timer previousTimer;
 - Timer nextTimer;
 - boolean found;
 - if (!timer.running) return;
 - previousTimer = null;
 - nextTimer = firstTimer;
 - found = false;
 - while (nextTimer != null) {
 - if (nextTimer == timer) {
 - found = true;
 - break;
 - }
 - previousTimer = nextTimer;
 - nextTimer = nextTimer.nextTimer;
 - }
 - if (!found) return;
 - if (previousTimer == null) {
 - firstTimer = timer.nextTimer;
 - }
 - else {
 - previousTimer.nextTimer = timer.nextTimer;
 - }
 - timer.expirationTime = 0;
 - timer.nextTimer = null;
 - timer.running = false;
 - }
 - synchronized boolean containsTimer(Timer timer) {
 - return timer.running;
 - }
 - /**
 - * If there are a ton of timers, this method may never return. It loops
 - * checking to see if the head of the Timer list has expired. If it has,
 - * it posts the Timer and reschedules it if necessary.
 - */
 - synchronized long postExpiredTimers() {
 - Timer timer;
 - long currentTime;
 - long timeToWait;
 - // The timeToWait we return should never be negative and only be zero
 - // when we have no Timers to wait for.
 - do {
 - timer = firstTimer;
 - if (timer == null) return 0;
 - currentTime = System.currentTimeMillis();
 - timeToWait = timer.expirationTime - currentTime;
 - if (timeToWait <= 0) {
 - try {
 - timer.post(); // have timer post an event
 - }
 - catch (SecurityException e) {
 - }
 - // Remove the timer from the queue
 - removeTimer(timer);
 - // This tries to keep the interval uniform at
 - // the cost of drift.
 - if (timer.isRepeats()) {
 - addTimer(timer, currentTime + timer.getDelay());
 - }
 - }
 - // Allow other threads to call addTimer() and removeTimer()
 - // even when we are posting Timers like mad. Since the wait()
 - // releases the lock, be sure not to maintain any state
 - // between iterations of the loop.
 - try {
 - wait(1);
 - }
 - catch (InterruptedException e) {
 - }
 - } while (timeToWait <= 0);
 - return timeToWait;
 - }
 - public synchronized void run() {
 - long timeToWait;
 - try {
 - while (running) {
 - timeToWait = postExpiredTimers();
 - try {
 - wait(timeToWait);
 - }
 - catch (InterruptedException e) {
 - }
 - }
 - }
 - catch (ThreadDeath td) {
 - running = false;
 - // Mark all the timers we contain as not being queued.
 - Timer timer = firstTimer;
 - while (timer != null) {
 - timer.eventQueued = false;
 - timer = timer.nextTimer;
 - }
 - SystemEventQueueUtilities.restartTimerQueueThread();
 - throw td;
 - }
 - }
 - public synchronized String toString() {
 - StringBuffer buf;
 - Timer nextTimer;
 - buf = new StringBuffer();
 - buf.append("TimerQueue (");
 - nextTimer = firstTimer;
 - while (nextTimer != null) {
 - buf.append(nextTimer.toString());
 - nextTimer = nextTimer.nextTimer;
 - if (nextTimer != null) buf.append(", ");
 - }
 - buf.append(")");
 - return buf.toString();
 - }
 - }