Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r61243 - trunk/boost/signals2/detail
From: fmhess_at_[hidden]
Date: 2010-04-13 09:02:18


Author: fmhess
Date: 2010-04-13 09:02:17 EDT (Tue, 13 Apr 2010)
New Revision: 61243
URL: http://svn.boost.org/trac/boost/changeset/61243

Log:
Fix for uncontrolled growth of slot list under certain patterns
of connection/disconnection without invocation. Refs #4089.

Text files modified:
   trunk/boost/signals2/detail/signal_template.hpp | 23 ++++++++++++++---------
   1 files changed, 14 insertions(+), 9 deletions(-)

Modified: trunk/boost/signals2/detail/signal_template.hpp
==============================================================================
--- trunk/boost/signals2/detail/signal_template.hpp (original)
+++ trunk/boost/signals2/detail/signal_template.hpp 2010-04-13 09:02:17 EDT (Tue, 13 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. */
@@ -413,11 +413,14 @@
 
         // clean up disconnected connections
         void nolock_cleanup_connections(bool grab_tracked,
- const typename connection_list_type::iterator &begin, bool break_on_connected = false) const
+ 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(grab_tracked, begin, count);
         }
         /* Make a new copy of the slot list if it is currently being read somewhere else
         */
@@ -461,7 +463,10 @@
             nolock_cleanup_connections(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(false, _shared_state->connection_bodies().begin());
         }
         shared_ptr<invocation_state> get_readable_state() const
         {


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk