Condition variable for outbound connection slots
authorPieter Wuille <pieter.wuille@gmail.com>
Wed, 4 Apr 2012 14:01:57 +0000 (16:01 +0200)
committerPieter Wuille <pieter.wuille@gmail.com>
Wed, 4 Apr 2012 15:24:13 +0000 (17:24 +0200)
Keep a global counter for nOutbound, protected with its own waitable
critical section, and wait when all outbound slots are filled, rather
than polling.

This removes the (on average) 1 second delay between a lost connection
and a new connection attempt, and may speed up shutdowns.

src/net.cpp

index 37e73c4..2d9cf6e 100644 (file)
@@ -64,6 +64,9 @@ map<CInv, int64> mapAlreadyAskedFor;
 set<CNetAddr> setservAddNodeAddresses;
 CCriticalSection cs_setservAddNodeAddresses;
 
+static CWaitableCriticalSection csOutbound;
+static int nOutbound = 0;
+static CConditionVariable condOutbound;
 
 
 unsigned short GetListenPort()
@@ -460,6 +463,8 @@ CNode* ConnectNode(CAddress addrConnect, int64 nTimeout)
             pnode->AddRef();
         CRITICAL_BLOCK(cs_vNodes)
             vNodes.push_back(pnode);
+        WAITABLE_CRITICAL_BLOCK(csOutbound)
+            nOutbound++;
 
         pnode->nTimeConnected = GetTime();
         return pnode;
@@ -610,6 +615,15 @@ void ThreadSocketHandler2(void* parg)
                     // remove from vNodes
                     vNodes.erase(remove(vNodes.begin(), vNodes.end(), pnode), vNodes.end());
 
+                    if (!pnode->fInbound)
+                        WAITABLE_CRITICAL_BLOCK(csOutbound)
+                        {
+                            nOutbound--;
+
+                            // Connection slot(s) were removed, notify connection creator(s)
+                            NOTIFY(condOutbound);
+                        }
+
                     // close socket and cleanup
                     pnode->CloseSocketDisconnect();
                     pnode->Cleanup();
@@ -1278,8 +1292,6 @@ void ThreadOpenConnections2(void* parg)
     int64 nStart = GetTime();
     loop
     {
-        int nOutbound = 0;
-
         vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
         Sleep(500);
         vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
@@ -1287,23 +1299,13 @@ void ThreadOpenConnections2(void* parg)
             return;
 
         // Limit outbound connections
-        loop
-        {
-            nOutbound = 0;
-            CRITICAL_BLOCK(cs_vNodes)
-                BOOST_FOREACH(CNode* pnode, vNodes)
-                    if (!pnode->fInbound)
-                        nOutbound++;
-            int nMaxOutboundConnections = MAX_OUTBOUND_CONNECTIONS;
-            nMaxOutboundConnections = min(nMaxOutboundConnections, (int)GetArg("-maxconnections", 125));
-            if (nOutbound < nMaxOutboundConnections)
-                break;
-            vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
-            Sleep(2000);
-            vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
-            if (fShutdown)
-                return;
-        }
+        int nMaxOutbound = min(MAX_OUTBOUND_CONNECTIONS, (int)GetArg("-maxconnections", 125));
+        vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
+        WAITABLE_CRITICAL_BLOCK(csOutbound)
+            WAIT(condOutbound, fShutdown || nOutbound < nMaxOutbound);
+        vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
+        if (fShutdown)
+            return;
 
         bool fAddSeeds = false;
 
@@ -1752,6 +1754,7 @@ bool StopNode()
     fShutdown = true;
     nTransactionsUpdated++;
     int64 nStart = GetTime();
+    NOTIFY_ALL(condOutbound);
     do
     {
         int nThreadsRunning = 0;