< prev index next >

src/java.desktop/share/classes/java/awt/WaitDispatchSupport.java

Print this page




  29 import java.util.TimerTask;
  30 import java.util.concurrent.atomic.AtomicBoolean;
  31 
  32 import java.security.PrivilegedAction;
  33 import java.security.AccessController;
  34 
  35 import sun.awt.PeerEvent;
  36 
  37 import sun.util.logging.PlatformLogger;
  38 
  39 /**
  40  * This utility class is used to suspend execution on a thread
  41  * while still allowing {@code EventDispatchThread} to dispatch events.
  42  * The API methods of the class are thread-safe.
  43  *
  44  * @author Anton Tarasov, Artem Ananiev
  45  *
  46  * @since 1.7
  47  */
  48 class WaitDispatchSupport implements SecondaryLoop {
  49 
  50     private final static PlatformLogger log =
  51         PlatformLogger.getLogger("java.awt.event.WaitDispatchSupport");
  52 
  53     private EventDispatchThread dispatchThread;
  54     private EventFilter filter;
  55 
  56     private volatile Conditional extCondition;
  57     private volatile Conditional condition;
  58 
  59     private long interval;
  60     // Use a shared daemon timer to serve all the WaitDispatchSupports
  61     private static Timer timer;
  62     // When this WDS expires, we cancel the timer task leaving the
  63     // shared timer up and running
  64     private TimerTask timerTask;
  65 
  66     private AtomicBoolean keepBlockingEDT = new AtomicBoolean(false);
  67     private AtomicBoolean keepBlockingCT = new AtomicBoolean(false);

  68 
  69     private static synchronized void initializeTimer() {
  70         if (timer == null) {
  71             timer = new Timer("AWT-WaitDispatchSupport-Timer", true);
  72         }
  73     }
  74 
  75     /**
  76      * Creates a {@code WaitDispatchSupport} instance to
  77      * serve the given event dispatch thread.
  78      *
  79      * @param dispatchThread An event dispatch thread that
  80      *        should not stop dispatching events while waiting
  81      *
  82      * @since 1.7
  83      */
  84     public WaitDispatchSupport(EventDispatchThread dispatchThread) {
  85         this(dispatchThread, null);
  86     }
  87 


 217                     log.fine("Dispose current SequencedEvent: " + currentSE);
 218                 }
 219                 currentSE.dispose();
 220             }
 221             // In case the exit() method is called before starting
 222             // new event pump it will post the waking event to EDT.
 223             // The event will be handled after the new event pump
 224             // starts. Thus, the enter() method will not hang.
 225             //
 226             // Event pump should be privileged. See 6300270.
 227             AccessController.doPrivileged(new PrivilegedAction<Void>() {
 228                 public Void run() {
 229                     run.run();
 230                     return null;
 231                 }
 232             });
 233         } else {
 234             if (log.isLoggable(PlatformLogger.Level.FINEST)) {
 235                 log.finest("On non-dispatch thread: " + currentThread);
 236             }

 237             synchronized (getTreeLock()) {

 238                 if (filter != null) {
 239                     dispatchThread.addEventFilter(filter);
 240                 }
 241                 try {
 242                     EventQueue eq = dispatchThread.getEventQueue();
 243                     eq.postEvent(new PeerEvent(this, run, PeerEvent.PRIORITY_EVENT));
 244                     keepBlockingCT.set(true);
 245                     if (interval > 0) {
 246                         long currTime = System.currentTimeMillis();
 247                         while (keepBlockingCT.get() &&
 248                                ((extCondition != null) ? extCondition.evaluate() : true) &&
 249                                (currTime + interval > System.currentTimeMillis()))
 250                         {
 251                             getTreeLock().wait(interval);
 252                         }
 253                     } else {
 254                         while (keepBlockingCT.get() &&
 255                                ((extCondition != null) ? extCondition.evaluate() : true))
 256                         {
 257                             getTreeLock().wait();
 258                         }
 259                     }
 260                     if (log.isLoggable(PlatformLogger.Level.FINE)) {
 261                         log.fine("waitDone " + keepBlockingEDT.get() + " " + keepBlockingCT.get());
 262                     }
 263                 } catch (InterruptedException e) {
 264                     if (log.isLoggable(PlatformLogger.Level.FINE)) {
 265                         log.fine("Exception caught while waiting: " + e);
 266                     }
 267                 } finally {
 268                     if (filter != null) {
 269                         dispatchThread.removeEventFilter(filter);
 270                     }
 271                 }
 272                 // If the waiting process has been stopped because of the
 273                 // time interval passed or an exception occurred, the state
 274                 // should be changed
 275                 keepBlockingEDT.set(false);
 276                 keepBlockingCT.set(false);




 277             }
 278         }
 279 
 280         return true;
 281     }
 282 
 283     /**
 284      * {@inheritDoc}
 285      */
 286     public boolean exit() {
 287         if (log.isLoggable(PlatformLogger.Level.FINE)) {
 288             log.fine("exit(): blockingEDT=" + keepBlockingEDT.get() +
 289                      ", blockingCT=" + keepBlockingCT.get());
 290         }
 291         if (keepBlockingEDT.compareAndSet(true, false)) {










 292             wakeupEDT();
 293             return true;
 294         }




 295         return false;
 296     }

 297 
 298     private final static Object getTreeLock() {
 299         return Component.LOCK;
 300     }
 301 
 302     private final Runnable wakingRunnable = new Runnable() {
 303         public void run() {
 304             log.fine("Wake up EDT");



 305             synchronized (getTreeLock()) {
 306                 keepBlockingCT.set(false);
 307                 getTreeLock().notifyAll();

 308             }
 309             log.fine("Wake up EDT done");
 310         }
 311     };
 312 
 313     private void wakeupEDT() {
 314         if (log.isLoggable(PlatformLogger.Level.FINEST)) {
 315             log.finest("wakeupEDT(): EDT == " + dispatchThread);
 316         }
 317         EventQueue eq = dispatchThread.getEventQueue();
 318         eq.postEvent(new PeerEvent(this, wakingRunnable, PeerEvent.PRIORITY_EVENT));
 319     }
 320 }


  29 import java.util.TimerTask;
  30 import java.util.concurrent.atomic.AtomicBoolean;
  31 
  32 import java.security.PrivilegedAction;
  33 import java.security.AccessController;
  34 
  35 import sun.awt.PeerEvent;
  36 
  37 import sun.util.logging.PlatformLogger;
  38 
  39 /**
  40  * This utility class is used to suspend execution on a thread
  41  * while still allowing {@code EventDispatchThread} to dispatch events.
  42  * The API methods of the class are thread-safe.
  43  *
  44  * @author Anton Tarasov, Artem Ananiev
  45  *
  46  * @since 1.7
  47  */
  48 class WaitDispatchSupport implements SecondaryLoop {

  49     private final static PlatformLogger log =
  50             PlatformLogger.getLogger("java.awt.event.WaitDispatchSupport");
  51 
  52     private EventDispatchThread dispatchThread;
  53     private EventFilter filter;
  54 
  55     private volatile Conditional extCondition;
  56     private volatile Conditional condition;
  57 
  58     private long interval;
  59     // Use a shared daemon timer to serve all the WaitDispatchSupports
  60     private static Timer timer;
  61     // When this WDS expires, we cancel the timer task leaving the
  62     // shared timer up and running
  63     private TimerTask timerTask;
  64 
  65     private AtomicBoolean keepBlockingEDT = new AtomicBoolean(false);
  66     private AtomicBoolean keepBlockingCT = new AtomicBoolean(false);
  67     private AtomicBoolean prematureExit = new AtomicBoolean(false);
  68 
  69     private static synchronized void initializeTimer() {
  70         if (timer == null) {
  71             timer = new Timer("AWT-WaitDispatchSupport-Timer", true);
  72         }
  73     }
  74 
  75     /**
  76      * Creates a {@code WaitDispatchSupport} instance to
  77      * serve the given event dispatch thread.
  78      *
  79      * @param dispatchThread An event dispatch thread that
  80      *                       should not stop dispatching events while waiting
  81      *
  82      * @since 1.7
  83      */
  84     public WaitDispatchSupport(EventDispatchThread dispatchThread) {
  85         this(dispatchThread, null);
  86     }
  87 


 217                     log.fine("Dispose current SequencedEvent: " + currentSE);
 218                 }
 219                 currentSE.dispose();
 220             }
 221             // In case the exit() method is called before starting
 222             // new event pump it will post the waking event to EDT.
 223             // The event will be handled after the new event pump
 224             // starts. Thus, the enter() method will not hang.
 225             //
 226             // Event pump should be privileged. See 6300270.
 227             AccessController.doPrivileged(new PrivilegedAction<Void>() {
 228                 public Void run() {
 229                     run.run();
 230                     return null;
 231                 }
 232             });
 233         } else {
 234             if (log.isLoggable(PlatformLogger.Level.FINEST)) {
 235                 log.finest("On non-dispatch thread: " + currentThread);
 236             }
 237             keepBlockingCT.set(true);
 238             synchronized (getTreeLock()) {
 239                 if (keepBlockingEDT.get()  && !prematureExit.get()) {
 240                     if (filter != null) {
 241                         dispatchThread.addEventFilter(filter);
 242                     }
 243                     try {
 244                         EventQueue eq = dispatchThread.getEventQueue();
 245                         eq.postEvent(new PeerEvent(this, run, PeerEvent.PRIORITY_EVENT));

 246                         if (interval > 0) {
 247                             long currTime = System.currentTimeMillis();
 248                             while (keepBlockingCT.get() &&
 249                                    ((extCondition != null) ? extCondition.evaluate() : true) &&
 250                                    (currTime + interval > System.currentTimeMillis()))
 251                             {
 252                                 getTreeLock().wait(interval);
 253                             }
 254                         } else {
 255                             while (keepBlockingCT.get() &&
 256                                    ((extCondition != null) ? extCondition.evaluate() : true))
 257                             {
 258                                 getTreeLock().wait();
 259                             }
 260                         }
 261                         if (log.isLoggable(PlatformLogger.Level.FINE)) {
 262                             log.fine("waitDone " + keepBlockingEDT.get() + " " + keepBlockingCT.get());
 263                         }
 264                     } catch (InterruptedException e) {
 265                         if (log.isLoggable(PlatformLogger.Level.FINE)) {
 266                             log.fine("Exception caught while waiting: " + e);
 267                         }
 268                     } finally {
 269                         if (filter != null) {
 270                             dispatchThread.removeEventFilter(filter);
 271                         }
 272                     }
 273                     // If the waiting process has been stopped because of the
 274                     // time interval passed or an exception occurred, the state
 275                     // should be changed
 276                     keepBlockingEDT.set(false);
 277                     keepBlockingCT.set(false);
 278                 } else {
 279                     // We get here when exit called after but happened concurrently
 280                     keepBlockingCT.set(false);
 281                     prematureExit.set(true);
 282                 }
 283             }
 284         }
 285         return !prematureExit.getAndSet(false);
 286     }
 287 
 288     /**
 289      * {@inheritDoc}
 290      */
 291     public boolean exit() {
 292         if (log.isLoggable(PlatformLogger.Level.FINE)) {
 293             log.fine("exit(): blockingEDT=" + keepBlockingEDT.get() +
 294                      ", blockingCT=" + keepBlockingCT.get());
 295         }
 296         if(keepBlockingCT.get()) {
 297             // enter() is waiting in non-dispatch thread
 298             synchronized (getTreeLock()) {
 299                 keepBlockingEDT.set(false);
 300                 prematureExit.set(false);
 301                 wakeupEDT();
 302                 return true;
 303             }
 304         } else {
 305             if (keepBlockingEDT.getAndSet(false)) {
 306                 prematureExit.set(false);
 307                 wakeupEDT();
 308                 return true;
 309             }
 310             // exit() call before enter()
 311             prematureExit.set(true);
 312             // Still need to wake up it can be a concurrent exit()
 313             wakeupEDT();
 314             return false;
 315         }
 316     }
 317 
 318     private final static Object getTreeLock() {
 319         return Component.LOCK;
 320     }
 321 
 322     private final Runnable wakingRunnable = new Runnable() {
 323         public void run() {
 324             log.fine("Wake up EDT");
 325             keepBlockingEDT.set(false);
 326             if (keepBlockingCT.get()) {
 327                 // Notify only if enter() waiting in non-dispatch thread
 328                 synchronized (getTreeLock()) {
 329                     keepBlockingCT.set(false);
 330                     getTreeLock().notifyAll();
 331                 }
 332             }
 333             log.fine("Wake up EDT done");
 334         }
 335     };
 336 
 337     private void wakeupEDT() {
 338         if (log.isLoggable(PlatformLogger.Level.FINEST)) {
 339             log.finest("wakeupEDT(): EDT == " + dispatchThread);
 340         }
 341         EventQueue eq = dispatchThread.getEventQueue();
 342         eq.postEvent(new PeerEvent(this, wakingRunnable, PeerEvent.PRIORITY_EVENT));
 343     }
 344 }
< prev index next >