src/share/classes/java/awt/EventQueue.java

Print this page




  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             }


  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             }