< prev index next >
src/java.desktop/share/classes/java/awt/WaitDispatchSupport.java
Print this page
@@ -44,11 +44,10 @@
* @author Anton Tarasov, Artem Ananiev
*
* @since 1.7
*/
class WaitDispatchSupport implements SecondaryLoop {
-
private final static PlatformLogger log =
PlatformLogger.getLogger("java.awt.event.WaitDispatchSupport");
private EventDispatchThread dispatchThread;
private EventFilter filter;
@@ -63,10 +62,11 @@
// shared timer up and running
private TimerTask timerTask;
private AtomicBoolean keepBlockingEDT = new AtomicBoolean(false);
private AtomicBoolean keepBlockingCT = new AtomicBoolean(false);
+ private AtomicBoolean prematureExit = new AtomicBoolean(false);
private static synchronized void initializeTimer() {
if (timer == null) {
timer = new Timer("AWT-WaitDispatchSupport-Timer", true);
}
@@ -232,18 +232,19 @@
});
} else {
if (log.isLoggable(PlatformLogger.Level.FINEST)) {
log.finest("On non-dispatch thread: " + currentThread);
}
+ keepBlockingCT.set(true);
synchronized (getTreeLock()) {
+ if (keepBlockingEDT.get() && !prematureExit.get()) {
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()))
@@ -272,42 +273,65 @@
// 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);
+ } else {
+ // We get here when exit called after but happened concurrently
+ keepBlockingCT.set(false);
+ prematureExit.set(true);
}
}
-
- return true;
+ }
+ return !prematureExit.getAndSet(false);
}
/**
* {@inheritDoc}
*/
public boolean exit() {
if (log.isLoggable(PlatformLogger.Level.FINE)) {
log.fine("exit(): blockingEDT=" + keepBlockingEDT.get() +
", blockingCT=" + keepBlockingCT.get());
}
- if (keepBlockingEDT.compareAndSet(true, false)) {
+ if(keepBlockingCT.get()) {
+ // enter() is waiting in non-dispatch thread
+ synchronized (getTreeLock()) {
+ keepBlockingEDT.set(false);
+ prematureExit.set(false);
+ wakeupEDT();
+ return true;
+ }
+ } else {
+ if (keepBlockingEDT.getAndSet(false)) {
+ prematureExit.set(false);
wakeupEDT();
return true;
}
+ // exit() call before enter()
+ prematureExit.set(true);
+ // Still need to wake up it can be a concurrent exit()
+ wakeupEDT();
return false;
}
+ }
private final static Object getTreeLock() {
return Component.LOCK;
}
private final Runnable wakingRunnable = new Runnable() {
public void run() {
log.fine("Wake up EDT");
+ keepBlockingEDT.set(false);
+ if (keepBlockingCT.get()) {
+ // Notify only if enter() waiting in non-dispatch thread
synchronized (getTreeLock()) {
keepBlockingCT.set(false);
getTreeLock().notifyAll();
}
+ }
log.fine("Wake up EDT done");
}
};
private void wakeupEDT() {
< prev index next >