KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > javax > swing > TimerQueue


1 /*
2  * @(#)TimerQueue.java 1.38 06/08/16
3  *
4  * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
5  * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
6  */

7
8
9
10 package javax.swing;
11
12
13
14 import java.util.*;
15 import sun.awt.AppContext;
16
17
18
19 /**
20  * Internal class to manage all Timers using one thread.
21  * TimerQueue manages a queue of Timers. The Timers are chained
22  * together in a linked list sorted by the order in which they will expire.
23  *
24  * @version 1.38 08/16/06
25  * @author Dave Moore
26  */

27 class TimerQueue implements Runnable JavaDoc
28 {
29     private static final Object JavaDoc sharedInstanceKey =
30         new StringBuffer JavaDoc("TimerQueue.sharedInstanceKey");
31     private static final Object JavaDoc expiredTimersKey =
32         new StringBuffer JavaDoc("TimerQueue.expiredTimersKey");
33
34     Timer JavaDoc firstTimer;
35     boolean running;
36
37     /* Lock object used in place of class object for synchronization.
38      * (4187686)
39      */

40     private static final Object JavaDoc classLock = new Object JavaDoc();
41
42
43     /**
44      * Constructor for TimerQueue.
45      */

46     public TimerQueue() {
47         super();
48
49         // Now start the TimerQueue thread.
50
start();
51     }
52
53
54     public static TimerQueue JavaDoc sharedInstance() {
55         synchronized (classLock) {
56             TimerQueue JavaDoc sharedInst = (TimerQueue JavaDoc)
57                                     SwingUtilities.appContextGet(
58                                                         sharedInstanceKey);
59             if (sharedInst == null) {
60                 sharedInst = new TimerQueue JavaDoc();
61                 SwingUtilities.appContextPut(sharedInstanceKey, sharedInst);
62             }
63             return sharedInst;
64         }
65     }
66
67
68     synchronized void start() {
69         if (running) {
70             throw new RuntimeException JavaDoc("Can't start a TimerQueue " +
71                                        "that is already running");
72         }
73         else {
74             final ThreadGroup JavaDoc threadGroup =
75                 AppContext.getAppContext().getThreadGroup();
76             java.security.AccessController.doPrivileged(
77                 new java.security.PrivilegedAction JavaDoc() {
78                 public Object JavaDoc run() {
79                     Thread JavaDoc timerThread = new Thread JavaDoc(threadGroup, TimerQueue.this,
80                                                     "TimerQueue");
81                     timerThread.setDaemon(true);
82                     timerThread.setPriority(Thread.NORM_PRIORITY);
83                     timerThread.start();
84                     return null;
85                 }
86             });
87             running = true;
88         }
89     }
90
91
92     synchronized void stop() {
93         running = false;
94         notify();
95     }
96
97
98     synchronized void addTimer(Timer JavaDoc timer, long expirationTime) {
99         Timer JavaDoc previousTimer;
100         Timer JavaDoc nextTimer;
101
102         // If the Timer is already in the queue, then ignore the add.
103
if (timer.running) {
104             return;
105         }
106
107         previousTimer = null;
108         nextTimer = firstTimer;
109
110         // Insert the Timer into the linked list in the order they will
111
// expire. If two timers expire at the same time, put the newer entry
112
// later so they expire in the order they came in.
113

114         while (nextTimer != null) {
115             if (nextTimer.expirationTime > expirationTime) break;
116
117             previousTimer = nextTimer;
118             nextTimer = nextTimer.nextTimer;
119         }
120
121         if (previousTimer == null) {
122             firstTimer = timer;
123         }
124         else {
125             previousTimer.nextTimer = timer;
126         }
127
128         timer.expirationTime = expirationTime;
129         timer.nextTimer = nextTimer;
130         timer.running = true;
131         notify();
132     }
133
134
135     synchronized void removeTimer(Timer JavaDoc timer) {
136         Timer JavaDoc previousTimer;
137         Timer JavaDoc nextTimer;
138         boolean found;
139
140         if (!timer.running) return;
141
142         previousTimer = null;
143         nextTimer = firstTimer;
144         found = false;
145
146         while (nextTimer != null) {
147             if (nextTimer == timer) {
148                 found = true;
149                 break;
150             }
151
152             previousTimer = nextTimer;
153             nextTimer = nextTimer.nextTimer;
154         }
155
156         if (!found) return;
157
158         if (previousTimer == null) {
159             firstTimer = timer.nextTimer;
160         }
161         else {
162             previousTimer.nextTimer = timer.nextTimer;
163         }
164
165         timer.expirationTime = 0;
166         timer.nextTimer = null;
167         timer.running = false;
168     }
169
170
171     synchronized boolean containsTimer(Timer JavaDoc timer) {
172         return timer.running;
173     }
174
175
176     /**
177      * If there are a ton of timers, this method may never return. It loops
178      * checking to see if the head of the Timer list has expired. If it has,
179      * it posts the Timer and reschedules it if necessary.
180      */

181     synchronized long postExpiredTimers() {
182         Timer JavaDoc timer;
183         long currentTime;
184         long timeToWait;
185
186         // The timeToWait we return should never be negative and only be zero
187
// when we have no Timers to wait for.
188

189         do {
190             timer = firstTimer;
191             if (timer == null) return 0;
192
193             currentTime = System.currentTimeMillis();
194             timeToWait = timer.expirationTime - currentTime;
195
196             if (timeToWait <= 0) {
197                 try {
198                     timer.post(); // have timer post an event
199
}
200                 catch (SecurityException JavaDoc e) {
201                 }
202
203                 // Remove the timer from the queue
204
removeTimer(timer);
205
206                 // This tries to keep the interval uniform at
207
// the cost of drift.
208
if (timer.isRepeats()) {
209                     addTimer(timer, currentTime + timer.getDelay());
210                 }
211
212                 // Allow other threads to call addTimer() and removeTimer()
213
// even when we are posting Timers like mad. Since the wait()
214
// releases the lock, be sure not to maintain any state
215
// between iterations of the loop.
216

217                 try {
218                     wait(1);
219                 }
220                 catch (InterruptedException JavaDoc e) {
221                 }
222             }
223         } while (timeToWait <= 0);
224
225         return timeToWait;
226     }
227
228
229     public synchronized void run() {
230         long timeToWait;
231
232         try {
233             while (running) {
234                 timeToWait = postExpiredTimers();
235                 try {
236                     wait(timeToWait);
237                 }
238                 catch (InterruptedException JavaDoc e) {
239                 }
240             }
241         }
242         catch (ThreadDeath JavaDoc td) {
243             running = false;
244             // Mark all the timers we contain as not being queued.
245
Timer JavaDoc timer = firstTimer;
246             while (timer != null) {
247                 timer.cancelEvent();
248                 timer = timer.nextTimer;
249             }
250             SystemEventQueueUtilities.restartTimerQueueThread();
251             throw td;
252         }
253     }
254
255
256     public synchronized String JavaDoc toString() {
257         StringBuffer JavaDoc buf;
258         Timer JavaDoc nextTimer;
259
260         buf = new StringBuffer JavaDoc();
261         buf.append("TimerQueue (");
262
263         nextTimer = firstTimer;
264         while (nextTimer != null) {
265             buf.append(nextTimer.toString());
266
267             nextTimer = nextTimer.nextTimer;
268             if (nextTimer != null) buf.append(", ");
269         }
270
271         buf.append(")");
272         return buf.toString();
273     }
274 }
275
Popular Tags