$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
Subject: [Boost-commit] svn:boost r61278 - in branches/release/boost/signals2: . detail
From: fmhess_at_[hidden]
Date: 2010-04-14 16:30:38
Author: fmhess
Date: 2010-04-14 16:30:37 EDT (Wed, 14 Apr 2010)
New Revision: 61278
URL: http://svn.boost.org/trac/boost/changeset/61278
Log:
Merged from trunk to release.  Fixes #4089.
Properties modified: 
   branches/release/boost/signals2/   (props changed)
Text files modified: 
   branches/release/boost/signals2/detail/signal_template.hpp |    27 ++++++++++++++++-----------             
   1 files changed, 16 insertions(+), 11 deletions(-)
Modified: branches/release/boost/signals2/detail/signal_template.hpp
==============================================================================
--- branches/release/boost/signals2/detail/signal_template.hpp	(original)
+++ branches/release/boost/signals2/detail/signal_template.hpp	2010-04-14 16:30:37 EDT (Wed, 14 Apr 2010)
@@ -229,7 +229,7 @@
             unique_lock<mutex_type> list_lock(_mutex);
             // only clean up if it is safe to do so
             if(_shared_state.unique())
-              nolock_cleanup_connections(false);
+              nolock_cleanup_connections(false, 1);
             /* Make a local copy of _shared_state while holding mutex, so we are
             thread safe against the combiner or connection list getting modified
             during invocation. */
@@ -253,7 +253,7 @@
             unique_lock<mutex_type> list_lock(_mutex);
             // only clean up if it is safe to do so
             if(_shared_state.unique())
-              nolock_cleanup_connections(false);
+              nolock_cleanup_connections(false, 1);
             /* Make a local copy of _shared_state while holding mutex, so we are
             thread safe against the combiner or connection list getting modified
             during invocation. */
@@ -412,12 +412,15 @@
         };
 
         // clean up disconnected connections
-        void nolock_cleanup_connections(bool grab_tracked,
-          const typename connection_list_type::iterator &begin, bool break_on_connected = false) const
+        void nolock_cleanup_connections_from(bool grab_tracked,
+          const typename connection_list_type::iterator &begin, unsigned count = 0) const
         {
           BOOST_ASSERT(_shared_state.unique());
           typename connection_list_type::iterator it;
-          for(it = begin; it != _shared_state->connection_bodies().end();)
+          unsigned i;
+          for(it = begin, i = 0;
+            it != _shared_state->connection_bodies().end() && (count == 0 || i < count);
+            ++i)
           {
             bool connected;
             {
@@ -432,13 +435,12 @@
             }else
             {
               ++it;
-              if(break_on_connected) break;
             }
           }
           _garbage_collector_it = it;
         }
         // clean up a few connections in constant time
-        void nolock_cleanup_connections(bool grab_tracked) const
+        void nolock_cleanup_connections(bool grab_tracked, unsigned count) const
         {
           BOOST_ASSERT(_shared_state.unique());
           typename connection_list_type::iterator begin;
@@ -449,7 +451,7 @@
           {
             begin = _garbage_collector_it;
           }
-          nolock_cleanup_connections(grab_tracked, begin, true);
+          nolock_cleanup_connections_from(grab_tracked, begin, count);
         }
         /* Make a new copy of the slot list if it is currently being read somewhere else
         */
@@ -458,10 +460,13 @@
           if(_shared_state.unique() == false)
           {
             _shared_state.reset(new invocation_state(*_shared_state, _shared_state->connection_bodies()));
-            nolock_cleanup_connections(true, _shared_state->connection_bodies().begin());
+            nolock_cleanup_connections_from(true, _shared_state->connection_bodies().begin());
           }else
           {
-            nolock_cleanup_connections(true);
+            /* We need to try and check more than just 1 connection here to avoid corner
+            cases where certain repeated connect/disconnect patterns cause the slot
+            list to grow without limit. */
+            nolock_cleanup_connections(true, 2);
           }
         }
         // force a full cleanup of the connection list
@@ -478,7 +483,7 @@
           {
             _shared_state.reset(new invocation_state(*_shared_state, _shared_state->connection_bodies()));
           }
-          nolock_cleanup_connections(true, _shared_state->connection_bodies().begin());
+          nolock_cleanup_connections_from(false, _shared_state->connection_bodies().begin());
         }
         shared_ptr<invocation_state> get_readable_state() const
         {