Update of /cvsroot/freenet/freenet/src/freenet/thread
In directory sc8-pr-cvs1:/tmp/cvs-serv22073/src/freenet/thread

Modified Files:
        QThreadFactory.java 
Log Message:
More locking improvements.
-Moved KillSurplusConnections to a thread of it's own, this is in the hopes of 
reducing contention for the highly contested lru lock in OpenConnectionManager
-Completely redid locking in QThreadFactory, locking the whole class for most of the 
operations in here didn't make sense, so I used several different locks to ensure 
synchronization w/o blocking threads trying to return themselves
(Committed at Zab's request)

Index: QThreadFactory.java
===================================================================
RCS file: /cvsroot/freenet/freenet/src/freenet/thread/QThreadFactory.java,v
retrieving revision 1.31
retrieving revision 1.32
diff -u -r1.31 -r1.32
--- QThreadFactory.java 26 Sep 2003 01:50:43 -0000      1.31
+++ QThreadFactory.java 26 Sep 2003 02:02:09 -0000      1.32
@@ -27,11 +27,14 @@
 
     private final ThreadGroup tg;
 
+    private final CountLock countLock = new CountLock();
     private int active = 0;
     private int available = 0;
 
+    private final NumLock numLock = new NumLock();
     private long threadNumber = 0;
 
+    private final HeadLock headLock = new HeadLock();
     private QThread headerThread = null;
 
     private final Object maxLock = new Object();
@@ -49,31 +52,50 @@
         while (true) {
             Throwable lastEx = null;
             try {
+                boolean adjust=false;
                 int desired=Integer.MAX_VALUE;
                 while ( true ) {
-                    synchronized(this) {
+                    synchronized(countLock) {
                         if ( desired != Integer.MAX_VALUE ||
-                                                        available < 
MINIMUM_AVAILABLE_ABS || 
+                             available < MINIMUM_AVAILABLE_ABS || 
                              available < active * MINIMUM_AVAILABLE_RATIO ) {
 
                             desired = 
                                 Math.min(Math.max((int) (active * 
IDEAL_AVAILABLE_RATIO),
                                                   2 * MINIMUM_AVAILABLE_ABS),desired);
                             if ( available < desired || 
-                                                                available < active * 
MINIMUM_AVAILABLE_RATIO ) {
-                                createThread();
-                            } else break;
-                        } else break;
+                                 available < active * MINIMUM_AVAILABLE_RATIO ) {
+                                adjust=true;;
+                            } else {
+                                try { 
+                                    long start = System.currentTimeMillis();
+                                    countLock.wait(500); 
+                                    if ( System.currentTimeMillis() < start + 500 )
+                                        continue;
+                                } catch ( InterruptedException ie ) {}
+                                break;
+                            }
+                        } else { 
+                            try { 
+                                long start = System.currentTimeMillis();
+                                countLock.wait(500); 
+                                if ( System.currentTimeMillis() < start + 500 )
+                                    continue;
+                            } catch ( InterruptedException ie ) {}
+                            break;
+                        }
                     }
+                    createThread();
                 }
                 Core.logger.log(this,"Thread creation thread past creation loop, 
available: " + 
                                 available + ", desired: " + desired + ", active: " + 
active,
                                 Core.logger.DEBUG);
+                adjust=false;
                 desired=0;
                 while ( true ) {
-                    synchronized(this) {   
+                    synchronized(countLock) {   
                         if ( desired != 0 || 
-                                                        ( available > (3 * 
MINIMUM_AVAILABLE_ABS) &&
+                             ( available > (3 * MINIMUM_AVAILABLE_ABS) &&
                                available > active * MAXIMUM_AVAILABLE_RATIO ) ) {
 
                             desired = 
@@ -82,22 +104,23 @@
 
 
                             if ( available > desired || 
-                                                                available > active * 
MAXIMUM_AVAILABLE_RATIO ) {
-                                destroyThread();
-                            } else break;
-                        } else break;
+                                 available > active * MAXIMUM_AVAILABLE_RATIO ) {
+                                adjust=true;
+                            } else {
+                                try { countLock.wait(500); } catch ( 
InterruptedException ie ) {}
+                                break;
+                            }
+                        } else { 
+                            try { countLock.wait(500); } catch ( InterruptedException 
ie ) {}
+                            break;
+                        }
                     }
+                    destroyThread();
                 }
                 Core.logger.log(this,"Thread creation thread past deletion loop, 
available: " + 
                                 available + ", desired: " + desired + ", active: " + 
active,
                                 Core.logger.DEBUG);
 
-                try {
-                    synchronized(this) {
-                        wait(1000);
-                    }
-                } catch (InterruptedException e) {
-                }
             } catch (Throwable e) {
                 if (lastEx == null || !lastEx.getClass().equals(e.getClass()))
                     Core.logger.log(this, "Exception in QThreadFactory. "
@@ -137,19 +160,30 @@
     /**
      * @param job       The job to be executed
      */
-    public synchronized final Thread getThread(Runnable job) {
-
-        // hopefully this will not happen often.
-        if (headerThread == null) {
-            createThread();
+    public final Thread getThread(Runnable job) {
+        boolean gotHead;
+        QThread thread=null;
+        synchronized(headLock) {
+            // hopefully this will not happen often.
+            if (headerThread == null) {
+                gotHead=false;
+            } else {
+                gotHead=true;
+                thread = headerThread;
+                headerThread = headerThread.next;
+            }
+        }
+        if (!gotHead) {
+            synchronized(numLock) {
+                thread = new QThread(++threadNumber);
+            }
         }
-
-        QThread thread = headerThread;
-        headerThread = headerThread.next;
         thread.next = null;
         thread.job = job;
-        ++active;
-        --available;
+        synchronized(countLock) {
+            active++;
+            available-=gotHead?1:0;
+        }
         thread.start();
 
         awaken();
@@ -159,39 +193,59 @@
     /**
      * Creates a thread and adds it to the stack.
      */
-    private synchronized final void createThread() {
-        QThread newThread = new QThread(++threadNumber);
-        newThread.next = headerThread;
-        headerThread = newThread;
-        available++;
+    private final void createThread() {
+        QThread newThread;
+        synchronized(numLock) {
+            newThread = new QThread(++threadNumber);
+        }
+        synchronized(headLock) {
+            newThread.next = headerThread;
+            headerThread = newThread;
+        }
+        synchronized(countLock) {
+            available++;
+        }
     }
 
     /**
      * Removes a thread from the stack and signals it to die.
      */
-    private synchronized final void destroyThread() {
-        QThread dyingThread = headerThread;
-        headerThread = headerThread.next;
-        dyingThread.die();
-        available--;
+    private final void destroyThread() {
+        QThread dyingThread;
+        synchronized(headLock) {
+            dyingThread = headerThread;
+            headerThread = headerThread.next;
+        }
+        if ( dyingThread != null ) {
+            dyingThread.die();
+        }
+        synchronized(countLock) {
+            available--;
+        }
     }
 
     /**
      * Returns a thread to the stack when it is finished executing.
      */
-    private synchronized final void returnThread(QThread returnThread) {
-        returnThread.next = headerThread;
-        headerThread = returnThread;
-        active--;
-        available++;
+    private final void returnThread(QThread returnThread) {
+        synchronized(headLock) {
+            returnThread.next = headerThread;
+            headerThread = returnThread;
+        }
+        synchronized(countLock) {
+            active--;
+            available++;
+        }
     }
 
     private synchronized final void awaken() {
-        if ( ( available < MINIMUM_AVAILABLE_ABS) ||
-             ( available < active * MINIMUM_AVAILABLE_RATIO) || 
-             ( ( available > (3 * MINIMUM_AVAILABLE_ABS)) &&
+        synchronized(countLock) {
+            if ( ( available < MINIMUM_AVAILABLE_ABS) ||
+                 ( available < active * MINIMUM_AVAILABLE_RATIO) || 
+                 ( ( available > (3 * MINIMUM_AVAILABLE_ABS)) &&
                           ( available > active * MAXIMUM_AVAILABLE_RATIO))) {
-            notifyAll();
+                notifyAll();
+            }
         }
     }
 
@@ -269,6 +323,10 @@
             }
         }
     }
+    
+    private class NumLock {}
+    private class HeadLock {}
+    private class CountLock {}
 }
 
 

_______________________________________________
cvs mailing list
[EMAIL PROTECTED]
http://dodo.freenetproject.org/cgi-bin/mailman/listinfo/cvs

Reply via email to