6623943: javax.swing.TimerQueue's thread occasionally fails to start
authoridk
Mon, 23 Jun 2008 15:21:37 -0400
changeset 1273 3b2eba521268
parent 1272 40d9533e1505
child 1274 5561e281cda6
6623943: javax.swing.TimerQueue's thread occasionally fails to start Reviewed-by: alexp
jdk/src/share/classes/javax/swing/JApplet.java
jdk/src/share/classes/javax/swing/TimerQueue.java
--- a/jdk/src/share/classes/javax/swing/JApplet.java	Thu Jun 19 18:03:43 2008 +0400
+++ b/jdk/src/share/classes/javax/swing/JApplet.java	Mon Jun 23 15:21:37 2008 -0400
@@ -131,10 +131,7 @@
         // Check the timerQ and restart if necessary.
         TimerQueue q = TimerQueue.sharedInstance();
         if(q != null) {
-            synchronized(q) {
-                if(!q.running)
-                    q.start();
-            }
+            q.startIfNeeded();
         }
 
         /* Workaround for bug 4155072.  The shared double buffer image
--- a/jdk/src/share/classes/javax/swing/TimerQueue.java	Thu Jun 19 18:03:43 2008 +0400
+++ b/jdk/src/share/classes/javax/swing/TimerQueue.java	Mon Jun 23 15:21:37 2008 -0400
@@ -31,6 +31,7 @@
 
 import java.util.*;
 import java.util.concurrent.*;
+import java.util.concurrent.locks.*;
 import java.util.concurrent.atomic.AtomicLong;
 import sun.awt.AppContext;
 
@@ -52,7 +53,8 @@
         new StringBuffer("TimerQueue.expiredTimersKey");
 
     private final DelayQueue<DelayedTimer> queue;
-    volatile boolean running;
+    private volatile boolean running;
+    private final Lock runningLock;
 
     /* Lock object used in place of class object for synchronization.
      * (4187686)
@@ -69,7 +71,8 @@
         super();
         queue = new DelayQueue<DelayedTimer>();
         // Now start the TimerQueue thread.
-        start();
+        runningLock = new ReentrantLock();
+        startIfNeeded();
     }
 
 
@@ -87,33 +90,30 @@
     }
 
 
-    synchronized void start() {
-        if (running) {
-            throw new RuntimeException("Can't start a TimerQueue " +
-                                       "that is already running");
-        }
-        else {
-            final ThreadGroup threadGroup =
-                AppContext.getAppContext().getThreadGroup();
-            java.security.AccessController.doPrivileged(
-                new java.security.PrivilegedAction() {
-                public Object run() {
-                    Thread timerThread = new Thread(threadGroup, TimerQueue.this,
-                                                    "TimerQueue");
-                    timerThread.setDaemon(true);
-                    timerThread.setPriority(Thread.NORM_PRIORITY);
-                    timerThread.start();
-                    return null;
-                }
-            });
-            running = true;
+    void startIfNeeded() {
+        if (! running) {
+            runningLock.lock();
+            try {
+                final ThreadGroup threadGroup =
+                    AppContext.getAppContext().getThreadGroup();
+                java.security.AccessController.doPrivileged(
+                    new java.security.PrivilegedAction() {
+                    public Object run() {
+                        Thread timerThread = new Thread(threadGroup, TimerQueue.this,
+                                                        "TimerQueue");
+                        timerThread.setDaemon(true);
+                        timerThread.setPriority(Thread.NORM_PRIORITY);
+                        timerThread.start();
+                        return null;
+                    }
+                });
+                running = true;
+            } finally {
+                runningLock.unlock();
+            }
         }
     }
 
-     synchronized void stop() {
-         running = false;
-     }
-
     void addTimer(Timer timer, long delayMillis) {
         timer.getLock().lock();
         try {
@@ -164,6 +164,7 @@
 
 
     public void run() {
+        runningLock.lock();
         try {
             while (running) {
                 try {
@@ -195,14 +196,14 @@
             }
         }
         catch (ThreadDeath td) {
-            synchronized (this) {
-                running = false;
-                // Mark all the timers we contain as not being queued.
-                for (DelayedTimer delayedTimer : queue) {
-                    delayedTimer.getTimer().cancelEvent();
-                }
-                throw td;
+            // Mark all the timers we contain as not being queued.
+            for (DelayedTimer delayedTimer : queue) {
+                delayedTimer.getTimer().cancelEvent();
             }
+            throw td;
+        } finally {
+            running = false;
+            runningLock.unlock();
         }
     }