24 */ 25 26 package sun.awt; 27 28 import java.awt.AWTEvent; 29 import java.security.AccessController; 30 import java.security.PrivilegedAction; 31 import java.util.HashSet; 32 import java.util.IdentityHashMap; 33 import java.util.Map; 34 import java.util.Set; 35 36 import sun.awt.util.ThreadGroupUtils; 37 import sun.misc.ManagedLocalsThread; 38 import sun.util.logging.PlatformLogger; 39 40 /** 41 * This class is to let AWT shutdown automatically when a user is done 42 * with AWT. It tracks AWT state using the following parameters: 43 * <ul> 44 * <li><code>peerMap</code> - the map between the existing peer objects 45 * and their associated targets 46 * <li><code>toolkitThreadBusy</code> - whether the toolkit thread 47 * is waiting for a new native event to appear in its queue 48 * or is dispatching an event 49 * <li><code>busyThreadSet</code> - a set of all the event dispatch 50 * threads that are busy at this moment, i.e. those that are not 51 * waiting for a new event to appear in their event queue. 52 * </ul><p> 53 * AWT is considered to be in ready-to-shutdown state when 54 * <code>peerMap</code> is empty and <code>toolkitThreadBusy</code> 55 * is false and <code>busyThreadSet</code> is empty. 56 * The internal AWTAutoShutdown logic secures that the single non-daemon 57 * thread (<code>blockerThread</code>) is running when AWT is not in 58 * ready-to-shutdown state. This blocker thread is to prevent AWT from 59 * exiting since the toolkit thread is now daemon and all the event 60 * dispatch threads are started only when needed. Once it is detected 61 * that AWT is in ready-to-shutdown state this blocker thread waits 62 * for a certain timeout and if AWT state doesn't change during timeout 63 * this blocker thread terminates all the event dispatch threads and 64 * exits. 65 */ 66 public final class AWTAutoShutdown implements Runnable { 67 68 private static final AWTAutoShutdown theInstance = new AWTAutoShutdown(); 69 70 /** 71 * This lock object is used to synchronize shutdown operations. 72 */ 73 private final Object mainLock = new Object(); 74 75 /** 76 * This lock object is to secure that when a new blocker thread is 77 * started it will be the first who acquire the main lock after 212 * has been created or some existing peer has been disposed. 213 * 214 * @see AWTAutoShutdown#isReadyToShutdown 215 */ 216 void notifyPeerMapUpdated() { 217 synchronized (activationLock) { 218 synchronized (mainLock) { 219 if (!isReadyToShutdown() && blockerThread == null) { 220 activateBlockerThread(); 221 } else { 222 mainLock.notifyAll(); 223 timeoutPassed = false; 224 } 225 } 226 } 227 } 228 229 /** 230 * Determine whether AWT is currently in ready-to-shutdown state. 231 * AWT is considered to be in ready-to-shutdown state if 232 * <code>peerMap</code> is empty and <code>toolkitThreadBusy</code> 233 * is false and <code>busyThreadSet</code> is empty. 234 * 235 * @return true if AWT is in ready-to-shutdown state. 236 */ 237 private boolean isReadyToShutdown() { 238 return (!toolkitThreadBusy && 239 peerMap.isEmpty() && 240 busyThreadSet.isEmpty()); 241 } 242 243 /** 244 * Notify about the toolkit thread state change. 245 * 246 * @param busy true if the toolkit thread state changes from idle 247 * to busy. 248 * @see AWTAutoShutdown#notifyToolkitThreadBusy 249 * @see AWTAutoShutdown#notifyToolkitThreadFree 250 * @see AWTAutoShutdown#isReadyToShutdown 251 */ 252 private void setToolkitBusy(final boolean busy) { 253 if (busy != toolkitThreadBusy) { | 24 */ 25 26 package sun.awt; 27 28 import java.awt.AWTEvent; 29 import java.security.AccessController; 30 import java.security.PrivilegedAction; 31 import java.util.HashSet; 32 import java.util.IdentityHashMap; 33 import java.util.Map; 34 import java.util.Set; 35 36 import sun.awt.util.ThreadGroupUtils; 37 import sun.misc.ManagedLocalsThread; 38 import sun.util.logging.PlatformLogger; 39 40 /** 41 * This class is to let AWT shutdown automatically when a user is done 42 * with AWT. It tracks AWT state using the following parameters: 43 * <ul> 44 * <li>{@code peerMap} - the map between the existing peer objects 45 * and their associated targets 46 * <li>{@code toolkitThreadBusy} - whether the toolkit thread 47 * is waiting for a new native event to appear in its queue 48 * or is dispatching an event 49 * <li>{@code busyThreadSet} - a set of all the event dispatch 50 * threads that are busy at this moment, i.e. those that are not 51 * waiting for a new event to appear in their event queue. 52 * </ul><p> 53 * AWT is considered to be in ready-to-shutdown state when 54 * {@code peerMap} is empty and {@code toolkitThreadBusy} 55 * is false and {@code busyThreadSet} is empty. 56 * The internal AWTAutoShutdown logic secures that the single non-daemon 57 * thread ({@code blockerThread}) is running when AWT is not in 58 * ready-to-shutdown state. This blocker thread is to prevent AWT from 59 * exiting since the toolkit thread is now daemon and all the event 60 * dispatch threads are started only when needed. Once it is detected 61 * that AWT is in ready-to-shutdown state this blocker thread waits 62 * for a certain timeout and if AWT state doesn't change during timeout 63 * this blocker thread terminates all the event dispatch threads and 64 * exits. 65 */ 66 public final class AWTAutoShutdown implements Runnable { 67 68 private static final AWTAutoShutdown theInstance = new AWTAutoShutdown(); 69 70 /** 71 * This lock object is used to synchronize shutdown operations. 72 */ 73 private final Object mainLock = new Object(); 74 75 /** 76 * This lock object is to secure that when a new blocker thread is 77 * started it will be the first who acquire the main lock after 212 * has been created or some existing peer has been disposed. 213 * 214 * @see AWTAutoShutdown#isReadyToShutdown 215 */ 216 void notifyPeerMapUpdated() { 217 synchronized (activationLock) { 218 synchronized (mainLock) { 219 if (!isReadyToShutdown() && blockerThread == null) { 220 activateBlockerThread(); 221 } else { 222 mainLock.notifyAll(); 223 timeoutPassed = false; 224 } 225 } 226 } 227 } 228 229 /** 230 * Determine whether AWT is currently in ready-to-shutdown state. 231 * AWT is considered to be in ready-to-shutdown state if 232 * {@code peerMap} is empty and {@code toolkitThreadBusy} 233 * is false and {@code busyThreadSet} is empty. 234 * 235 * @return true if AWT is in ready-to-shutdown state. 236 */ 237 private boolean isReadyToShutdown() { 238 return (!toolkitThreadBusy && 239 peerMap.isEmpty() && 240 busyThreadSet.isEmpty()); 241 } 242 243 /** 244 * Notify about the toolkit thread state change. 245 * 246 * @param busy true if the toolkit thread state changes from idle 247 * to busy. 248 * @see AWTAutoShutdown#notifyToolkitThreadBusy 249 * @see AWTAutoShutdown#notifyToolkitThreadFree 250 * @see AWTAutoShutdown#isReadyToShutdown 251 */ 252 private void setToolkitBusy(final boolean busy) { 253 if (busy != toolkitThreadBusy) { |