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+
28+package javax.swing;
29+
30+
31+
32+import java.util.*;
33+import java.util.concurrent.*;
34+import java.util.concurrent.locks.*;
35+import java.util.concurrent.atomic.AtomicLong;
36+import 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+ */
48+class 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+}