jdk/src/share/classes/java/awt/EventQueue.java
changeset 4365 4ac67034e98b
parent 4264 40c232605c68
child 5506 202f599c92aa
equal deleted inserted replaced
4364:4b4427db3536 4365:4ac67034e98b
    42 import sun.awt.AWTAutoShutdown;
    42 import sun.awt.AWTAutoShutdown;
    43 import sun.awt.PeerEvent;
    43 import sun.awt.PeerEvent;
    44 import sun.awt.SunToolkit;
    44 import sun.awt.SunToolkit;
    45 import sun.awt.EventQueueItem;
    45 import sun.awt.EventQueueItem;
    46 import sun.awt.AWTAccessor;
    46 import sun.awt.AWTAccessor;
       
    47 
       
    48 import java.util.concurrent.locks.Condition;
       
    49 import java.util.concurrent.locks.Lock;
    47 
    50 
    48 /**
    51 /**
    49  * <code>EventQueue</code> is a platform-independent class
    52  * <code>EventQueue</code> is a platform-independent class
    50  * that queues events, both from the underlying peer classes
    53  * that queues events, both from the underlying peer classes
    51  * and from trusted application classes.
    54  * and from trusted application classes.
   125      * The previous EventQueue on the stack, or null if this is the
   128      * The previous EventQueue on the stack, or null if this is the
   126      * "base" EventQueue.
   129      * "base" EventQueue.
   127      */
   130      */
   128     private EventQueue previousQueue;
   131     private EventQueue previousQueue;
   129 
   132 
       
   133     /*
       
   134      * A single lock to synchronize the push()/pop() and related operations with
       
   135      * all the EventQueues from the AppContext. Synchronization on any particular
       
   136      * event queue(s) is not enough: we should lock the whole stack.
       
   137      */
       
   138     private final Lock pushPopLock;
       
   139     private final Condition pushPopCond;
       
   140 
   130     private EventDispatchThread dispatchThread;
   141     private EventDispatchThread dispatchThread;
   131 
   142 
   132     private final ThreadGroup threadGroup =
   143     private final ThreadGroup threadGroup =
   133         Thread.currentThread().getThreadGroup();
   144         Thread.currentThread().getThreadGroup();
   134     private final ClassLoader classLoader =
   145     private final ClassLoader classLoader =
   156     private static final PlatformLogger eventLog = PlatformLogger.getLogger("java.awt.event.EventQueue");
   167     private static final PlatformLogger eventLog = PlatformLogger.getLogger("java.awt.event.EventQueue");
   157 
   168 
   158     static {
   169     static {
   159         AWTAccessor.setEventQueueAccessor(
   170         AWTAccessor.setEventQueueAccessor(
   160             new AWTAccessor.EventQueueAccessor() {
   171             new AWTAccessor.EventQueueAccessor() {
   161                 public EventQueue getNextQueue(EventQueue eventQueue) {
       
   162                     return eventQueue.nextQueue;
       
   163                 }
       
   164                 public Thread getDispatchThread(EventQueue eventQueue) {
   172                 public Thread getDispatchThread(EventQueue eventQueue) {
   165                     return eventQueue.dispatchThread;
   173                     return eventQueue.getDispatchThread();
       
   174                 }
       
   175                 public boolean isDispatchThreadImpl(EventQueue eventQueue) {
       
   176                     return eventQueue.isDispatchThreadImpl();
   166                 }
   177                 }
   167             });
   178             });
   168     }
   179     }
   169 
   180 
   170     public EventQueue() {
   181     public EventQueue() {
   177          * If this EventQueue instance is created in
   188          * If this EventQueue instance is created in
   178          * SunToolkit.createNewAppContext() the started dispatch thread
   189          * SunToolkit.createNewAppContext() the started dispatch thread
   179          * may call AppContext.getAppContext() before createNewAppContext()
   190          * may call AppContext.getAppContext() before createNewAppContext()
   180          * completes thus causing mess in thread group to appcontext mapping.
   191          * completes thus causing mess in thread group to appcontext mapping.
   181          */
   192          */
       
   193 
       
   194         pushPopLock = (Lock)AppContext.getAppContext().get(AppContext.EVENT_QUEUE_LOCK_KEY);
       
   195         pushPopCond = (Condition)AppContext.getAppContext().get(AppContext.EVENT_QUEUE_COND_KEY);
   182     }
   196     }
   183 
   197 
   184     /**
   198     /**
   185      * Posts a 1.1-style event to the <code>EventQueue</code>.
   199      * Posts a 1.1-style event to the <code>EventQueue</code>.
   186      * If there is an existing event on the queue with the same ID
   200      * If there is an existing event on the queue with the same ID
   205      * @param theEvent an instance of <code>java.awt.AWTEvent</code>,
   219      * @param theEvent an instance of <code>java.awt.AWTEvent</code>,
   206      *          or a subclass of it
   220      *          or a subclass of it
   207      */
   221      */
   208     final void postEventPrivate(AWTEvent theEvent) {
   222     final void postEventPrivate(AWTEvent theEvent) {
   209         theEvent.isPosted = true;
   223         theEvent.isPosted = true;
   210         synchronized(this) {
   224         pushPopLock.lock();
       
   225         try {
   211             if (dispatchThread == null && nextQueue == null) {
   226             if (dispatchThread == null && nextQueue == null) {
   212                 if (theEvent.getSource() == AWTAutoShutdown.getInstance()) {
   227                 if (theEvent.getSource() == AWTAutoShutdown.getInstance()) {
   213                     return;
   228                     return;
   214                 } else {
   229                 } else {
   215                     initDispatchThread();
   230                     initDispatchThread();
   219                 // Forward event to top of EventQueue stack.
   234                 // Forward event to top of EventQueue stack.
   220                 nextQueue.postEventPrivate(theEvent);
   235                 nextQueue.postEventPrivate(theEvent);
   221                 return;
   236                 return;
   222             }
   237             }
   223             postEvent(theEvent, getPriority(theEvent));
   238             postEvent(theEvent, getPriority(theEvent));
       
   239         } finally {
       
   240             pushPopLock.unlock();
   224         }
   241         }
   225     }
   242     }
   226 
   243 
   227     private static int getPriority(AWTEvent theEvent) {
   244     private static int getPriority(AWTEvent theEvent) {
   228         if (theEvent instanceof PeerEvent &&
   245         if (theEvent instanceof PeerEvent &&
   278 
   295 
   279             if (shouldNotify) {
   296             if (shouldNotify) {
   280                 if (theEvent.getSource() != AWTAutoShutdown.getInstance()) {
   297                 if (theEvent.getSource() != AWTAutoShutdown.getInstance()) {
   281                     AWTAutoShutdown.getInstance().notifyThreadBusy(dispatchThread);
   298                     AWTAutoShutdown.getInstance().notifyThreadBusy(dispatchThread);
   282                 }
   299                 }
   283                 notifyAll();
   300                 pushPopCond.signalAll();
   284             } else if (notifyID) {
   301             } else if (notifyID) {
   285                 notifyAll();
   302                 pushPopCond.signalAll();
   286             }
   303             }
   287         } else {
   304         } else {
   288             // The event was not coalesced or has non-Component source.
   305             // The event was not coalesced or has non-Component source.
   289             // Insert it at the end of the appropriate Queue.
   306             // Insert it at the end of the appropriate Queue.
   290             queues[priority].tail.next = newItem;
   307             queues[priority].tail.next = newItem;
   291             queues[priority].tail = newItem;
   308             queues[priority].tail = newItem;
   292             if (notifyID) {
   309             if (notifyID) {
   293                 notifyAll();
   310                 pushPopCond.signalAll();
   294             }
   311             }
   295         }
   312         }
   296     }
   313     }
   297 
   314 
   298     private boolean coalescePaintEvent(PaintEvent e) {
   315     private boolean coalescePaintEvent(PaintEvent e) {
   480              * SunToolkit.flushPendingEvents must be called outside
   497              * SunToolkit.flushPendingEvents must be called outside
   481              * of the synchronized block to avoid deadlock when
   498              * of the synchronized block to avoid deadlock when
   482              * event queues are nested with push()/pop().
   499              * event queues are nested with push()/pop().
   483              */
   500              */
   484             SunToolkit.flushPendingEvents();
   501             SunToolkit.flushPendingEvents();
   485             synchronized (this) {
   502             pushPopLock.lock();
       
   503             try {
   486                 for (int i = NUM_PRIORITIES - 1; i >= 0; i--) {
   504                 for (int i = NUM_PRIORITIES - 1; i >= 0; i--) {
   487                     if (queues[i].head != null) {
   505                     if (queues[i].head != null) {
   488                         EventQueueItem entry = queues[i].head;
   506                         EventQueueItem entry = queues[i].head;
   489                         queues[i].head = entry.next;
   507                         queues[i].head = entry.next;
   490                         if (entry.next == null) {
   508                         if (entry.next == null) {
   493                         uncacheEQItem(entry);
   511                         uncacheEQItem(entry);
   494                         return entry.event;
   512                         return entry.event;
   495                     }
   513                     }
   496                 }
   514                 }
   497                 AWTAutoShutdown.getInstance().notifyThreadFree(dispatchThread);
   515                 AWTAutoShutdown.getInstance().notifyThreadFree(dispatchThread);
   498                 wait();
   516                 pushPopCond.await();
       
   517             } finally {
       
   518                 pushPopLock.unlock();
   499             }
   519             }
   500         } while(true);
   520         } while(true);
   501     }
   521     }
   502 
   522 
   503     AWTEvent getNextEvent(int id) throws InterruptedException {
   523     AWTEvent getNextEvent(int id) throws InterruptedException {
   506              * SunToolkit.flushPendingEvents must be called outside
   526              * SunToolkit.flushPendingEvents must be called outside
   507              * of the synchronized block to avoid deadlock when
   527              * of the synchronized block to avoid deadlock when
   508              * event queues are nested with push()/pop().
   528              * event queues are nested with push()/pop().
   509              */
   529              */
   510             SunToolkit.flushPendingEvents();
   530             SunToolkit.flushPendingEvents();
   511             synchronized (this) {
   531             pushPopLock.lock();
       
   532             try {
   512                 for (int i = 0; i < NUM_PRIORITIES; i++) {
   533                 for (int i = 0; i < NUM_PRIORITIES; i++) {
   513                     for (EventQueueItem entry = queues[i].head, prev = null;
   534                     for (EventQueueItem entry = queues[i].head, prev = null;
   514                          entry != null; prev = entry, entry = entry.next)
   535                          entry != null; prev = entry, entry = entry.next)
   515                     {
   536                     {
   516                         if (entry.event.getID() == id) {
   537                         if (entry.event.getID() == id) {
   525                             uncacheEQItem(entry);
   546                             uncacheEQItem(entry);
   526                             return entry.event;
   547                             return entry.event;
   527                         }
   548                         }
   528                     }
   549                     }
   529                 }
   550                 }
   530                 this.waitForID = id;
   551                 waitForID = id;
   531                 wait();
   552                 pushPopCond.await();
   532                 this.waitForID = 0;
   553                 waitForID = 0;
       
   554             } finally {
       
   555                 pushPopLock.unlock();
   533             }
   556             }
   534         } while(true);
   557         } while(true);
   535     }
   558     }
   536 
   559 
   537     /**
   560     /**
   538      * Returns the first event on the <code>EventQueue</code>
   561      * Returns the first event on the <code>EventQueue</code>
   539      * without removing it.
   562      * without removing it.
   540      * @return the first event
   563      * @return the first event
   541      */
   564      */
   542     public synchronized AWTEvent peekEvent() {
   565     public AWTEvent peekEvent() {
   543         for (int i = NUM_PRIORITIES - 1; i >= 0; i--) {
   566         pushPopLock.lock();
   544             if (queues[i].head != null) {
   567         try {
   545                 return queues[i].head.event;
   568             for (int i = NUM_PRIORITIES - 1; i >= 0; i--) {
   546             }
   569                 if (queues[i].head != null) {
       
   570                     return queues[i].head.event;
       
   571                 }
       
   572             }
       
   573         } finally {
       
   574             pushPopLock.unlock();
   547         }
   575         }
   548 
   576 
   549         return null;
   577         return null;
   550     }
   578     }
   551 
   579 
   553      * Returns the first event with the specified id, if any.
   581      * Returns the first event with the specified id, if any.
   554      * @param id the id of the type of event desired
   582      * @param id the id of the type of event desired
   555      * @return the first event of the specified id or <code>null</code>
   583      * @return the first event of the specified id or <code>null</code>
   556      *    if there is no such event
   584      *    if there is no such event
   557      */
   585      */
   558     public synchronized AWTEvent peekEvent(int id) {
   586     public AWTEvent peekEvent(int id) {
   559         for (int i = NUM_PRIORITIES - 1; i >= 0; i--) {
   587         pushPopLock.lock();
   560             EventQueueItem q = queues[i].head;
   588         try {
   561             for (; q != null; q = q.next) {
   589             for (int i = NUM_PRIORITIES - 1; i >= 0; i--) {
   562                 if (q.event.getID() == id) {
   590                 EventQueueItem q = queues[i].head;
   563                     return q.event;
   591                 for (; q != null; q = q.next) {
   564                 }
   592                     if (q.event.getID() == id) {
   565             }
   593                         return q.event;
       
   594                     }
       
   595                 }
       
   596             }
       
   597         } finally {
       
   598             pushPopLock.unlock();
   566         }
   599         }
   567 
   600 
   568         return null;
   601         return null;
   569     }
   602     }
   570 
   603 
   659      * @since 1.4
   692      * @since 1.4
   660      */
   693      */
   661     public static long getMostRecentEventTime() {
   694     public static long getMostRecentEventTime() {
   662         return Toolkit.getEventQueue().getMostRecentEventTimeImpl();
   695         return Toolkit.getEventQueue().getMostRecentEventTimeImpl();
   663     }
   696     }
   664     private synchronized long getMostRecentEventTimeImpl() {
   697     private long getMostRecentEventTimeImpl() {
   665         return (Thread.currentThread() == dispatchThread)
   698         pushPopLock.lock();
   666             ? mostRecentEventTime
   699         try {
   667             : System.currentTimeMillis();
   700             return (Thread.currentThread() == dispatchThread)
       
   701                 ? mostRecentEventTime
       
   702                 : System.currentTimeMillis();
       
   703         } finally {
       
   704             pushPopLock.unlock();
       
   705         }
   668     }
   706     }
   669 
   707 
   670     /**
   708     /**
   671      * @return most recent event time on all threads.
   709      * @return most recent event time on all threads.
   672      */
   710      */
   673     synchronized long getMostRecentEventTimeEx() {
   711     long getMostRecentEventTimeEx() {
   674         return mostRecentEventTime;
   712         pushPopLock.lock();
       
   713         try {
       
   714             return mostRecentEventTime;
       
   715         } finally {
       
   716             pushPopLock.unlock();
       
   717         }
   675     }
   718     }
   676 
   719 
   677     /**
   720     /**
   678      * Returns the the event currently being dispatched by the
   721      * Returns the the event currently being dispatched by the
   679      * <code>EventQueue</code> associated with the calling thread. This is
   722      * <code>EventQueue</code> associated with the calling thread. This is
   687      * @since 1.4
   730      * @since 1.4
   688      */
   731      */
   689     public static AWTEvent getCurrentEvent() {
   732     public static AWTEvent getCurrentEvent() {
   690         return Toolkit.getEventQueue().getCurrentEventImpl();
   733         return Toolkit.getEventQueue().getCurrentEventImpl();
   691     }
   734     }
   692     private synchronized AWTEvent getCurrentEventImpl() {
   735     private AWTEvent getCurrentEventImpl() {
   693         return (Thread.currentThread() == dispatchThread)
   736         pushPopLock.lock();
   694             ? ((AWTEvent)currentEvent.get())
   737         try {
   695             : null;
   738                 return (Thread.currentThread() == dispatchThread)
       
   739                 ? ((AWTEvent)currentEvent.get())
       
   740                 : null;
       
   741         } finally {
       
   742             pushPopLock.unlock();
       
   743         }
   696     }
   744     }
   697 
   745 
   698     /**
   746     /**
   699      * Replaces the existing <code>EventQueue</code> with the specified one.
   747      * Replaces the existing <code>EventQueue</code> with the specified one.
   700      * Any pending events are transferred to the new <code>EventQueue</code>
   748      * Any pending events are transferred to the new <code>EventQueue</code>
   704      *          (or subclass thereof) instance to be use
   752      *          (or subclass thereof) instance to be use
   705      * @see      java.awt.EventQueue#pop
   753      * @see      java.awt.EventQueue#pop
   706      * @throws NullPointerException if <code>newEventQueue</code> is <code>null</code>
   754      * @throws NullPointerException if <code>newEventQueue</code> is <code>null</code>
   707      * @since           1.2
   755      * @since           1.2
   708      */
   756      */
   709     public synchronized void push(EventQueue newEventQueue) {
   757     public void push(EventQueue newEventQueue) {
   710         if (eventLog.isLoggable(PlatformLogger.FINE)) {
   758         if (eventLog.isLoggable(PlatformLogger.FINE)) {
   711             eventLog.fine("EventQueue.push(" + newEventQueue + ")");
   759             eventLog.fine("EventQueue.push(" + newEventQueue + ")");
   712         }
   760         }
   713 
   761 
   714         if (nextQueue != null) {
   762         pushPopLock.lock();
   715             nextQueue.push(newEventQueue);
   763         try {
   716             return;
   764             EventQueue toPush = this;
   717         }
   765             while (toPush.nextQueue != null) {
   718 
   766                 toPush = toPush.nextQueue;
   719         synchronized (newEventQueue) {
   767             }
       
   768 
   720             // Transfer all events forward to new EventQueue.
   769             // Transfer all events forward to new EventQueue.
   721             while (peekEvent() != null) {
   770             while (toPush.peekEvent() != null) {
   722                 try {
   771                 try {
   723                     newEventQueue.postEventPrivate(getNextEvent());
   772                     newEventQueue.postEventPrivate(toPush.getNextEvent());
   724                 } catch (InterruptedException ie) {
   773                 } catch (InterruptedException ie) {
   725                     if (eventLog.isLoggable(PlatformLogger.FINE)) {
   774                     if (eventLog.isLoggable(PlatformLogger.FINE)) {
   726                         eventLog.fine("Interrupted push", ie);
   775                         eventLog.fine("Interrupted push", ie);
   727                     }
   776                     }
   728                 }
   777                 }
   729             }
   778             }
   730 
   779 
   731             newEventQueue.previousQueue = this;
   780             newEventQueue.previousQueue = toPush;
   732         }
   781 
   733         /*
   782             /*
   734          * Stop the event dispatch thread associated with the currently
   783              * Stop the event dispatch thread associated with the currently
   735          * active event queue, so that after the new queue is pushed
   784              * active event queue, so that after the new queue is pushed
   736          * on the top this event dispatch thread won't prevent AWT from
   785              * on the top this event dispatch thread won't prevent AWT from
   737          * being automatically shut down.
   786              * being automatically shut down.
   738          * Use stopDispatchingLater() to avoid deadlock: stopDispatching()
   787              * Use stopDispatchingLater() to avoid deadlock: stopDispatching()
   739          * waits for the dispatch thread to exit, so if the dispatch
   788              * waits for the dispatch thread to exit, which in turn waits
   740          * thread attempts to synchronize on this EventQueue object
   789              * for the lock in EQ.detachDispatchThread(), which is hold by
   741          * it will never exit since we already hold this lock.
   790              * this method.
   742          */
   791              */
   743         if (dispatchThread != null) {
   792             if (toPush.dispatchThread != null) {
   744             dispatchThread.stopDispatchingLater();
   793                 toPush.dispatchThread.stopDispatchingLater();
   745         }
   794             }
   746 
   795 
   747         nextQueue = newEventQueue;
   796             toPush.nextQueue = newEventQueue;
   748 
   797 
   749         AppContext appContext = AppContext.getAppContext();
   798             AppContext appContext = AppContext.getAppContext();
   750         if (appContext.get(AppContext.EVENT_QUEUE_KEY) == this) {
   799             if (appContext.get(AppContext.EVENT_QUEUE_KEY) == toPush) {
   751             appContext.put(AppContext.EVENT_QUEUE_KEY, newEventQueue);
   800                 appContext.put(AppContext.EVENT_QUEUE_KEY, newEventQueue);
       
   801             }
       
   802         } finally {
       
   803             pushPopLock.unlock();
   752         }
   804         }
   753     }
   805     }
   754 
   806 
   755     /**
   807     /**
   756      * Stops dispatching events using this <code>EventQueue</code>.
   808      * Stops dispatching events using this <code>EventQueue</code>.
   768     protected void pop() throws EmptyStackException {
   820     protected void pop() throws EmptyStackException {
   769         if (eventLog.isLoggable(PlatformLogger.FINE)) {
   821         if (eventLog.isLoggable(PlatformLogger.FINE)) {
   770             eventLog.fine("EventQueue.pop(" + this + ")");
   822             eventLog.fine("EventQueue.pop(" + this + ")");
   771         }
   823         }
   772 
   824 
   773         // To prevent deadlock, we lock on the previous EventQueue before
   825         EventDispatchThread dt = null;
   774         // this one.  This uses the same locking order as everything else
   826         pushPopLock.lock();
   775         // in EventQueue.java, so deadlock isn't possible.
   827         try {
   776         EventQueue prev = previousQueue;
   828             EventQueue toPop = this;
   777         synchronized ((prev != null) ? prev : this) {
   829             while (toPop.nextQueue != null) {
   778           synchronized(this) {
   830                 toPop = toPop.nextQueue;
   779             if (nextQueue != null) {
   831             }
   780                 nextQueue.pop();
   832             EventQueue prev = toPop.previousQueue;
   781                 return;
   833             if (prev == null) {
   782             }
       
   783             if (previousQueue == null) {
       
   784                 throw new EmptyStackException();
   834                 throw new EmptyStackException();
   785             }
   835             }
       
   836             toPop.previousQueue = null;
   786 
   837 
   787             // Transfer all events back to previous EventQueue.
   838             // Transfer all events back to previous EventQueue.
   788             previousQueue.nextQueue = null;
   839             prev.nextQueue = null;
   789             while (peekEvent() != null) {
   840             while (toPop.peekEvent() != null) {
   790                 try {
   841                 try {
   791                     previousQueue.postEventPrivate(getNextEvent());
   842                     prev.postEventPrivate(toPop.getNextEvent());
   792                 } catch (InterruptedException ie) {
   843                 } catch (InterruptedException ie) {
   793                     if (eventLog.isLoggable(PlatformLogger.FINE)) {
   844                     if (eventLog.isLoggable(PlatformLogger.FINE)) {
   794                         eventLog.fine("Interrupted pop", ie);
   845                         eventLog.fine("Interrupted pop", ie);
   795                     }
   846                     }
   796                 }
   847                 }
   797             }
   848             }
   798             AppContext appContext = AppContext.getAppContext();
   849             AppContext appContext = AppContext.getAppContext();
   799             if (appContext.get(AppContext.EVENT_QUEUE_KEY) == this) {
   850             if (appContext.get(AppContext.EVENT_QUEUE_KEY) == this) {
   800                 appContext.put(AppContext.EVENT_QUEUE_KEY, previousQueue);
   851                 appContext.put(AppContext.EVENT_QUEUE_KEY, prev);
   801             }
   852             }
   802 
   853 
   803             previousQueue = null;
   854             dt = toPop.dispatchThread;
   804           }
   855         } finally {
   805         }
   856             pushPopLock.unlock();
   806 
   857         }
   807         EventDispatchThread dt = this.dispatchThread;
   858 
   808         if (dt != null) {
   859         if (dt != null) {
   809             dt.stopDispatching(); // Must be done outside synchronized
   860             dt.stopDispatching(); // Must be done outside synchronized
   810                                   // block to avoid possible deadlock
   861                                   // block to avoid possible deadlock
   811         }
   862         }
   812     }
   863     }
   831      * @see             Toolkit#getSystemEventQueue
   882      * @see             Toolkit#getSystemEventQueue
   832      * @since           1.2
   883      * @since           1.2
   833      */
   884      */
   834     public static boolean isDispatchThread() {
   885     public static boolean isDispatchThread() {
   835         EventQueue eq = Toolkit.getEventQueue();
   886         EventQueue eq = Toolkit.getEventQueue();
   836         EventQueue next = eq.nextQueue;
   887         return eq.isDispatchThreadImpl();
   837         while (next != null) {
   888     }
   838             eq = next;
   889 
   839             next = eq.nextQueue;
   890     final boolean isDispatchThreadImpl() {
   840         }
   891         EventQueue eq = this;
   841         return (Thread.currentThread() == eq.dispatchThread);
   892         pushPopLock.lock();
       
   893         try {
       
   894             EventQueue next = eq.nextQueue;
       
   895             while (next != null) {
       
   896                 eq = next;
       
   897                 next = eq.nextQueue;
       
   898             }
       
   899             return (Thread.currentThread() == eq.dispatchThread);
       
   900         } finally {
       
   901             pushPopLock.unlock();
       
   902         }
   842     }
   903     }
   843 
   904 
   844     final void initDispatchThread() {
   905     final void initDispatchThread() {
   845         synchronized (this) {
   906         pushPopLock.lock();
       
   907         try {
   846             AppContext appContext = AppContext.getAppContext();
   908             AppContext appContext = AppContext.getAppContext();
   847             if (dispatchThread == null && !threadGroup.isDestroyed() && !appContext.isDisposed()) {
   909             if (dispatchThread == null && !threadGroup.isDestroyed() && !appContext.isDisposed()) {
   848                 dispatchThread = (EventDispatchThread)
   910                 dispatchThread = (EventDispatchThread)
   849                     AccessController.doPrivileged(new PrivilegedAction() {
   911                     AccessController.doPrivileged(new PrivilegedAction() {
   850                         public Object run() {
   912                         public Object run() {
   859                         }
   921                         }
   860                     });
   922                     });
   861                 AWTAutoShutdown.getInstance().notifyThreadBusy(dispatchThread);
   923                 AWTAutoShutdown.getInstance().notifyThreadBusy(dispatchThread);
   862                 dispatchThread.start();
   924                 dispatchThread.start();
   863             }
   925             }
   864         }
   926         } finally {
   865     }
   927             pushPopLock.unlock();
   866 
   928         }
   867     final void detachDispatchThread() {
   929     }
   868         dispatchThread = null;
   930 
       
   931     final void detachDispatchThread(EventDispatchThread edt, boolean restart) {
       
   932         /*
       
   933          * This synchronized block is to secure that the event dispatch
       
   934          * thread won't die in the middle of posting a new event to the
       
   935          * associated event queue. It is important because we notify
       
   936          * that the event dispatch thread is busy after posting a new event
       
   937          * to its queue, so the EventQueue.dispatchThread reference must
       
   938          * be valid at that point.
       
   939          */
       
   940         pushPopLock.lock();
       
   941         try {
       
   942             EventDispatchThread oldDispatchThread = dispatchThread;
       
   943             if (dispatchThread == edt) {
       
   944                 dispatchThread = null;
       
   945             }
       
   946             if (restart) {
       
   947                 /*
       
   948                  * Event dispatch thread dies in case of an uncaught exception.
       
   949                  * A new event dispatch thread for this queue will be started
       
   950                  * only if a new event is posted to it. In case if no more
       
   951                  * events are posted after this thread died all events that
       
   952                  * currently are in the queue will never be dispatched.
       
   953                  *
       
   954                  * Fix for 4648733. Check both the associated java event
       
   955                  * queue and the PostEventQueue.
       
   956                  */
       
   957                 if ((peekEvent() != null) || !SunToolkit.isPostEventQueueEmpty()) {
       
   958                     initDispatchThread();
       
   959                 }
       
   960                 AWTAutoShutdown.getInstance().notifyThreadFree(oldDispatchThread);
       
   961             }
       
   962         } finally {
       
   963             pushPopLock.unlock();
       
   964         }
   869     }
   965     }
   870 
   966 
   871     /*
   967     /*
   872      * Gets the <code>EventDispatchThread</code> for this
   968      * Gets the <code>EventDispatchThread</code> for this
   873      * <code>EventQueue</code>.
   969      * <code>EventQueue</code>.
   876      *         working thread associated with it
   972      *         working thread associated with it
   877      * @see    java.awt.EventQueue#initDispatchThread
   973      * @see    java.awt.EventQueue#initDispatchThread
   878      * @see    java.awt.EventQueue#detachDispatchThread
   974      * @see    java.awt.EventQueue#detachDispatchThread
   879      */
   975      */
   880     final EventDispatchThread getDispatchThread() {
   976     final EventDispatchThread getDispatchThread() {
   881         return dispatchThread;
   977         pushPopLock.lock();
       
   978         try {
       
   979             return dispatchThread;
       
   980         } finally {
       
   981             pushPopLock.unlock();
       
   982         }
   882     }
   983     }
   883 
   984 
   884     /*
   985     /*
   885      * Removes any pending events for the specified source object.
   986      * Removes any pending events for the specified source object.
   886      * If removeAllEvents parameter is <code>true</code> then all
   987      * If removeAllEvents parameter is <code>true</code> then all
   893      * This method is normally called by the source's
   994      * This method is normally called by the source's
   894      * <code>removeNotify</code> method.
   995      * <code>removeNotify</code> method.
   895      */
   996      */
   896     final void removeSourceEvents(Object source, boolean removeAllEvents) {
   997     final void removeSourceEvents(Object source, boolean removeAllEvents) {
   897         SunToolkit.flushPendingEvents();
   998         SunToolkit.flushPendingEvents();
   898         synchronized (this) {
   999         pushPopLock.lock();
       
  1000         try {
   899             for (int i = 0; i < NUM_PRIORITIES; i++) {
  1001             for (int i = 0; i < NUM_PRIORITIES; i++) {
   900                 EventQueueItem entry = queues[i].head;
  1002                 EventQueueItem entry = queues[i].head;
   901                 EventQueueItem prev = null;
  1003                 EventQueueItem prev = null;
   902                 while (entry != null) {
  1004                 while (entry != null) {
   903                     if ((entry.event.getSource() == source)
  1005                     if ((entry.event.getSource() == source)
   926                     }
  1028                     }
   927                     entry = entry.next;
  1029                     entry = entry.next;
   928                 }
  1030                 }
   929                 queues[i].tail = prev;
  1031                 queues[i].tail = prev;
   930             }
  1032             }
       
  1033         } finally {
       
  1034             pushPopLock.unlock();
   931         }
  1035         }
   932     }
  1036     }
   933 
  1037 
   934     static void setCurrentEventAndMostRecentTime(AWTEvent e) {
  1038     static void setCurrentEventAndMostRecentTime(AWTEvent e) {
   935         Toolkit.getEventQueue().setCurrentEventAndMostRecentTimeImpl(e);
  1039         Toolkit.getEventQueue().setCurrentEventAndMostRecentTimeImpl(e);
   936     }
  1040     }
   937     private synchronized void setCurrentEventAndMostRecentTimeImpl(AWTEvent e)
  1041     private void setCurrentEventAndMostRecentTimeImpl(AWTEvent e) {
   938     {
  1042         pushPopLock.lock();
   939         if (Thread.currentThread() != dispatchThread) {
  1043         try {
   940             return;
  1044             if (Thread.currentThread() != dispatchThread) {
   941         }
  1045                 return;
   942 
  1046             }
   943         currentEvent = new WeakReference(e);
  1047 
   944 
  1048             currentEvent = new WeakReference(e);
   945         // This series of 'instanceof' checks should be replaced with a
  1049 
   946         // polymorphic type (for example, an interface which declares a
  1050             // This series of 'instanceof' checks should be replaced with a
   947         // getWhen() method). However, this would require us to make such
  1051             // polymorphic type (for example, an interface which declares a
   948         // a type public, or to place it in sun.awt. Both of these approaches
  1052             // getWhen() method). However, this would require us to make such
   949         // have been frowned upon. So for now, we hack.
  1053             // a type public, or to place it in sun.awt. Both of these approaches
   950         //
  1054             // have been frowned upon. So for now, we hack.
   951         // In tiger, we will probably give timestamps to all events, so this
  1055             //
   952         // will no longer be an issue.
  1056             // In tiger, we will probably give timestamps to all events, so this
   953         long mostRecentEventTime2 = Long.MIN_VALUE;
  1057             // will no longer be an issue.
   954         if (e instanceof InputEvent) {
  1058             long mostRecentEventTime2 = Long.MIN_VALUE;
   955             InputEvent ie = (InputEvent)e;
  1059             if (e instanceof InputEvent) {
   956             mostRecentEventTime2 = ie.getWhen();
  1060                 InputEvent ie = (InputEvent)e;
   957         } else if (e instanceof InputMethodEvent) {
  1061                 mostRecentEventTime2 = ie.getWhen();
   958             InputMethodEvent ime = (InputMethodEvent)e;
  1062             } else if (e instanceof InputMethodEvent) {
   959             mostRecentEventTime2 = ime.getWhen();
  1063                 InputMethodEvent ime = (InputMethodEvent)e;
   960         } else if (e instanceof ActionEvent) {
  1064                 mostRecentEventTime2 = ime.getWhen();
   961             ActionEvent ae = (ActionEvent)e;
  1065             } else if (e instanceof ActionEvent) {
   962             mostRecentEventTime2 = ae.getWhen();
  1066                 ActionEvent ae = (ActionEvent)e;
   963         } else if (e instanceof InvocationEvent) {
  1067                 mostRecentEventTime2 = ae.getWhen();
   964             InvocationEvent ie = (InvocationEvent)e;
  1068             } else if (e instanceof InvocationEvent) {
   965             mostRecentEventTime2 = ie.getWhen();
  1069                 InvocationEvent ie = (InvocationEvent)e;
   966         }
  1070                 mostRecentEventTime2 = ie.getWhen();
   967         mostRecentEventTime = Math.max(mostRecentEventTime, mostRecentEventTime2);
  1071             }
       
  1072             mostRecentEventTime = Math.max(mostRecentEventTime, mostRecentEventTime2);
       
  1073         } finally {
       
  1074             pushPopLock.unlock();
       
  1075         }
   968     }
  1076     }
   969 
  1077 
   970     /**
  1078     /**
   971      * Causes <code>runnable</code> to have its <code>run</code>
  1079      * Causes <code>runnable</code> to have its <code>run</code>
   972      * method called in the {@link #isDispatchThread dispatch thread} of
  1080      * method called in the {@link #isDispatchThread dispatch thread} of
  1043      * appeared. First it proceeds to the EventQueue on the top of the
  1151      * appeared. First it proceeds to the EventQueue on the top of the
  1044      * stack, then notifies the associated dispatch thread if it exists
  1152      * stack, then notifies the associated dispatch thread if it exists
  1045      * or starts a new one otherwise.
  1153      * or starts a new one otherwise.
  1046      */
  1154      */
  1047     private void wakeup(boolean isShutdown) {
  1155     private void wakeup(boolean isShutdown) {
  1048         synchronized(this) {
  1156         pushPopLock.lock();
       
  1157         try {
  1049             if (nextQueue != null) {
  1158             if (nextQueue != null) {
  1050                 // Forward call to the top of EventQueue stack.
  1159                 // Forward call to the top of EventQueue stack.
  1051                 nextQueue.wakeup(isShutdown);
  1160                 nextQueue.wakeup(isShutdown);
  1052             } else if (dispatchThread != null) {
  1161             } else if (dispatchThread != null) {
  1053                 notifyAll();
  1162                 pushPopCond.signalAll();
  1054             } else if (!isShutdown) {
  1163             } else if (!isShutdown) {
  1055                 initDispatchThread();
  1164                 initDispatchThread();
  1056             }
  1165             }
       
  1166         } finally {
       
  1167             pushPopLock.unlock();
  1057         }
  1168         }
  1058     }
  1169     }
  1059 }
  1170 }
  1060 
  1171 
  1061 /**
  1172 /**