91 *
92 * @param dispatchThread An event dispatch thread that
93 * should not stop dispatching events while waiting
94 * @param extCondition A conditional object used to determine
95 * if the loop should be terminated
96 *
97 * @since 1.7
98 */
99 public WaitDispatchSupport(EventDispatchThread dispatchThread,
100 Conditional extCond)
101 {
102 if (dispatchThread == null) {
103 throw new IllegalArgumentException("The dispatchThread can not be null");
104 }
105
106 this.dispatchThread = dispatchThread;
107 this.extCondition = extCond;
108 this.condition = new Conditional() {
109 @Override
110 public boolean evaluate() {
111 if (log.isLoggable(PlatformLogger.FINEST)) {
112 log.finest("evaluate(): blockingEDT=" + keepBlockingEDT.get() +
113 ", blockingCT=" + keepBlockingCT.get());
114 }
115 boolean extEvaluate =
116 (extCondition != null) ? extCondition.evaluate() : true;
117 if (!keepBlockingEDT.get() || !extEvaluate) {
118 if (timerTask != null) {
119 timerTask.cancel();
120 timerTask = null;
121 }
122 return false;
123 }
124 return true;
125 }
126 };
127 }
128
129 /**
130 * Creates a {@code WaitDispatchSupport} instance to
131 * serve the given event dispatch thread.
148 public WaitDispatchSupport(EventDispatchThread dispatchThread,
149 Conditional extCondition,
150 EventFilter filter, long interval)
151 {
152 this(dispatchThread, extCondition);
153 this.filter = filter;
154 if (interval < 0) {
155 throw new IllegalArgumentException("The interval value must be >= 0");
156 }
157 this.interval = interval;
158 if (interval != 0) {
159 initializeTimer();
160 }
161 }
162
163 /**
164 * @inheritDoc
165 */
166 @Override
167 public boolean enter() {
168 if (log.isLoggable(PlatformLogger.FINE)) {
169 log.fine("enter(): blockingEDT=" + keepBlockingEDT.get() +
170 ", blockingCT=" + keepBlockingCT.get());
171 }
172
173 if (!keepBlockingEDT.compareAndSet(false, true)) {
174 log.fine("The secondary loop is already running, aborting");
175 return false;
176 }
177
178 final Runnable run = new Runnable() {
179 public void run() {
180 log.fine("Starting a new event pump");
181 if (filter == null) {
182 dispatchThread.pumpEvents(condition);
183 } else {
184 dispatchThread.pumpEventsForFilter(condition, filter);
185 }
186 }
187 };
188
189 // We have two mechanisms for blocking: if we're on the
190 // dispatch thread, start a new event pump; if we're
191 // on any other thread, call wait() on the treelock
192
193 Thread currentThread = Thread.currentThread();
194 if (currentThread == dispatchThread) {
195 if (log.isLoggable(PlatformLogger.FINEST)) {
196 log.finest("On dispatch thread: " + dispatchThread);
197 }
198 if (interval != 0) {
199 if (log.isLoggable(PlatformLogger.FINEST)) {
200 log.finest("scheduling the timer for " + interval + " ms");
201 }
202 timer.schedule(timerTask = new TimerTask() {
203 @Override
204 public void run() {
205 if (keepBlockingEDT.compareAndSet(true, false)) {
206 wakeupEDT();
207 }
208 }
209 }, interval);
210 }
211 // Dispose SequencedEvent we are dispatching on the the current
212 // AppContext, to prevent us from hang - see 4531693 for details
213 SequencedEvent currentSE = KeyboardFocusManager.
214 getCurrentKeyboardFocusManager().getCurrentSequencedEvent();
215 if (currentSE != null) {
216 if (log.isLoggable(PlatformLogger.FINE)) {
217 log.fine("Dispose current SequencedEvent: " + currentSE);
218 }
219 currentSE.dispose();
220 }
221 // In case the exit() method is called before starting
222 // new event pump it will post the waking event to EDT.
223 // The event will be handled after the the new event pump
224 // starts. Thus, the enter() method will not hang.
225 //
226 // Event pump should be privileged. See 6300270.
227 AccessController.doPrivileged(new PrivilegedAction() {
228 public Object run() {
229 run.run();
230 return null;
231 }
232 });
233 } else {
234 if (log.isLoggable(PlatformLogger.FINEST)) {
235 log.finest("On non-dispatch thread: " + currentThread);
236 }
237 synchronized (getTreeLock()) {
238 if (filter != null) {
239 dispatchThread.addEventFilter(filter);
240 }
241 try {
242 EventQueue eq = dispatchThread.getEventQueue();
243 eq.postEvent(new PeerEvent(this, run, PeerEvent.PRIORITY_EVENT));
244 keepBlockingCT.set(true);
245 if (interval > 0) {
246 long currTime = System.currentTimeMillis();
247 while (keepBlockingCT.get() &&
248 ((extCondition != null) ? extCondition.evaluate() : true) &&
249 (currTime + interval > System.currentTimeMillis()))
250 {
251 getTreeLock().wait(interval);
252 }
253 } else {
254 while (keepBlockingCT.get() &&
255 ((extCondition != null) ? extCondition.evaluate() : true))
256 {
257 getTreeLock().wait();
258 }
259 }
260 if (log.isLoggable(PlatformLogger.FINE)) {
261 log.fine("waitDone " + keepBlockingEDT.get() + " " + keepBlockingCT.get());
262 }
263 } catch (InterruptedException e) {
264 if (log.isLoggable(PlatformLogger.FINE)) {
265 log.fine("Exception caught while waiting: " + e);
266 }
267 } finally {
268 if (filter != null) {
269 dispatchThread.removeEventFilter(filter);
270 }
271 }
272 // If the waiting process has been stopped because of the
273 // time interval passed or an exception occurred, the state
274 // should be changed
275 keepBlockingEDT.set(false);
276 keepBlockingCT.set(false);
277 }
278 }
279
280 return true;
281 }
282
283 /**
284 * @inheritDoc
285 */
286 public boolean exit() {
287 if (log.isLoggable(PlatformLogger.FINE)) {
288 log.fine("exit(): blockingEDT=" + keepBlockingEDT.get() +
289 ", blockingCT=" + keepBlockingCT.get());
290 }
291 if (keepBlockingEDT.compareAndSet(true, false)) {
292 wakeupEDT();
293 return true;
294 }
295 return false;
296 }
297
298 private final static Object getTreeLock() {
299 return Component.LOCK;
300 }
301
302 private final Runnable wakingRunnable = new Runnable() {
303 public void run() {
304 log.fine("Wake up EDT");
305 synchronized (getTreeLock()) {
306 keepBlockingCT.set(false);
307 getTreeLock().notifyAll();
308 }
309 log.fine("Wake up EDT done");
310 }
311 };
312
313 private void wakeupEDT() {
314 if (log.isLoggable(PlatformLogger.FINEST)) {
315 log.finest("wakeupEDT(): EDT == " + dispatchThread);
316 }
317 EventQueue eq = dispatchThread.getEventQueue();
318 eq.postEvent(new PeerEvent(this, wakingRunnable, PeerEvent.PRIORITY_EVENT));
319 }
320 }
|
91 *
92 * @param dispatchThread An event dispatch thread that
93 * should not stop dispatching events while waiting
94 * @param extCondition A conditional object used to determine
95 * if the loop should be terminated
96 *
97 * @since 1.7
98 */
99 public WaitDispatchSupport(EventDispatchThread dispatchThread,
100 Conditional extCond)
101 {
102 if (dispatchThread == null) {
103 throw new IllegalArgumentException("The dispatchThread can not be null");
104 }
105
106 this.dispatchThread = dispatchThread;
107 this.extCondition = extCond;
108 this.condition = new Conditional() {
109 @Override
110 public boolean evaluate() {
111 if (log.isLoggable(PlatformLogger.Level.FINEST)) {
112 log.finest("evaluate(): blockingEDT=" + keepBlockingEDT.get() +
113 ", blockingCT=" + keepBlockingCT.get());
114 }
115 boolean extEvaluate =
116 (extCondition != null) ? extCondition.evaluate() : true;
117 if (!keepBlockingEDT.get() || !extEvaluate) {
118 if (timerTask != null) {
119 timerTask.cancel();
120 timerTask = null;
121 }
122 return false;
123 }
124 return true;
125 }
126 };
127 }
128
129 /**
130 * Creates a {@code WaitDispatchSupport} instance to
131 * serve the given event dispatch thread.
148 public WaitDispatchSupport(EventDispatchThread dispatchThread,
149 Conditional extCondition,
150 EventFilter filter, long interval)
151 {
152 this(dispatchThread, extCondition);
153 this.filter = filter;
154 if (interval < 0) {
155 throw new IllegalArgumentException("The interval value must be >= 0");
156 }
157 this.interval = interval;
158 if (interval != 0) {
159 initializeTimer();
160 }
161 }
162
163 /**
164 * @inheritDoc
165 */
166 @Override
167 public boolean enter() {
168 if (log.isLoggable(PlatformLogger.Level.FINE)) {
169 log.fine("enter(): blockingEDT=" + keepBlockingEDT.get() +
170 ", blockingCT=" + keepBlockingCT.get());
171 }
172
173 if (!keepBlockingEDT.compareAndSet(false, true)) {
174 log.fine("The secondary loop is already running, aborting");
175 return false;
176 }
177
178 final Runnable run = new Runnable() {
179 public void run() {
180 log.fine("Starting a new event pump");
181 if (filter == null) {
182 dispatchThread.pumpEvents(condition);
183 } else {
184 dispatchThread.pumpEventsForFilter(condition, filter);
185 }
186 }
187 };
188
189 // We have two mechanisms for blocking: if we're on the
190 // dispatch thread, start a new event pump; if we're
191 // on any other thread, call wait() on the treelock
192
193 Thread currentThread = Thread.currentThread();
194 if (currentThread == dispatchThread) {
195 if (log.isLoggable(PlatformLogger.Level.FINEST)) {
196 log.finest("On dispatch thread: " + dispatchThread);
197 }
198 if (interval != 0) {
199 if (log.isLoggable(PlatformLogger.Level.FINEST)) {
200 log.finest("scheduling the timer for " + interval + " ms");
201 }
202 timer.schedule(timerTask = new TimerTask() {
203 @Override
204 public void run() {
205 if (keepBlockingEDT.compareAndSet(true, false)) {
206 wakeupEDT();
207 }
208 }
209 }, interval);
210 }
211 // Dispose SequencedEvent we are dispatching on the the current
212 // AppContext, to prevent us from hang - see 4531693 for details
213 SequencedEvent currentSE = KeyboardFocusManager.
214 getCurrentKeyboardFocusManager().getCurrentSequencedEvent();
215 if (currentSE != null) {
216 if (log.isLoggable(PlatformLogger.Level.FINE)) {
217 log.fine("Dispose current SequencedEvent: " + currentSE);
218 }
219 currentSE.dispose();
220 }
221 // In case the exit() method is called before starting
222 // new event pump it will post the waking event to EDT.
223 // The event will be handled after the the new event pump
224 // starts. Thus, the enter() method will not hang.
225 //
226 // Event pump should be privileged. See 6300270.
227 AccessController.doPrivileged(new PrivilegedAction() {
228 public Object run() {
229 run.run();
230 return null;
231 }
232 });
233 } else {
234 if (log.isLoggable(PlatformLogger.Level.FINEST)) {
235 log.finest("On non-dispatch thread: " + currentThread);
236 }
237 synchronized (getTreeLock()) {
238 if (filter != null) {
239 dispatchThread.addEventFilter(filter);
240 }
241 try {
242 EventQueue eq = dispatchThread.getEventQueue();
243 eq.postEvent(new PeerEvent(this, run, PeerEvent.PRIORITY_EVENT));
244 keepBlockingCT.set(true);
245 if (interval > 0) {
246 long currTime = System.currentTimeMillis();
247 while (keepBlockingCT.get() &&
248 ((extCondition != null) ? extCondition.evaluate() : true) &&
249 (currTime + interval > System.currentTimeMillis()))
250 {
251 getTreeLock().wait(interval);
252 }
253 } else {
254 while (keepBlockingCT.get() &&
255 ((extCondition != null) ? extCondition.evaluate() : true))
256 {
257 getTreeLock().wait();
258 }
259 }
260 if (log.isLoggable(PlatformLogger.Level.FINE)) {
261 log.fine("waitDone " + keepBlockingEDT.get() + " " + keepBlockingCT.get());
262 }
263 } catch (InterruptedException e) {
264 if (log.isLoggable(PlatformLogger.Level.FINE)) {
265 log.fine("Exception caught while waiting: " + e);
266 }
267 } finally {
268 if (filter != null) {
269 dispatchThread.removeEventFilter(filter);
270 }
271 }
272 // If the waiting process has been stopped because of the
273 // time interval passed or an exception occurred, the state
274 // should be changed
275 keepBlockingEDT.set(false);
276 keepBlockingCT.set(false);
277 }
278 }
279
280 return true;
281 }
282
283 /**
284 * @inheritDoc
285 */
286 public boolean exit() {
287 if (log.isLoggable(PlatformLogger.Level.FINE)) {
288 log.fine("exit(): blockingEDT=" + keepBlockingEDT.get() +
289 ", blockingCT=" + keepBlockingCT.get());
290 }
291 if (keepBlockingEDT.compareAndSet(true, false)) {
292 wakeupEDT();
293 return true;
294 }
295 return false;
296 }
297
298 private final static Object getTreeLock() {
299 return Component.LOCK;
300 }
301
302 private final Runnable wakingRunnable = new Runnable() {
303 public void run() {
304 log.fine("Wake up EDT");
305 synchronized (getTreeLock()) {
306 keepBlockingCT.set(false);
307 getTreeLock().notifyAll();
308 }
309 log.fine("Wake up EDT done");
310 }
311 };
312
313 private void wakeupEDT() {
314 if (log.isLoggable(PlatformLogger.Level.FINEST)) {
315 log.finest("wakeupEDT(): EDT == " + dispatchThread);
316 }
317 EventQueue eq = dispatchThread.getEventQueue();
318 eq.postEvent(new PeerEvent(this, wakingRunnable, PeerEvent.PRIORITY_EVENT));
319 }
320 }
|