< 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 >