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

Modified Files:
        QThreadFactory.java 
Log Message:
(LoadStats.java) use 200 samples for accept ratio and 
  requests/hour.
(LRUQueue.java) fix an NPE.
(QThreadFactory.java) fix bugs, simplify.  
  Changes since 1.28 really do reduce lock contention.
  added trailing blanks on certain lines so that
  emacs ediff vs. 1.28 does not lose sync.
(ReadSelectorLoop.java) fix typo in comment.
(Version.java) 6208


Index: QThreadFactory.java
===================================================================
RCS file: /cvsroot/freenet/freenet/src/freenet/thread/QThreadFactory.java,v
retrieving revision 1.32
retrieving revision 1.33
diff -u -r1.32 -r1.33
--- QThreadFactory.java 26 Sep 2003 02:02:09 -0000      1.32
+++ QThreadFactory.java 26 Sep 2003 09:22:36 -0000      1.33
@@ -29,7 +29,7 @@
 
     private final CountLock countLock = new CountLock();
     private int active = 0;
-    private int available = 0;
+    private int available = 0; // never more than number of threads on stack.
 
     private final NumLock numLock = new NumLock();
     private long threadNumber = 0;
@@ -51,81 +51,106 @@
     public void run() {
         while (true) {
             Throwable lastEx = null;
+                       int logAvailable = 0, logActive = 0;
             try {
-                boolean adjust=false;
-                int desired=Integer.MAX_VALUE;
-                while ( true ) {
+                int required;
+                               synchronized(countLock) {
+                                       // start with a minimal required value.
+                                       required = (int)(active * 
MINIMUM_AVAILABLE_RATIO);
+                                       if ( available < MINIMUM_AVAILABLE_ABS || 
+                                                available < required ) {
+                                               // if we fell below that, set target 
higher.
+                                               required =
+                            Math.max((int) (active * IDEAL_AVAILABLE_RATIO),
+                                     2 * MINIMUM_AVAILABLE_ABS);
+                                       }
+                                       logAvailable = available;
+                                       logActive = active;
+                               }
+                while ( available < required ) {
+                                       createThread();
                     synchronized(countLock) {
-                        if ( desired != Integer.MAX_VALUE ||
-                             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 ) {
-                                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,
+                                               // required must not increase.
+                                               required = 
+                                                       Math.min(required, 
+                                                                        
Math.max((int) (active * IDEAL_AVAILABLE_RATIO),
+                                                                                      
   2 * MINIMUM_AVAILABLE_ABS));
+                                               if ( available > required &&
+                                                        available > active * 
MINIMUM_AVAILABLE_RATIO ) {
+                                                       try { 
+                                                               countLock.wait(500); 
+                                                       } catch ( InterruptedException 
ie ) {
+                                                               // active might have 
changed.
+                                                               // required must not 
increase.
+                                                               required = 
+                                                                       
Math.min(required, 
+                                                                                      
  Math.max((int) (active * IDEAL_AVAILABLE_RATIO),
+                                                                                      
                   2 * MINIMUM_AVAILABLE_ABS));
+                                                       }
+                                               }
+                                               logAvailable = available;
+                                               logActive = active;
+                    } 
+                } 
+                Core.logger.log(this,"Thread creation thread past creation loop" + 
+                                                               ", available: " + 
logAvailable + 
+                                                               ", required: " + 
required + 
+                                                               ", active: " + 
logActive,
                                 Core.logger.DEBUG);
-                adjust=false;
-                desired=0;
-                while ( true ) {
-                    synchronized(countLock) {   
-                        if ( desired != 0 || 
-                             ( available > (3 * MINIMUM_AVAILABLE_ABS) &&
-                               available > active * MAXIMUM_AVAILABLE_RATIO ) ) {
-
-                            desired = 
-                                Math.max(Math.max((int) (active * 
IDEAL_AVAILABLE_RATIO),
-                                                  2 * MINIMUM_AVAILABLE_ABS),desired);
-
-
-                            if ( available > desired || 
-                                 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;
-                        }
-                    }
+                int allowed;
+                               synchronized(countLock) {
+                                       // start with a maximal allowed value.
+                                       allowed = (int)(active * 
MAXIMUM_AVAILABLE_RATIO);
+                                       if ( available > 3 * MINIMUM_AVAILABLE_ABS && 
+                                                available > allowed ) {
+                                               // if we are above that, set target 
lower.
+                                               allowed =
+                            Math.max((int) (active * IDEAL_AVAILABLE_RATIO),
+                                     2 * MINIMUM_AVAILABLE_ABS);
+                                       }
+                                       logAvailable = available;
+                                       logActive = active;
+                               }
+                while ( available > allowed ) {
                     destroyThread();
-                }
-                Core.logger.log(this,"Thread creation thread past deletion loop, 
available: " + 
-                                available + ", desired: " + desired + ", active: " + 
active,
+                    synchronized(countLock) {   
+                                               // allowed must not decrease.
+                                               allowed = 
+                                                       Math.max((int) (active * 
IDEAL_AVAILABLE_RATIO),
+                                                                        
Math.max(allowed,
+                                                                                      
   2 * MINIMUM_AVAILABLE_ABS));
+                                               if ( available < allowed &&
+                                                        available < active * 
MAXIMUM_AVAILABLE_RATIO ) {
+                                                       try { 
+                                                               countLock.wait(500); 
+                                                       } catch ( InterruptedException 
ie ) {
+                                                               // active might have 
changed.
+                                                               // allowed must not 
decrease.
+                                                               allowed = 
+                                                                       Math.max((int) 
(active * IDEAL_AVAILABLE_RATIO),
+                                                                                      
  Math.max(allowed,
+                                                                                      
                   2 * MINIMUM_AVAILABLE_ABS));
+                                                       }
+                                               }
+                                               logAvailable = available;
+                                               logActive = active;
+                    } 
+                } 
+                Core.logger.log(this,"Thread creation thread past destruction loop" + 
+                                                               ", available: " + 
logAvailable + 
+                                                               ", allowed: " + 
allowed + 
+                                                               ", active: " + 
logActive,
                                 Core.logger.DEBUG);
 
             } catch (Throwable e) {
                 if (lastEx == null || !lastEx.getClass().equals(e.getClass()))
+                                       synchronized(countLock) {
+                                               logAvailable = available;
+                                               logActive = active;
+                    } 
                     Core.logger.log(this, "Exception in QThreadFactory. "
-                                    + available + " threads available ," 
-                                    + active + " running. Top: " + headerThread, 
+                                    + logAvailable + " threads available ," 
+                                    + logActive + " running. Top: " + headerThread, 
                                                                        e, 
Core.logger.ERROR);
                 lastEx = e;
                 try {
@@ -150,8 +175,7 @@
 
     /**
      * @return  the instantaneous number of idle threads;
-     *          may return a negative number if the force option
-     *          was used with getThread()
+        *          may return an underestimate, even < 0.
      */
     public final int availableThreads() {
         return available;
@@ -162,28 +186,33 @@
      */
     public final Thread getThread(Runnable job) {
         boolean gotHead;
-        QThread thread=null;
+        QThread thread = null;
+        synchronized(countLock) {
+            active++;
+            available--; // never an overestimate
+        }
         synchronized(headLock) {
             // hopefully this will not happen often.
             if (headerThread == null) {
-                gotHead=false;
+                gotHead = false;
             } else {
-                gotHead=true;
+                gotHead = true;
                 thread = headerThread;
                 headerThread = headerThread.next;
             }
         }
         if (!gotHead) {
+                       long newThreadNumber;
             synchronized(numLock) {
-                thread = new QThread(++threadNumber);
+                newThreadNumber = ++threadNumber;
             }
+                       synchronized(countLock) {
+                               available++; // correct the underestimate.
+                       }
+                       thread = new QThread(newThreadNumber);
         }
         thread.next = null;
         thread.job = job;
-        synchronized(countLock) {
-            active++;
-            available-=gotHead?1:0;
-        }
         thread.start();
 
         awaken();
@@ -195,33 +224,36 @@
      */
     private final void createThread() {
         QThread newThread;
-        synchronized(numLock) {
-            newThread = new QThread(++threadNumber);
-        }
+               long newThreadNumber;
+               synchronized(numLock) {
+                       newThreadNumber = ++threadNumber;
+               }
+               newThread = new QThread(newThreadNumber);
         synchronized(headLock) {
             newThread.next = headerThread;
             headerThread = newThread;
         }
         synchronized(countLock) {
-            available++;
+            available++; // never an overestimate.
         }
     }
 
     /**
      * Removes a thread from the stack and signals it to die.
+        * But if all of the threads have meanwhile started jobs,
+        * then does nothing.
      */
     private final void destroyThread() {
         QThread dyingThread;
+               synchronized(countLock) {
+                       if (available < 1) return;
+                       available--; // never an overestimate.
+               }
         synchronized(headLock) {
             dyingThread = headerThread;
-            headerThread = headerThread.next;
-        }
-        if ( dyingThread != null ) {
-            dyingThread.die();
-        }
-        synchronized(countLock) {
-            available--;
+                       headerThread = headerThread.next;
         }
+               dyingThread.die();
     }
 
     /**
@@ -234,11 +266,11 @@
         }
         synchronized(countLock) {
             active--;
-            available++;
+            available++; // never an overestimate
         }
     }
 
-    private synchronized final void awaken() {
+    private final void awaken() {
         synchronized(countLock) {
             if ( ( available < MINIMUM_AVAILABLE_ABS) ||
                  ( available < active * MINIMUM_AVAILABLE_RATIO) || 
@@ -251,7 +283,7 @@
 
     private final class QThread extends Thread implements PooledThread {
 
-        private QThread next;
+        private QThread next; // link for stack of available threads.
     
         private Runnable job = null;
 

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

Reply via email to