You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@river.apache.org by pe...@apache.org on 2008/05/01 17:19:32 UTC

svn commit: r652555 - /incubator/river/jtsk/trunk/src/net/jini/jeri/connection/ConnectionManager.java

Author: peter_jones
Date: Thu May  1 08:19:32 2008
New Revision: 652555

URL: http://svn.apache.org/viewvc?rev=652555&view=rev
Log:
fix RIVER-229 & RIVER-242

Modified:
    incubator/river/jtsk/trunk/src/net/jini/jeri/connection/ConnectionManager.java

Modified: incubator/river/jtsk/trunk/src/net/jini/jeri/connection/ConnectionManager.java
URL: http://svn.apache.org/viewvc/incubator/river/jtsk/trunk/src/net/jini/jeri/connection/ConnectionManager.java?rev=652555&r1=652554&r2=652555&view=diff
==============================================================================
--- incubator/river/jtsk/trunk/src/net/jini/jeri/connection/ConnectionManager.java (original)
+++ incubator/river/jtsk/trunk/src/net/jini/jeri/connection/ConnectionManager.java Thu May  1 08:19:32 2008
@@ -30,8 +30,11 @@
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
+import java.util.HashSet;
+import java.util.Iterator;
 import java.util.List;
 import java.util.NoSuchElementException;
+import java.util.Set;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 import net.jini.core.constraint.InvocationConstraints;
@@ -125,6 +128,11 @@
     private static final Executor systemThreadPool =
 	(Executor) AccessController.doPrivileged(
 	    new GetThreadPoolAction(false));
+    /**
+     * Set of connection managers with open or pending muxes
+     * (connections), for consideration by the reaper thread.
+     */
+    private static final Set reaperSet = new HashSet();
 
     /**
      * The endpoint.
@@ -155,9 +163,7 @@
     /**
      * Number of pending connect calls.
      */
-    private int pendingConnects = 0;	// REMIND: no longer necessary?
-
-    private Reaper reaper = null;	// non-null if reaper running
+    private int pendingConnects = 0;
 
     /**
      * Creates a new <code>ConnectionManager</code> that manages
@@ -170,13 +176,6 @@
     }
 
     /**
-     * Registers a pending connect call.
-     */
-    synchronized void connectPending() {
-	pendingConnects++;
-    }
-
-    /**
      * Calls connect on the connection endpoint with the active and idle
      * muxes and the specified handle. If no connection is returned, calls
      * connect with the handle. In either case, if a new connection is
@@ -185,7 +184,17 @@
      * along the way.
      */
     OutboundMux connect(OutboundRequestHandle handle) throws IOException {
+	synchronized (this) {
+	    pendingConnects++;
+	}
 	try {
+	    synchronized (reaperSet) {
+		if (reaperSet.isEmpty()) {
+		    systemThreadPool.execute(
+			new Reaper(), "ConnectionManager.Reaper");
+		}
+		reaperSet.add(this);
+	    }
 	    synchronized (this) {
 		active.clear();
 		idle.clear();
@@ -216,11 +225,6 @@
 		    }
 		    OutboundMux mux = newOutboundMux(c);
 		    mux.newRequestPending();
-		    if (reaper == null) {
-			reaper = new Reaper();
-			systemThreadPool.execute(
-			    reaper, "ConnectionManager[" + ep + "].Reaper");
-		    }
 		    muxes.add(mux);
 		    return mux;
 		}
@@ -229,11 +233,6 @@
 	    synchronized (this) {
 		OutboundMux mux = newOutboundMux(c);
 		mux.newRequestPending();
-		if (reaper == null) {
-		    reaper = new Reaper();
-		    systemThreadPool.execute(
-			reaper, "ConnectionManager[" + ep + "].Reaper");
-		}
 		muxes.add(mux);
 		return mux;
 	    }
@@ -250,8 +249,7 @@
      * true, removes the mux and adds it to the idle list. Returns true
      * if no connects are pending and no muxes remain.
      */
-    boolean checkIdle(long now, List idle) {
-	assert Thread.holdsLock(this);
+    synchronized boolean checkIdle(long now, List idle) {
 	for (int i = muxes.size(); --i >= 0; ) {
 	    OutboundMux mux = (OutboundMux) muxes.get(i);
 	    if (mux.checkIdle(now)) {
@@ -569,19 +567,16 @@
     /**
      * Records idle times in muxes and shuts down muxes that have been
      * idle for at least TIMEOUT milliseconds.
-     *
-     * REMIND: It should be possible to have a shared reaper once
-     * again, with some care regarding GC issues.
      */
-    private final class Reaper implements Runnable {
+    private static final class Reaper implements Runnable {
 	Reaper() {
 	}
 
 	/**
-	 * Sleep for TIMEOUT milliseconds.  Then call checkIdle,
-	 * shutdown all of idle muxes that have been collected, and if
-	 * checkIdle returned true, terminate, else repeat (go back to
-	 * sleep).
+	 * Sleep for TIMEOUT milliseconds.  Then call checkIdle on
+	 * each manager with open muxes, shutdown all of idle muxes
+	 * that have been collected, and if no managers with open
+	 * muxes remain terminate, else repeat (go back to sleep).
 	 */
 	public void run() {
 	    List idle = new ArrayList(1);
@@ -593,12 +588,17 @@
 		    return;
 		}
 		long now = System.currentTimeMillis();
-		synchronized (ConnectionManager.this) {
-		    checkIdle(now, idle);
-		    done = muxes.isEmpty();
-		    if (done) {
-			reaper = null;
+		synchronized (reaperSet) {
+		    for (Iterator iter = reaperSet.iterator();
+			 iter.hasNext();)
+		    {
+			ConnectionManager mgr =
+			    (ConnectionManager) iter.next();
+			if (mgr.checkIdle(now, idle)) {
+			    iter.remove();
+			}
 		    }
+		    done = reaperSet.isEmpty();
 		}
 		for (int i = idle.size(); --i >= 0; ) {
 		    ((OutboundMux) idle.get(i)).shutdown("idle");
@@ -650,8 +650,6 @@
 		throw new NoSuchElementException();
 	    }
 	    first = false;
-	    mux = null;
-	    connectPending();
 	    mux = connect(handle);
 	    OutboundRequest req = mux.newRequest();
 	    OutboundRequest sreq = null;