--- old/src/java.desktop/share/classes/java/awt/WaitDispatchSupport.java 2015-04-21 13:08:19.252914100 +0300 +++ new/src/java.desktop/share/classes/java/awt/WaitDispatchSupport.java 2015-04-21 13:08:18.850873900 +0300 @@ -46,9 +46,8 @@ * @since 1.7 */ class WaitDispatchSupport implements SecondaryLoop { - private final static PlatformLogger log = - PlatformLogger.getLogger("java.awt.event.WaitDispatchSupport"); + PlatformLogger.getLogger("java.awt.event.WaitDispatchSupport"); private EventDispatchThread dispatchThread; private EventFilter filter; @@ -65,6 +64,7 @@ private AtomicBoolean keepBlockingEDT = new AtomicBoolean(false); private AtomicBoolean keepBlockingCT = new AtomicBoolean(false); + private AtomicBoolean afterExit = new AtomicBoolean(false); private static synchronized void initializeTimer() { if (timer == null) { @@ -77,7 +77,7 @@ * serve the given event dispatch thread. * * @param dispatchThread An event dispatch thread that - * should not stop dispatching events while waiting + * should not stop dispatching events while waiting * * @since 1.7 */ @@ -114,7 +114,7 @@ } boolean extEvaluate = (extCondition != null) ? extCondition.evaluate() : true; - if (!keepBlockingEDT.get() || !extEvaluate) { + if (!keepBlockingEDT.get() || !extEvaluate || afterExit.get()) { if (timerTask != null) { timerTask.cancel(); timerTask = null; @@ -174,110 +174,116 @@ log.fine("The secondary loop is already running, aborting"); return false; } + try { + if (afterExit.get()) { + log.fine("Exit was called already, aborting"); + return false; + } - final Runnable run = new Runnable() { - public void run() { - log.fine("Starting a new event pump"); - if (filter == null) { - dispatchThread.pumpEvents(condition); - } else { - dispatchThread.pumpEventsForFilter(condition, filter); + final Runnable run = new Runnable() { + public void run() { + log.fine("Starting a new event pump"); + if (filter == null) { + dispatchThread.pumpEvents(condition); + } else { + dispatchThread.pumpEventsForFilter(condition, filter); + } } - } - }; + }; - // We have two mechanisms for blocking: if we're on the - // dispatch thread, start a new event pump; if we're - // on any other thread, call wait() on the treelock - - Thread currentThread = Thread.currentThread(); - if (currentThread == dispatchThread) { - if (log.isLoggable(PlatformLogger.Level.FINEST)) { - log.finest("On dispatch thread: " + dispatchThread); - } - if (interval != 0) { + // We have two mechanisms for blocking: if we're on the + // dispatch thread, start a new event pump; if we're + // on any other thread, call wait() on the treelock + + Thread currentThread = Thread.currentThread(); + if (currentThread == dispatchThread) { if (log.isLoggable(PlatformLogger.Level.FINEST)) { - log.finest("scheduling the timer for " + interval + " ms"); + log.finest("On dispatch thread: " + dispatchThread); } - timer.schedule(timerTask = new TimerTask() { - @Override - public void run() { - if (keepBlockingEDT.compareAndSet(true, false)) { - wakeupEDT(); - } + if (interval != 0) { + if (log.isLoggable(PlatformLogger.Level.FINEST)) { + log.finest("scheduling the timer for " + interval + " ms"); } - }, interval); - } - // Dispose SequencedEvent we are dispatching on the current - // AppContext, to prevent us from hang - see 4531693 for details - SequencedEvent currentSE = KeyboardFocusManager. - getCurrentKeyboardFocusManager().getCurrentSequencedEvent(); - if (currentSE != null) { - if (log.isLoggable(PlatformLogger.Level.FINE)) { - log.fine("Dispose current SequencedEvent: " + currentSE); - } - currentSE.dispose(); - } - // In case the exit() method is called before starting - // new event pump it will post the waking event to EDT. - // The event will be handled after the new event pump - // starts. Thus, the enter() method will not hang. - // - // Event pump should be privileged. See 6300270. - AccessController.doPrivileged(new PrivilegedAction() { - public Void run() { - run.run(); - return null; - } - }); - } else { - if (log.isLoggable(PlatformLogger.Level.FINEST)) { - log.finest("On non-dispatch thread: " + currentThread); - } - synchronized (getTreeLock()) { - if (filter != null) { - dispatchThread.addEventFilter(filter); - } - try { - EventQueue eq = dispatchThread.getEventQueue(); - eq.postEvent(new PeerEvent(this, run, PeerEvent.PRIORITY_EVENT)); - keepBlockingCT.set(true); - if (interval > 0) { - long currTime = System.currentTimeMillis(); - while (keepBlockingCT.get() && - ((extCondition != null) ? extCondition.evaluate() : true) && - (currTime + interval > System.currentTimeMillis())) - { - getTreeLock().wait(interval); - } - } else { - while (keepBlockingCT.get() && - ((extCondition != null) ? extCondition.evaluate() : true)) - { - getTreeLock().wait(); + timer.schedule(timerTask = new TimerTask() { + @Override + public void run() { + if (keepBlockingEDT.compareAndSet(true, false)) { + wakeupEDT(); + } } - } + }, interval); + } + // Dispose SequencedEvent we are dispatching on the current + // AppContext, to prevent us from hang - see 4531693 for details + SequencedEvent currentSE = KeyboardFocusManager. + getCurrentKeyboardFocusManager().getCurrentSequencedEvent(); + if (currentSE != null) { if (log.isLoggable(PlatformLogger.Level.FINE)) { - log.fine("waitDone " + keepBlockingEDT.get() + " " + keepBlockingCT.get()); + log.fine("Dispose current SequencedEvent: " + currentSE); } - } catch (InterruptedException e) { - if (log.isLoggable(PlatformLogger.Level.FINE)) { - log.fine("Exception caught while waiting: " + e); + currentSE.dispose(); + } + // In case the exit() method is called before starting + // new event pump it will post the waking event to EDT. + // The event will be handled after the new event pump + // starts. Thus, the enter() method will not hang. + // + // Event pump should be privileged. See 6300270. + AccessController.doPrivileged(new PrivilegedAction() { + public Void run() { + run.run(); + return null; } - } finally { + }); + } else { + if (log.isLoggable(PlatformLogger.Level.FINEST)) { + log.finest("On non-dispatch thread: " + currentThread); + } + keepBlockingCT.set(true); + synchronized (getTreeLock()) { + if (afterExit.get()) return false; if (filter != null) { - dispatchThread.removeEventFilter(filter); + dispatchThread.addEventFilter(filter); + } + try { + EventQueue eq = dispatchThread.getEventQueue(); + eq.postEvent(new PeerEvent(this, run, PeerEvent.PRIORITY_EVENT)); + if (interval > 0) { + long currTime = System.currentTimeMillis(); + while (keepBlockingCT.get() && + ((extCondition != null) ? extCondition.evaluate() : true) && + (currTime + interval > System.currentTimeMillis())) + { + getTreeLock().wait(interval); + } + } else { + while (keepBlockingCT.get() && + ((extCondition != null) ? extCondition.evaluate() : true)) + { + getTreeLock().wait(); + } + } + if (log.isLoggable(PlatformLogger.Level.FINE)) { + log.fine("waitDone " + keepBlockingEDT.get() + " " + keepBlockingCT.get()); + } + } catch (InterruptedException e) { + if (log.isLoggable(PlatformLogger.Level.FINE)) { + log.fine("Exception caught while waiting: " + e); + } + } finally { + if (filter != null) { + dispatchThread.removeEventFilter(filter); + } } } - // If the waiting process has been stopped because of the - // time interval passed or an exception occurred, the state - // should be changed - keepBlockingEDT.set(false); - keepBlockingCT.set(false); } + return true; + } + finally { + keepBlockingEDT.set(false); + keepBlockingCT.set(false); + afterExit.set(false); } - - return true; } /** @@ -286,9 +292,10 @@ public boolean exit() { if (log.isLoggable(PlatformLogger.Level.FINE)) { log.fine("exit(): blockingEDT=" + keepBlockingEDT.get() + - ", blockingCT=" + keepBlockingCT.get()); + ", blockingCT=" + keepBlockingCT.get()); } - if (keepBlockingEDT.compareAndSet(true, false)) { + afterExit.set(true); + if (keepBlockingEDT.getAndSet(false)) { wakeupEDT(); return true; }