Author: jochen
Date: Wed Apr 29 19:54:33 2009
New Revision: 769900

URL: http://svn.apache.org/viewvc?rev=769900&view=rev
Log:
PR: XMLRPC-168
Fixed a deadlock in the ThreadPool.

Modified:
    
webservices/xmlrpc/trunk/common/src/main/java/org/apache/xmlrpc/util/ThreadPool.java
    webservices/xmlrpc/trunk/src/changes/changes.xml

Modified: 
webservices/xmlrpc/trunk/common/src/main/java/org/apache/xmlrpc/util/ThreadPool.java
URL: 
http://svn.apache.org/viewvc/webservices/xmlrpc/trunk/common/src/main/java/org/apache/xmlrpc/util/ThreadPool.java?rev=769900&r1=769899&r2=769900&view=diff
==============================================================================
--- 
webservices/xmlrpc/trunk/common/src/main/java/org/apache/xmlrpc/util/ThreadPool.java
 (original)
+++ 
webservices/xmlrpc/trunk/common/src/main/java/org/apache/xmlrpc/util/ThreadPool.java
 Wed Apr 29 19:54:33 2009
@@ -45,18 +45,18 @@
     }
 
     private class Poolable {
-        private boolean shuttingDown;
+        private volatile boolean shuttingDown;
         private Task task;
         private Thread thread;
         Poolable(ThreadGroup pGroup, int pNum) {
             thread = new Thread(pGroup, pGroup.getName() + "-" + pNum){
                 public void run() {
-                    while (!isShuttingDown()) {
+                    while (!shuttingDown) {
                         final Task t = getTask();
                         if (t == null) {
                             try {
                                 synchronized (this) {
-                                    if (!isShuttingDown()  &&  getTask() == 
null) {
+                                    if (!shuttingDown  &&  getTask() == null) {
                                         wait();
                                     }
                                 }
@@ -69,7 +69,8 @@
                                 resetTask();
                                 repool(Poolable.this);
                             } catch (Throwable e) {
-                                discard(Poolable.this);
+                                remove(Poolable.this);
+                                Poolable.this.shutdown();
                                 resetTask();
                             }
                         }
@@ -93,15 +94,13 @@
                 thread.notify();
             }
         }
-        private synchronized boolean isShuttingDown() { return shuttingDown; }
-        String getName() { return thread.getName(); }
-        private synchronized Task getTask() {
+        private Task getTask() {
             return task;
         }
-        private synchronized void resetTask() {
+        private void resetTask() {
             task = null;
         }
-        synchronized void start(Task pTask) {
+        void start(Task pTask) {
             task = pTask;
             synchronized (thread) {
                 thread.notify();
@@ -126,26 +125,39 @@
                threadGroup = new ThreadGroup(pName);
        }
 
-       synchronized void discard(Poolable pPoolable) {
-               pPoolable.shutdown();
+       private synchronized void remove(Poolable pPoolable) {
         runningThreads.remove(pPoolable);
         waitingThreads.remove(pPoolable);
        }
 
-       synchronized void repool(Poolable pPoolable) {
-        if (runningThreads.remove(pPoolable)) {
-            if (maxSize != 0  &&  runningThreads.size() + 
waitingThreads.size() >= maxSize) {
-                discard(pPoolable);
-            } else {
-                waitingThreads.add(pPoolable);
-                if (waitingTasks.size() > 0) {
-                    Task task = (Task) waitingTasks.remove(waitingTasks.size() 
- 1);
-                    startTask(task);
-                }
-            }
-        } else {
-            discard(pPoolable);
-        }
+       void repool(Poolable pPoolable) {
+           boolean discarding = false;
+           Task task = null;
+           Poolable poolable = null;
+           synchronized (this) {
+               if (runningThreads.remove(pPoolable)) {
+                   if (maxSize != 0  &&  runningThreads.size() + 
waitingThreads.size() >= maxSize) {
+                       discarding = true;
+                   } else {
+                       waitingThreads.add(pPoolable);
+                       if (waitingTasks.size() > 0) {
+                           task = (Task) 
waitingTasks.remove(waitingTasks.size() - 1);
+                           poolable = getPoolable(task, false);
+                       }
+                   }
+               } else {
+                   discarding = true;
+               }
+               if (discarding) {
+                   remove(pPoolable);
+               }
+           }
+           if (poolable != null) {
+               poolable.start(task);
+           }
+           if (discarding) {
+               pPoolable.shutdown();
+           }
        }
 
        /** Starts a task immediately.
@@ -154,32 +166,45 @@
         * the maxmimum number of concurrent tasks was exceeded. If so, you
         * might consider to use the {...@link #addTask(ThreadPool.Task)} 
method instead.
         */
-       public synchronized boolean startTask(Task pTask) {
-               if (maxSize != 0  &&  runningThreads.size() >= maxSize) {
-                       return false;
-               }
-        Poolable poolable;
-               if (waitingThreads.size() > 0) {
-                   poolable = (Poolable) 
waitingThreads.remove(waitingThreads.size()-1);
-               } else {
-            poolable = new Poolable(threadGroup, num++);
-               }
-               runningThreads.add(poolable);
-        poolable.start(pTask);
+       public boolean startTask(Task pTask) {
+           final Poolable poolable = getPoolable(pTask, false);
+           if (poolable == null) {
+               return false;
+           }
+           poolable.start(pTask);
                return true;
        }
 
+       private synchronized Poolable getPoolable(Task pTask, boolean pQueue) {
+        if (maxSize != 0  &&  runningThreads.size() >= maxSize) {
+            if (pQueue) {
+                waitingTasks.add(pTask);
+            }
+            return null;
+        }
+        Poolable poolable;
+        if (waitingThreads.size() > 0) {
+            poolable = (Poolable) 
waitingThreads.remove(waitingThreads.size()-1);
+        } else {
+            poolable = new Poolable(threadGroup, num++);
+        }
+        runningThreads.add(poolable);
+        return poolable;
+       }
+       
        /** Adds a task for immediate or deferred execution.
         * @param pTask The task being added.
         * @return True, if the task was started immediately. False, if
         * the task will be executed later.
+        * @deprecated No longer in use.
         */
-       public synchronized boolean addTask(Task pTask) {
-               if (startTask(pTask)) {
-                       return true;
-               }
-               waitingTasks.add(pTask);
-               return false;
+       public boolean addTask(Task pTask) {
+           final Poolable poolable = getPoolable(pTask, true);
+           if (poolable != null) {
+               poolable.start(pTask);
+               return true;
+           }
+           return false;
        }
 
        /** Closes the pool.

Modified: webservices/xmlrpc/trunk/src/changes/changes.xml
URL: 
http://svn.apache.org/viewvc/webservices/xmlrpc/trunk/src/changes/changes.xml?rev=769900&r1=769899&r2=769900&view=diff
==============================================================================
--- webservices/xmlrpc/trunk/src/changes/changes.xml (original)
+++ webservices/xmlrpc/trunk/src/changes/changes.xml Wed Apr 29 19:54:33 2009
@@ -23,11 +23,14 @@
     <title>Changes in Apache XML-RPC</title>
   </properties>
   <body>
-    <release version="3.1.2" date="2009-Apr-19">
+    <release version="3.1.3-SNAPSHOT" date="2009-Apr-29">
       <action dev="jochen" type="fix">
         The version number in the clients user agent string is now
         updated automatically.
       </action>
+      <action dev="jochen" type="fix" issue="XMLRPC-168">
+        Fixed a deadlock in the ThreadPool.
+      </action>
     </release>
 
     <release version="3.1.2" date="2009-Apr-19">


Reply via email to