src/share/classes/java/awt/EventQueue.java
Print this page
@@ -44,11 +44,12 @@
import sun.awt.SunToolkit;
import sun.awt.EventQueueItem;
import sun.awt.AWTAccessor;
import java.util.concurrent.locks.Condition;
-import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
+import java.util.concurrent.atomic.AtomicInteger;
import java.security.AccessControlContext;
import java.security.ProtectionDomain;
import sun.misc.SharedSecrets;
@@ -97,16 +98,11 @@
* @author David Mendenhall
*
* @since 1.1
*/
public class EventQueue {
-
- // From Thread.java
- private static int threadInitNumber;
- private static synchronized int nextThreadNum() {
- return threadInitNumber++;
- }
+ private static final AtomicInteger threadInitNumber = new AtomicInteger(0);
private static final int LOW_PRIORITY = 0;
private static final int NORM_PRIORITY = 1;
private static final int HIGH_PRIORITY = 2;
private static final int ULTIMATE_PRIORITY = 3;
@@ -139,11 +135,11 @@
/*
* A single lock to synchronize the push()/pop() and related operations with
* all the EventQueues from the AppContext. Synchronization on any particular
* event queue(s) is not enough: we should lock the whole stack.
*/
- private final Lock pushPopLock;
+ private final ReentrantLock pushPopLock;
private final Condition pushPopCond;
/*
* Dummy runnable to wake up EDT from getNextEvent() after
push/pop is performed
@@ -173,13 +169,13 @@
/*
* Non-zero if a thread is waiting in getNextEvent(int) for an event of
* a particular ID to be posted to the queue.
*/
- private int waitForID;
+ private volatile int waitForID;
- private final String name = "AWT-EventQueue-" + nextThreadNum();
+ private final String name = "AWT-EventQueue-" + threadInitNumber.getAndIncrement();
private static final PlatformLogger eventLog = PlatformLogger.getLogger("java.awt.event.EventQueue");
static {
AWTAccessor.setEventQueueAccessor(
@@ -204,11 +200,11 @@
* SunToolkit.createNewAppContext() the started dispatch thread
* may call AppContext.getAppContext() before createNewAppContext()
* completes thus causing mess in thread group to appcontext mapping.
*/
- pushPopLock = (Lock)AppContext.getAppContext().get(AppContext.EVENT_QUEUE_LOCK_KEY);
+ pushPopLock = (ReentrantLock)AppContext.getAppContext().get(AppContext.EVENT_QUEUE_LOCK_KEY);
pushPopCond = (Condition)AppContext.getAppContext().get(AppContext.EVENT_QUEUE_COND_KEY);
}
/**
* Posts a 1.1-style event to the <code>EventQueue</code>.
@@ -512,12 +508,17 @@
return event;
}
AWTAutoShutdown.getInstance().notifyThreadFree(dispatchThread);
pushPopCond.await();
} finally {
+ // In case the current Thread has been stopped,
+ // re-acquiring the lock fails, and unlocking it would
+ // cause an IllegalMonitorStateException to be thrown.
+ if(pushPopLock.isHeldByCurrentThread()) {
pushPopLock.unlock();
}
+ }
} while(true);
}
/*
* Must be called under the lock. Doesn't call flushPendingEvents()
@@ -567,12 +568,17 @@
}
waitForID = id;
pushPopCond.await();
waitForID = 0;
} finally {
+ // In case the current Thread has been stopped,
+ // re-acquiring the lock fails, and unlocking it would
+ // cause an IllegalMonitorStateException to be thrown.
+ if(pushPopLock.isHeldByCurrentThread()) {
pushPopLock.unlock();
}
+ }
} while(true);
}
/**
* Returns the first event on the <code>EventQueue</code>
@@ -1028,11 +1034,11 @@
} finally {
pushPopLock.unlock();
}
}
- final boolean detachDispatchThread(EventDispatchThread edt) {
+ final boolean detachDispatchThread(EventDispatchThread edt, boolean forceDetach) {
/*
* This synchronized block is to secure that the event dispatch
* thread won't die in the middle of posting a new event to the
* associated event queue. It is important because we notify
* that the event dispatch thread is busy after posting a new event
@@ -1047,11 +1053,11 @@
* sure if it's a possible scenario, though.
*
* Fix for 4648733. Check both the associated java event
* queue and the PostEventQueue.
*/
- if ((peekEvent() != null) || !SunToolkit.isPostEventQueueEmpty()) {
+ if (!forceDetach && (peekEvent() != null) || !SunToolkit.isPostEventQueueEmpty()) {
return false;
}
dispatchThread = null;
}
AWTAutoShutdown.getInstance().notifyThreadFree(edt);