src/share/classes/sun/awt/SunToolkit.java

Print this page

        

@@ -542,44 +542,29 @@
                 }
             }, PeerEvent.ULTIMATE_PRIORITY_EVENT);
         postEvent(targetToAppContext(e.getSource()), pe);
     }
 
-    protected static final Lock flushLock = new ReentrantLock();
-    private static boolean isFlushingPendingEvents = false;
-
     /*
      * Flush any pending events which haven't been posted to the AWT
      * EventQueue yet.
      */
     public static void flushPendingEvents()  {
-        flushLock.lock();
-        try {
-            // Don't call flushPendingEvents() recursively
-            if (!isFlushingPendingEvents) {
-                isFlushingPendingEvents = true;
                 AppContext appContext = AppContext.getAppContext();
-                PostEventQueue postEventQueue =
-                    (PostEventQueue)appContext.get(POST_EVENT_QUEUE_KEY);
-                if (postEventQueue != null) {
-                    postEventQueue.flush();
-                }
-            }
-        } finally {
-            isFlushingPendingEvents = false;
-            flushLock.unlock();
-        }
+        flushPendingEvents(appContext);
     }
 
-    public static boolean isPostEventQueueEmpty()  {
-        AppContext appContext = AppContext.getAppContext();
+    /*
+     * Flush the PostEventQueue for the right AppContext.
+     * The default flushPendingEvents only flushes the thread-local context,
+     * which is not always correct, c.f. 3746956
+     */
+    public static void flushPendingEvents(AppContext appContext) {
         PostEventQueue postEventQueue =
             (PostEventQueue)appContext.get(POST_EVENT_QUEUE_KEY);
         if (postEventQueue != null) {
-            return postEventQueue.noEvents();
-        } else {
-            return true;
+            postEventQueue.flush();
         }
     }
 
     /*
      * Execute a chunk of code on the Java event handler thread for the

@@ -2110,46 +2095,61 @@
 class PostEventQueue {
     private EventQueueItem queueHead = null;
     private EventQueueItem queueTail = null;
     private final EventQueue eventQueue;
 
-    // For the case when queue is cleared but events are not posted
-    private volatile boolean isFlushing = false;
+    // For synchronization of flush() method call
+    private boolean isFlushing = false;
+
+    // For elimination of recursion of flush() method call
+    private final ThreadLocal<Boolean> isThreadLocalFlushing = new ThreadLocal<>();
 
     PostEventQueue(EventQueue eq) {
         eventQueue = eq;
     }
 
-    public synchronized boolean noEvents() {
-        return queueHead == null && !isFlushing;
-    }
-
     /*
      * Continually post pending AWTEvents to the Java EventQueue. The method
      * is synchronized to ensure the flush is completed before a new event
      * can be posted to this queue.
      *
      * 7177040: The method couldn't be wholly synchronized because of calls
      * of EventQueue.postEvent() that uses pushPopLock, otherwise it could
      * potentially lead to deadlock
      */
     public void flush() {
+        Boolean b = isThreadLocalFlushing.get();
+        if (b != null && b) {
+            return;
+        }
+
+        isThreadLocalFlushing.set(true);
+        try {
         EventQueueItem tempQueue;
         synchronized (this) {
+                while (isFlushing) {
+                   wait();
+                }
+                isFlushing = (queueHead != null);
+
             tempQueue = queueHead;
             queueHead = queueTail = null;
-            isFlushing = true;
         }
-        try {
             while (tempQueue != null) {
                 eventQueue.postEvent(tempQueue.event);
                 tempQueue = tempQueue.next;
             }
         }
+        catch (InterruptedException e) {
+        }
         finally {
+            synchronized (this) {
             isFlushing = false;
+                notifyAll();
+            }
         }
+        isThreadLocalFlushing.set(false);
     }
 
     /*
      * Enqueue an AWTEvent to be posted to the Java EventQueue.
      */