22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package java.awt;
27
28 import java.awt.event.*;
29
30 import java.awt.peer.ComponentPeer;
31
32 import java.lang.ref.WeakReference;
33 import java.lang.reflect.InvocationTargetException;
34
35 import java.security.AccessController;
36 import java.security.PrivilegedAction;
37
38 import java.util.EmptyStackException;
39 import sun.util.logging.PlatformLogger;
40
41 import sun.awt.AppContext;
42 import sun.awt.AWTAutoShutdown;
43 import sun.awt.PeerEvent;
44 import sun.awt.SunToolkit;
45 import sun.awt.EventQueueItem;
46 import sun.awt.AWTAccessor;
47
48 import java.util.concurrent.locks.Condition;
49 import java.util.concurrent.locks.Lock;
50 import java.util.concurrent.atomic.AtomicInteger;
51
52 import java.security.AccessControlContext;
53 import java.security.ProtectionDomain;
54
55 import sun.misc.SharedSecrets;
56 import sun.misc.JavaSecurityAccess;
57
58 /**
59 * <code>EventQueue</code> is a platform-independent class
60 * that queues events, both from the underlying peer classes
61 * and from trusted application classes.
62 * <p>
63 * It encapsulates asynchronous event dispatch machinery which
64 * extracts events from the queue and dispatches them by calling
65 * {@link #dispatchEvent(AWTEvent) dispatchEvent(AWTEvent)} method
66 * on this <code>EventQueue</code> with the event to be dispatched
1021 AWTAutoShutdown.getInstance().notifyThreadBusy(dispatchThread);
1022 dispatchThread.start();
1023 }
1024 } finally {
1025 pushPopLock.unlock();
1026 }
1027 }
1028
1029 final boolean detachDispatchThread(EventDispatchThread edt, boolean forceDetach) {
1030 /*
1031 * This synchronized block is to secure that the event dispatch
1032 * thread won't die in the middle of posting a new event to the
1033 * associated event queue. It is important because we notify
1034 * that the event dispatch thread is busy after posting a new event
1035 * to its queue, so the EventQueue.dispatchThread reference must
1036 * be valid at that point.
1037 */
1038 pushPopLock.lock();
1039 try {
1040 if (edt == dispatchThread) {
1041 /*
1042 * Don't detach the thread if any events are pending. Not
1043 * sure if it's a possible scenario, though.
1044 *
1045 * Fix for 4648733. Check both the associated java event
1046 * queue and the PostEventQueue.
1047 */
1048 if (!forceDetach && (peekEvent() != null) || !SunToolkit.isPostEventQueueEmpty()) {
1049 return false;
1050 }
1051 dispatchThread = null;
1052 }
1053 AWTAutoShutdown.getInstance().notifyThreadFree(edt);
1054 return true;
1055 } finally {
1056 pushPopLock.unlock();
1057 }
1058 }
1059
1060 /*
1061 * Gets the <code>EventDispatchThread</code> for this
1062 * <code>EventQueue</code>.
1063 * @return the event dispatch thread associated with this event queue
1064 * or <code>null</code> if this event queue doesn't have a
1065 * working thread associated with it
1066 * @see java.awt.EventQueue#initDispatchThread
1067 * @see java.awt.EventQueue#detachDispatchThread
1068 */
1069 final EventDispatchThread getDispatchThread() {
1111 ((SentEvent)entry.event).dispose();
1112 }
1113 if (prev == null) {
1114 queues[i].head = entry.next;
1115 } else {
1116 prev.next = entry.next;
1117 }
1118 uncacheEQItem(entry);
1119 } else {
1120 prev = entry;
1121 }
1122 entry = entry.next;
1123 }
1124 queues[i].tail = prev;
1125 }
1126 } finally {
1127 pushPopLock.unlock();
1128 }
1129 }
1130
1131 static void setCurrentEventAndMostRecentTime(AWTEvent e) {
1132 Toolkit.getEventQueue().setCurrentEventAndMostRecentTimeImpl(e);
1133 }
1134 private void setCurrentEventAndMostRecentTimeImpl(AWTEvent e) {
1135 pushPopLock.lock();
1136 try {
1137 if (Thread.currentThread() != dispatchThread) {
1138 return;
1139 }
1140
1141 currentEvent = new WeakReference(e);
1142
1143 // This series of 'instanceof' checks should be replaced with a
1144 // polymorphic type (for example, an interface which declares a
1145 // getWhen() method). However, this would require us to make such
1146 // a type public, or to place it in sun.awt. Both of these approaches
1147 // have been frowned upon. So for now, we hack.
1148 //
1149 // In tiger, we will probably give timestamps to all events, so this
1150 // will no longer be an issue.
1218 if (EventQueue.isDispatchThread()) {
1219 throw new Error("Cannot call invokeAndWait from the event dispatcher thread");
1220 }
1221
1222 class AWTInvocationLock {}
1223 Object lock = new AWTInvocationLock();
1224
1225 InvocationEvent event =
1226 new InvocationEvent(Toolkit.getDefaultToolkit(), runnable, lock,
1227 true);
1228
1229 synchronized (lock) {
1230 Toolkit.getEventQueue().postEvent(event);
1231 while (!event.isDispatched()) {
1232 lock.wait();
1233 }
1234 }
1235
1236 Throwable eventThrowable = event.getThrowable();
1237 if (eventThrowable != null) {
1238 throw new InvocationTargetException(eventThrowable);
1239 }
1240 }
1241
1242 /*
1243 * Called from PostEventQueue.postEvent to notify that a new event
1244 * appeared. First it proceeds to the EventQueue on the top of the
1245 * stack, then notifies the associated dispatch thread if it exists
1246 * or starts a new one otherwise.
1247 */
1248 private void wakeup(boolean isShutdown) {
1249 pushPopLock.lock();
1250 try {
1251 if (nextQueue != null) {
1252 // Forward call to the top of EventQueue stack.
1253 nextQueue.wakeup(isShutdown);
1254 } else if (dispatchThread != null) {
1255 pushPopCond.signalAll();
1256 } else if (!isShutdown) {
1257 initDispatchThread();
1258 }
|
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package java.awt;
27
28 import java.awt.event.*;
29
30 import java.awt.peer.ComponentPeer;
31
32 import java.lang.ref.WeakReference;
33 import java.lang.reflect.InvocationTargetException;
34
35 import java.security.AccessController;
36 import java.security.PrivilegedAction;
37
38 import java.util.EmptyStackException;
39 import sun.util.logging.PlatformLogger;
40
41 import sun.awt.AppContext;
42 import sun.awt.AWTAccessor;
43 import sun.awt.AWTAutoShutdown;
44 import sun.awt.AWTInterruptedException;
45 import sun.awt.PeerEvent;
46 import sun.awt.SunToolkit;
47 import sun.awt.EventQueueItem;
48
49 import java.util.concurrent.locks.Condition;
50 import java.util.concurrent.locks.Lock;
51 import java.util.concurrent.atomic.AtomicInteger;
52
53 import java.security.AccessControlContext;
54 import java.security.ProtectionDomain;
55
56 import sun.misc.SharedSecrets;
57 import sun.misc.JavaSecurityAccess;
58
59 /**
60 * <code>EventQueue</code> is a platform-independent class
61 * that queues events, both from the underlying peer classes
62 * and from trusted application classes.
63 * <p>
64 * It encapsulates asynchronous event dispatch machinery which
65 * extracts events from the queue and dispatches them by calling
66 * {@link #dispatchEvent(AWTEvent) dispatchEvent(AWTEvent)} method
67 * on this <code>EventQueue</code> with the event to be dispatched
1022 AWTAutoShutdown.getInstance().notifyThreadBusy(dispatchThread);
1023 dispatchThread.start();
1024 }
1025 } finally {
1026 pushPopLock.unlock();
1027 }
1028 }
1029
1030 final boolean detachDispatchThread(EventDispatchThread edt, boolean forceDetach) {
1031 /*
1032 * This synchronized block is to secure that the event dispatch
1033 * thread won't die in the middle of posting a new event to the
1034 * associated event queue. It is important because we notify
1035 * that the event dispatch thread is busy after posting a new event
1036 * to its queue, so the EventQueue.dispatchThread reference must
1037 * be valid at that point.
1038 */
1039 pushPopLock.lock();
1040 try {
1041 if (edt == dispatchThread) {
1042 if (peekEvent() != null || !SunToolkit.isPostEventQueueEmpty()) {
1043 if (!forceDetach) {
1044 /*
1045 * Fix for 4648733. Check both the associated java event
1046 * queue and the PostEventQueue.
1047 */
1048 return false;
1049 } else {
1050 // 7162144 - derail pending events
1051 removeAllEvents();
1052 }
1053 }
1054 dispatchThread = null;
1055 }
1056 AWTAutoShutdown.getInstance().notifyThreadFree(edt);
1057 return true;
1058 } finally {
1059 pushPopLock.unlock();
1060 }
1061 }
1062
1063 /*
1064 * Gets the <code>EventDispatchThread</code> for this
1065 * <code>EventQueue</code>.
1066 * @return the event dispatch thread associated with this event queue
1067 * or <code>null</code> if this event queue doesn't have a
1068 * working thread associated with it
1069 * @see java.awt.EventQueue#initDispatchThread
1070 * @see java.awt.EventQueue#detachDispatchThread
1071 */
1072 final EventDispatchThread getDispatchThread() {
1114 ((SentEvent)entry.event).dispose();
1115 }
1116 if (prev == null) {
1117 queues[i].head = entry.next;
1118 } else {
1119 prev.next = entry.next;
1120 }
1121 uncacheEQItem(entry);
1122 } else {
1123 prev = entry;
1124 }
1125 entry = entry.next;
1126 }
1127 queues[i].tail = prev;
1128 }
1129 } finally {
1130 pushPopLock.unlock();
1131 }
1132 }
1133
1134 private void removeAllEvents() {
1135 SunToolkit.flushPendingEvents();
1136 pushPopLock.lock();
1137 try {
1138 for (int i = 0; i < NUM_PRIORITIES; i++) {
1139 EventQueueItem entry = queues[i].head;
1140 EventQueueItem prev = null;
1141 while (entry != null) {
1142 if (entry.event instanceof InvocationEvent) {
1143 AWTAccessor.getInvocationEventAccessor().
1144 dispose((InvocationEvent)entry.event);
1145 }
1146 if (entry.event instanceof SequencedEvent) {
1147 ((SequencedEvent)entry.event).dispose();
1148 }
1149 if (entry.event instanceof SentEvent) {
1150 ((SentEvent)entry.event).dispose();
1151 }
1152 if (prev == null) {
1153 queues[i].head = entry.next;
1154 } else {
1155 prev.next = entry.next;
1156 }
1157 uncacheEQItem(entry);
1158 entry = entry.next;
1159 }
1160 queues[i].tail = prev;
1161 }
1162 } finally {
1163 pushPopLock.unlock();
1164 }
1165 }
1166
1167 static void setCurrentEventAndMostRecentTime(AWTEvent e) {
1168 Toolkit.getEventQueue().setCurrentEventAndMostRecentTimeImpl(e);
1169 }
1170 private void setCurrentEventAndMostRecentTimeImpl(AWTEvent e) {
1171 pushPopLock.lock();
1172 try {
1173 if (Thread.currentThread() != dispatchThread) {
1174 return;
1175 }
1176
1177 currentEvent = new WeakReference(e);
1178
1179 // This series of 'instanceof' checks should be replaced with a
1180 // polymorphic type (for example, an interface which declares a
1181 // getWhen() method). However, this would require us to make such
1182 // a type public, or to place it in sun.awt. Both of these approaches
1183 // have been frowned upon. So for now, we hack.
1184 //
1185 // In tiger, we will probably give timestamps to all events, so this
1186 // will no longer be an issue.
1254 if (EventQueue.isDispatchThread()) {
1255 throw new Error("Cannot call invokeAndWait from the event dispatcher thread");
1256 }
1257
1258 class AWTInvocationLock {}
1259 Object lock = new AWTInvocationLock();
1260
1261 InvocationEvent event =
1262 new InvocationEvent(Toolkit.getDefaultToolkit(), runnable, lock,
1263 true);
1264
1265 synchronized (lock) {
1266 Toolkit.getEventQueue().postEvent(event);
1267 while (!event.isDispatched()) {
1268 lock.wait();
1269 }
1270 }
1271
1272 Throwable eventThrowable = event.getThrowable();
1273 if (eventThrowable != null) {
1274 if (eventThrowable instanceof AWTInterruptedException) {
1275 throw new InterruptedException(eventThrowable.getMessage());
1276 } else {
1277 throw new InvocationTargetException(eventThrowable);
1278 }
1279 }
1280 }
1281
1282 /*
1283 * Called from PostEventQueue.postEvent to notify that a new event
1284 * appeared. First it proceeds to the EventQueue on the top of the
1285 * stack, then notifies the associated dispatch thread if it exists
1286 * or starts a new one otherwise.
1287 */
1288 private void wakeup(boolean isShutdown) {
1289 pushPopLock.lock();
1290 try {
1291 if (nextQueue != null) {
1292 // Forward call to the top of EventQueue stack.
1293 nextQueue.wakeup(isShutdown);
1294 } else if (dispatchThread != null) {
1295 pushPopCond.signalAll();
1296 } else if (!isShutdown) {
1297 initDispatchThread();
1298 }
|