|
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