--- old/src/share/classes/sun/awt/SunToolkit.java 2012-08-28 18:06:58.768099600 +0400 +++ new/src/share/classes/sun/awt/SunToolkit.java 2012-08-28 18:06:57.852047200 +0400 @@ -544,40 +544,25 @@ 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(); - } + AppContext appContext = AppContext.getAppContext(); + 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); + (PostEventQueue)appContext.get(POST_EVENT_QUEUE_KEY); if (postEventQueue != null) { - return postEventQueue.noEvents(); - } else { - return true; + postEventQueue.flush(); } } @@ -2112,17 +2097,16 @@ 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 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 @@ -2133,21 +2117,37 @@ * potentially lead to deadlock */ public void flush() { - EventQueueItem tempQueue; - synchronized (this) { - tempQueue = queueHead; - queueHead = queueTail = null; - isFlushing = true; + 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; + } while (tempQueue != null) { eventQueue.postEvent(tempQueue.event); tempQueue = tempQueue.next; } } + catch (InterruptedException e) { + } finally { - isFlushing = false; + synchronized (this) { + isFlushing = false; + notifyAll(); + } } + isThreadLocalFlushing.set(false); } /*