History

My first initial commit with all of mine experimental changes.

Dmitry Kabak (userdima committed 13 years ago

Commit d37b88d1 parent 3f5b46618352 files · +2598093 −-8690Browse files

Showing the changes to java/pkg/javax/swing/TimerQueue.java (1 of 18352 files). Show all

Unified · Split

java/pkg/javax/swing/TimerQueue.java+298−0
@@ -0,0 +1,298 @@
1/*
2 * Copyright (c) 1997, 2009, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26
27
28package javax.swing;
29
30
31
32import java.util.*;
33import java.util.concurrent.*;
34import java.util.concurrent.locks.*;
35import java.util.concurrent.atomic.AtomicLong;
36import sun.awt.AppContext;
37
38
39
40/**
41 * Internal class to manage all Timers using one thread.
42 * TimerQueue manages a queue of Timers. The Timers are chained
43 * together in a linked list sorted by the order in which they will expire.
44 *
45 * @author Dave Moore
46 * @author Igor Kushnirskiy
47 */
48class TimerQueue implements Runnable
49{
50 private static final Object sharedInstanceKey =
51 new StringBuffer("TimerQueue.sharedInstanceKey");
52 private static final Object expiredTimersKey =
53 new StringBuffer("TimerQueue.expiredTimersKey");
54
55 private final DelayQueue<DelayedTimer> queue;
56 private volatile boolean running;
57 private final Lock runningLock;
58
59 /* Lock object used in place of class object for synchronization.
60 * (4187686)
61 */
62 private static final Object classLock = new Object();
63
64 /** Base of nanosecond timings, to avoid wrapping */
65 private static final long NANO_ORIGIN = System.nanoTime();
66
67 /**
68 * Constructor for TimerQueue.
69 */
70 public TimerQueue() {
71 super();
72 queue = new DelayQueue<DelayedTimer>();
73 // Now start the TimerQueue thread.
74 runningLock = new ReentrantLock();
75 startIfNeeded();
76 }
77
78
79 public static TimerQueue sharedInstance() {
80 synchronized (classLock) {
81 TimerQueue sharedInst = (TimerQueue)
82 SwingUtilities.appContextGet(
83 sharedInstanceKey);
84 if (sharedInst == null) {
85 sharedInst = new TimerQueue();
86 SwingUtilities.appContextPut(sharedInstanceKey, sharedInst);
87 }
88 return sharedInst;
89 }
90 }
91
92
93 void startIfNeeded() {
94 if (! running) {
95 runningLock.lock();
96 try {
97 final ThreadGroup threadGroup =
98 AppContext.getAppContext().getThreadGroup();
99 java.security.AccessController.doPrivileged(
100 new java.security.PrivilegedAction<Object>() {
101 public Object run() {
102 Thread timerThread = new Thread(threadGroup, TimerQueue.this,
103 "TimerQueue");
104 timerThread.setDaemon(true);
105 timerThread.setPriority(Thread.NORM_PRIORITY);
106 timerThread.start();
107 return null;
108 }
109 });
110 running = true;
111 } finally {
112 runningLock.unlock();
113 }
114 }
115 }
116
117 void addTimer(Timer timer, long delayMillis) {
118 timer.getLock().lock();
119 try {
120 // If the Timer is already in the queue, then ignore the add.
121 if (! containsTimer(timer)) {
122 addTimer(new DelayedTimer(timer,
123 TimeUnit.MILLISECONDS.toNanos(delayMillis)
124 + now()));
125 }
126 } finally {
127 timer.getLock().unlock();
128 }
129 }
130
131 private void addTimer(DelayedTimer delayedTimer) {
132 assert delayedTimer != null && ! containsTimer(delayedTimer.getTimer());
133
134 Timer timer = delayedTimer.getTimer();
135 timer.getLock().lock();
136 try {
137 timer.delayedTimer = delayedTimer;
138 queue.add(delayedTimer);
139 } finally {
140 timer.getLock().unlock();
141 }
142 }
143
144 void removeTimer(Timer timer) {
145 timer.getLock().lock();
146 try {
147 if (timer.delayedTimer != null) {
148 queue.remove(timer.delayedTimer);
149 timer.delayedTimer = null;
150 }
151 } finally {
152 timer.getLock().unlock();
153 }
154 }
155
156 boolean containsTimer(Timer timer) {
157 timer.getLock().lock();
158 try {
159 return timer.delayedTimer != null;
160 } finally {
161 timer.getLock().unlock();
162 }
163 }
164
165
166 public void run() {
167 runningLock.lock();
168 try {
169 while (running) {
170 try {
171 Timer timer = queue.take().getTimer();
172 timer.getLock().lock();
173 try {
174 DelayedTimer delayedTimer = timer.delayedTimer;
175 if (delayedTimer != null) {
176 /*
177 * Timer is not removed after we get it from
178 * the queue and before the lock on the timer is
179 * acquired
180 */
181 timer.post(); // have timer post an event
182 timer.delayedTimer = null;
183 if (timer.isRepeats()) {
184 delayedTimer.setTime(now()
185 + TimeUnit.MILLISECONDS.toNanos(
186 timer.getDelay()));
187 addTimer(delayedTimer);
188 }
189 }
190 } catch (SecurityException ignore) {
191 } finally {
192 timer.getLock().unlock();
193 }
194 } catch (InterruptedException ie) {
195 // Shouldn't ignore InterruptedExceptions here, so AppContext
196 // is disposed gracefully, see 6799345 for details
197 if (AppContext.getAppContext().isDisposed()) {
198 break;
199 }
200 }
201 }
202 }
203 catch (ThreadDeath td) {
204 // Mark all the timers we contain as not being queued.
205 for (DelayedTimer delayedTimer : queue) {
206 delayedTimer.getTimer().cancelEvent();
207 }
208 throw td;
209 } finally {
210 running = false;
211 runningLock.unlock();
212 }
213 }
214
215
216 public String toString() {
217 StringBuilder buf = new StringBuilder();
218 buf.append("TimerQueue (");
219 boolean isFirst = true;
220 for (DelayedTimer delayedTimer : queue) {
221 if (! isFirst) {
222 buf.append(", ");
223 }
224 buf.append(delayedTimer.getTimer().toString());
225 isFirst = false;
226 }
227 buf.append(")");
228 return buf.toString();
229 }
230
231 /**
232 * Returns nanosecond time offset by origin
233 */
234 private static long now() {
235 return System.nanoTime() - NANO_ORIGIN;
236 }
237
238 static class DelayedTimer implements Delayed {
239 // most of it copied from
240 // java.util.concurrent.ScheduledThreadPoolExecutor
241
242 /**
243 * Sequence number to break scheduling ties, and in turn to
244 * guarantee FIFO order among tied entries.
245 */
246 private static final AtomicLong sequencer = new AtomicLong(0);
247
248 /** Sequence number to break ties FIFO */
249 private final long sequenceNumber;
250
251
252 /** The time the task is enabled to execute in nanoTime units */
253 private volatile long time;
254
255 private final Timer timer;
256
257 DelayedTimer(Timer timer, long nanos) {
258 this.timer = timer;
259 time = nanos;
260 sequenceNumber = sequencer.getAndIncrement();
261 }
262
263
264 final public long getDelay(TimeUnit unit) {
265 return unit.convert(time - now(), TimeUnit.NANOSECONDS);
266 }
267
268 final void setTime(long nanos) {
269 time = nanos;
270 }
271
272 final Timer getTimer() {
273 return timer;
274 }
275
276 public int compareTo(Delayed other) {
277 if (other == this) { // compare zero ONLY if same object
278 return 0;
279 }
280 if (other instanceof DelayedTimer) {
281 DelayedTimer x = (DelayedTimer)other;
282 long diff = time - x.time;
283 if (diff < 0) {
284 return -1;
285 } else if (diff > 0) {
286 return 1;
287 } else if (sequenceNumber < x.sequenceNumber) {
288 return -1;
289 } else {
290 return 1;
291 }
292 }
293 long d = (getDelay(TimeUnit.NANOSECONDS) -
294 other.getDelay(TimeUnit.NANOSECONDS));
295 return (d == 0) ? 0 : ((d < 0) ? -1 : 1);
296 }
297 }
298}