|
From: Frank M. H. <fm...@us...> - 2007-03-01 15:57:36
|
Update of /cvsroot/boost-sandbox/boost-sandbox/boost/thread_safe_signals/detail In directory sc8-pr-cvs3.sourceforge.net:/tmp/cvs-serv10496/boost/thread_safe_signals/detail Modified Files: signal_base.hpp signal_template.hpp slot_call_iterator.hpp Log Message: Restored per-slot locking, due to unresolvable failures in deletion_test.cpp. Restored ThreadingModel parameter due to popular demand, but made default "signals::auto_threaded" which uses the lightweight_mutex. Removed obsolete trackable.hpp. Index: slot_call_iterator.hpp =================================================================== RCS file: /cvsroot/boost-sandbox/boost-sandbox/boost/thread_safe_signals/detail/slot_call_iterator.hpp,v retrieving revision 1.21 retrieving revision 1.22 diff -u -d -r1.21 -r1.22 --- slot_call_iterator.hpp 28 Feb 2007 20:48:30 -0000 1.21 +++ slot_call_iterator.hpp 1 Mar 2007 15:57:25 -0000 1.22 @@ -90,7 +90,7 @@ } for(;iter != end; ++iter) { - lock_type lock(*(*iter)->_mutex); + lock_type lock((*iter)->mutex); tracked_ptrs = (*iter)->nolock_grab_tracked_objects(); if((*iter)->nolock_nograb_blocked() == false) { Index: signal_template.hpp =================================================================== RCS file: /cvsroot/boost-sandbox/boost-sandbox/boost/thread_safe_signals/detail/signal_template.hpp,v retrieving revision 1.39 retrieving revision 1.40 diff -u -d -r1.39 -r1.40 --- signal_template.hpp 28 Feb 2007 20:48:30 -0000 1.39 +++ signal_template.hpp 1 Mar 2007 15:57:25 -0000 1.40 @@ -34,18 +34,20 @@ typename Combiner = boost::last_value<R>, \ typename Group = int, \ typename GroupCompare = std::less<Group>, \ - typename SlotFunction = BOOST_FUNCTION_N_DECL(BOOST_SIGNALS_NUM_ARGS) + typename SlotFunction = BOOST_FUNCTION_N_DECL(BOOST_SIGNALS_NUM_ARGS), \ + typename ThreadingModel = signalslib::auto_threaded // typename R, typename T1, typename T2, ..., typename TN, typename Combiner, ... #define BOOST_SIGNAL_TEMPLATE_DECL \ BOOST_SIGNAL_SIGNATURE_TEMPLATE_DECL(BOOST_SIGNALS_NUM_ARGS), \ typename Combiner, \ typename Group, \ typename GroupCompare, \ - typename SlotFunction -// R, T1, T2, ..., TN, Combiner, Group, GroupCompare, SlotFunction + typename SlotFunction, \ + typename ThreadingModel +// R, T1, T2, ..., TN, Combiner, Group, GroupCompare, SlotFunction, ThreadingModel #define BOOST_SIGNAL_TEMPLATE_INSTANTIATION \ BOOST_SIGNAL_SIGNATURE_TEMPLATE_INSTANTIATION(BOOST_SIGNALS_NUM_ARGS), \ - Combiner, Group, GroupCompare, SlotFunction + Combiner, Group, GroupCompare, SlotFunction, ThreadingModel namespace boost { @@ -54,7 +56,7 @@ namespace detail { template<BOOST_SIGNAL_TEMPLATE_DECL> - class BOOST_SIGNAL_IMPL_CLASS_NAME: public signal_impl_base + class BOOST_SIGNAL_IMPL_CLASS_NAME { public: typedef SlotFunction slot_function_type; @@ -64,7 +66,7 @@ private: class slot_invoker; typedef typename signalslib::detail::group_key<Group>::type group_key_type; - typedef shared_ptr<ConnectionBody<group_key_type, slot_type> > connection_body_type; + typedef shared_ptr<ConnectionBody<group_key_type, slot_type, ThreadingModel> > connection_body_type; typedef grouped_list<Group, GroupCompare, connection_body_type> connection_list_type; public: typedef typename slot_function_type::result_type slot_result_type; @@ -73,7 +75,7 @@ typedef Group group_type; typedef GroupCompare group_compare_type; typedef typename signalslib::detail::slot_call_iterator_t<slot_invoker, - typename connection_list_type::iterator, ConnectionBody<group_key_type, SlotFunction> > slot_call_iterator; + typename connection_list_type::iterator, ConnectionBody<group_key_type, SlotFunction, ThreadingModel> > slot_call_iterator; BOOST_SIGNAL_IMPL_CLASS_NAME(const combiner_type &combiner, const group_compare_type &group_compare): @@ -83,7 +85,7 @@ // connect slot signalslib::connection connect(const slot_type &slot, signalslib::connect_position position = signalslib::at_back) { - typename mutex_type::scoped_lock lock(*_mutex); + typename mutex_type::scoped_lock lock(_mutex); connection_body_type newConnectionBody = create_new_connection(slot); group_key_type group_key; @@ -102,7 +104,7 @@ signalslib::connection connect(const group_type &group, const slot_type &slot, signalslib::connect_position position = signalslib::at_back) { - typename mutex_type::scoped_lock lock(*_mutex); + typename mutex_type::scoped_lock lock(_mutex); connection_body_type newConnectionBody = create_new_connection(slot); // update map to first connection body in group if needed @@ -155,7 +157,7 @@ shared_ptr<invocation_state> local_state; typename connection_list_type::iterator it; { - typename mutex_type::scoped_lock listLock(*_mutex); + typename mutex_type::scoped_lock listLock(_mutex); // only clean up if it is safe to do so if(_shared_state.unique()) nolock_cleanup_connections(false); @@ -176,7 +178,7 @@ shared_ptr<invocation_state> local_state; typename connection_list_type::iterator it; { - typename mutex_type::scoped_lock listLock(*_mutex); + typename mutex_type::scoped_lock listLock(_mutex); // only clean up if it is safe to do so if(_shared_state.unique()) nolock_cleanup_connections(false); @@ -219,19 +221,19 @@ } combiner_type combiner() const { - typename mutex_type::scoped_lock lock(*_mutex); + typename mutex_type::scoped_lock lock(_mutex); return _shared_state->combiner; } void set_combiner(const combiner_type &combiner) { - typename mutex_type::scoped_lock lock(*_mutex); + typename mutex_type::scoped_lock lock(_mutex); if(_shared_state.unique()) _shared_state->combiner = combiner; else _shared_state.reset(new invocation_state(_shared_state->connection_bodies, combiner)); } private: - typedef typename signal_impl_base::mutex_type mutex_type; + typedef typename ThreadingModel::mutex_type mutex_type; // slot_invoker is passed to slot_call_iterator_t to run slots class slot_invoker @@ -295,9 +297,13 @@ for(it = begin; it != end;) { bool connected; - if(grab_tracked) - (*it)->nolock_slot_expired(); - connected = (*it)->nolock_nograb_connected(); + { + // skip over slots that are busy + typename ConnectionBody<group_key_type, SlotFunction, ThreadingModel>::mutex_type::scoped_lock lock((*it)->mutex); + if(grab_tracked) + (*it)->nolock_slot_expired(); + connected = (*it)->nolock_nograb_connected(); + }// scoped lock destructs here, safe to erase now if(connected == false) { it = _shared_state->connection_bodies.erase((*it)->group_key(), it); @@ -340,13 +346,13 @@ } shared_ptr<invocation_state> get_readable_state() const { - typename mutex_type::scoped_lock listLock(*_mutex); + typename mutex_type::scoped_lock listLock(_mutex); return _shared_state; } connection_body_type create_new_connection(const slot_type &slot) { nolock_force_unique_connection_list(); - return connection_body_type(new ConnectionBody<group_key_type, slot_type>(_mutex, slot)); + return connection_body_type(new ConnectionBody<group_key_type, slot_type, ThreadingModel>(slot)); } void do_disconnect(const group_type &group, mpl::bool_<true> is_group) { @@ -361,7 +367,7 @@ for(it = local_state->connection_bodies.begin(); it != local_state->connection_bodies.end(); ++it) { - typename mutex_type::scoped_lock lock(*_mutex); + typename ConnectionBody<group_key_type, slot_function_type, ThreadingModel>::mutex_type::scoped_lock lock((*it)->mutex); if((*it)->slot.slot_function() == slot) { (*it)->nolock_disconnect(); @@ -371,6 +377,9 @@ shared_ptr<invocation_state> _shared_state; mutable typename connection_list_type::iterator _garbage_collector_it; + // connection list mutex must never be locked when attempting a blocking lock on a slot, + // or you could deadlock. + mutable mutex_type _mutex; }; template<BOOST_SIGNAL_TEMPLATE_DECL> @@ -509,19 +518,19 @@ }; template<unsigned arity, typename Signature, typename Combiner, - typename Group, typename GroupCompare, typename SlotFunction> + typename Group, typename GroupCompare, typename SlotFunction, typename ThreadingModel> class signalN; // partial template specialization template<typename Signature, typename Combiner, typename Group, - typename GroupCompare, typename SlotFunction> + typename GroupCompare, typename SlotFunction, typename ThreadingModel> class signalN<BOOST_SIGNALS_NUM_ARGS, Signature, Combiner, Group, - GroupCompare, SlotFunction> + GroupCompare, SlotFunction, ThreadingModel> { public: typedef BOOST_SIGNAL_CLASS_NAME< BOOST_SIGNAL_PORTABLE_SIGNATURE(BOOST_SIGNALS_NUM_ARGS, Signature), Combiner, Group, - GroupCompare, SlotFunction> type; + GroupCompare, SlotFunction, ThreadingModel> type; }; } } Index: signal_base.hpp =================================================================== RCS file: /cvsroot/boost-sandbox/boost-sandbox/boost/thread_safe_signals/detail/signal_base.hpp,v retrieving revision 1.3 retrieving revision 1.4 diff -u -d -r1.3 -r1.4 --- signal_base.hpp 28 Feb 2007 20:48:30 -0000 1.3 +++ signal_base.hpp 1 Mar 2007 15:57:25 -0000 1.4 @@ -10,9 +10,7 @@ #ifndef BOOST_TSS_SIGNALS_SIGNAL_BASE_HEADER #define BOOST_TSS_SIGNALS_SIGNAL_BASE_HEADER -#include <boost/detail/lightweight_mutex.hpp> #include <boost/noncopyable.hpp> -#include <boost/shared_ptr.hpp> #ifdef BOOST_HAS_ABI_HEADERS # include BOOST_ABI_PREFIX @@ -23,17 +21,6 @@ namespace detail { class slot_base; - class signal_impl_base - { - public: - typedef boost::detail::lightweight_mutex mutex_type; - - signal_impl_base(): _mutex(new boost::detail::lightweight_mutex) - {} - protected: - mutable shared_ptr<mutex_type> _mutex; - }; - class signal_base : public noncopyable { public: |