You can subscribe to this list here.
| 2005 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
(89) |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 2006 |
Jan
(208) |
Feb
(76) |
Mar
(55) |
Apr
(74) |
May
(43) |
Jun
(116) |
Jul
(109) |
Aug
(46) |
Sep
(36) |
Oct
(106) |
Nov
(159) |
Dec
(128) |
| 2007 |
Jan
(54) |
Feb
(225) |
Mar
(200) |
Apr
(229) |
May
(7) |
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
|
From: Frank M. H. <fm...@us...> - 2007-03-02 22:05:10
|
Update of /cvsroot/boost-sandbox/boost-sandbox/libs/thread_safe_signals/test In directory sc8-pr-cvs3.sourceforge.net:/tmp/cvs-serv20359/libs/thread_safe_signals/test Modified Files: signal_n_test.cpp signal_test.cpp track_test.cpp Log Message: Made slots throw bad_weak_ptr when called with expired tracked objects. Combiners now have to catch bad_weak_ptr exceptions thrown on slot iterator dereference. Tracking works automatically now for slots that call other slots. Index: signal_test.cpp =================================================================== RCS file: /cvsroot/boost-sandbox/boost-sandbox/libs/thread_safe_signals/test/signal_test.cpp,v retrieving revision 1.2 retrieving revision 1.3 diff -u -d -r1.2 -r1.3 --- signal_test.cpp 28 Feb 2007 19:44:09 -0000 1.2 +++ signal_test.cpp 2 Mar 2007 22:04:47 -0000 1.3 @@ -7,6 +7,7 @@ // For more information, see http://www.boost.org +#include <boost/optional.hpp> #include <boost/test/minimal.hpp> #include <boost/thread_safe_signal.hpp> #include <functional> @@ -19,14 +20,19 @@ typename InputIterator::value_type operator()(InputIterator first, InputIterator last) const { - if (first == last) - return T(); - - T max = *first++; + boost::optional<T> max; for (; first != last; ++first) - max = (*first > max)? *first : max; - - return max; + { + try + { + if(max == false) max = *first; + else max = (*first > max.get())? *first : max; + } + catch(const boost::bad_weak_ptr &) + {} + } + if(max) return max.get(); + return T(); } }; Index: signal_n_test.cpp =================================================================== RCS file: /cvsroot/boost-sandbox/boost-sandbox/libs/thread_safe_signals/test/signal_n_test.cpp,v retrieving revision 1.2 retrieving revision 1.3 diff -u -d -r1.2 -r1.3 --- signal_n_test.cpp 28 Feb 2007 19:44:09 -0000 1.2 +++ signal_n_test.cpp 2 Mar 2007 22:04:46 -0000 1.3 @@ -7,6 +7,7 @@ // For more information, see http://www.boost.org +#include <boost/optional.hpp> #include <boost/test/minimal.hpp> #include <boost/thread_safe_signal.hpp> #include <functional> @@ -18,14 +19,19 @@ typename InputIterator::value_type operator()(InputIterator first, InputIterator last) const { - if (first == last) - return T(); - - T max = *first++; + boost::optional<T> max; for (; first != last; ++first) - max = (*first > max)? *first : max; - - return max; + { + try + { + if(max == false) max = *first; + else max = (*first > max.get())? *first : max; + } + catch(const boost::bad_weak_ptr &) + {} + } + if(max) return max.get(); + return T(); } }; Index: track_test.cpp =================================================================== RCS file: /cvsroot/boost-sandbox/boost-sandbox/libs/thread_safe_signals/test/track_test.cpp,v retrieving revision 1.5 retrieving revision 1.6 diff -u -d -r1.5 -r1.6 --- track_test.cpp 28 Feb 2007 17:08:12 -0000 1.5 +++ track_test.cpp 2 Mar 2007 22:04:47 -0000 1.6 @@ -77,7 +77,7 @@ boost::shared_ptr<int> shorty(new int(2)); boost::slot<int (double)> other_slot(&myfunc, boost::cref(*shorty.get()), _1); other_slot.track(shorty); - s1.connect(sig_type::slot_type(other_slot, 0.5).track(other_slot)); + s1.connect(sig_type::slot_type(other_slot, 0.5)); BOOST_CHECK(s1(3) == 2); } BOOST_CHECK(s1(3) == 0); |
|
From: Frank M. H. <fm...@us...> - 2007-03-02 19:34:31
|
Update of /cvsroot/boost-sandbox/boost-sandbox/boost/thread_safe_signals/detail In directory sc8-pr-cvs3.sourceforge.net:/tmp/cvs-serv21810/detail Modified Files: slot_template.hpp Log Message: Added const overload of slot::operator()() Index: slot_template.hpp =================================================================== RCS file: /cvsroot/boost-sandbox/boost-sandbox/boost/thread_safe_signals/detail/slot_template.hpp,v retrieving revision 1.5 retrieving revision 1.6 diff -u -d -r1.5 -r1.6 --- slot_template.hpp 28 Feb 2007 19:30:18 -0000 1.5 +++ slot_template.hpp 2 Mar 2007 19:34:30 -0000 1.6 @@ -79,6 +79,10 @@ { return _slot_function(BOOST_SIGNAL_SIGNATURE_ARG_NAMES(BOOST_SIGNALS_NUM_ARGS)); } + R operator()(BOOST_SIGNAL_SIGNATURE_FULL_ARGS(BOOST_SIGNALS_NUM_ARGS)) const + { + return _slot_function(BOOST_SIGNAL_SIGNATURE_ARG_NAMES(BOOST_SIGNALS_NUM_ARGS)); + } BOOST_SLOT_CLASS_NAME(BOOST_SIGNALS_NUM_ARGS)& track(const weak_ptr<void> &tracked) { _trackedObjects.push_back(tracked); |
|
From: Frank M. H. <fm...@us...> - 2007-03-02 16:00:43
|
Update of /cvsroot/boost-sandbox/boost-sandbox/boost In directory sc8-pr-cvs3.sourceforge.net:/tmp/cvs-serv32237/boost Modified Files: thread_safe_signal.hpp Log Message: Got rid of signalslib::connection::block() and unblock() and replaced them with exception-safe signalslib::shared_connection_block() class. The new way is also more useable in a multi-threaded context, since it prevents one thread from unexpectedly unblocking a connection that another thread wants blocked. Index: thread_safe_signal.hpp =================================================================== RCS file: /cvsroot/boost-sandbox/boost-sandbox/boost/thread_safe_signal.hpp,v retrieving revision 1.16 retrieving revision 1.17 diff -u -d -r1.16 -r1.17 --- thread_safe_signal.hpp 1 Mar 2007 15:57:25 -0000 1.16 +++ thread_safe_signal.hpp 2 Mar 2007 16:00:38 -0000 1.17 @@ -44,8 +44,9 @@ #include <boost/thread_safe_signals/detail/signals_common_macros.hpp> #include <boost/thread_safe_signals/detail/slot_groups.hpp> #include <boost/thread_safe_signals/detail/slot_call_iterator.hpp> -#include <boost/thread_safe_signals/connection.hpp> #include <boost/thread_safe_signals/auto_threaded.hpp> +#include <boost/thread_safe_signals/connection.hpp> +#include <boost/thread_safe_signals/shared_connection_block.hpp> #include <boost/thread_safe_signals/single_threaded.hpp> #include <boost/thread_safe_signals/slot.hpp> #include <boost/thread_safe_signals/track.hpp> @@ -62,10 +63,10 @@ namespace signals = signalslib; #endif template<typename Signature, - typename Combiner = boost::last_value<typename boost::function_traits<Signature>::result_type >, + typename Combiner = last_value<typename boost::function_traits<Signature>::result_type>, typename Group = int, typename GroupCompare = std::less<Group>, - typename SlotFunction = boost::function<Signature>, + typename SlotFunction = function<Signature>, typename ThreadingModel = signalslib::auto_threaded > class signal: public signalslib::detail::signalN<function_traits<Signature>::arity, Signature, Combiner, Group, GroupCompare, SlotFunction, ThreadingModel>::type |
|
From: Frank M. H. <fm...@us...> - 2007-03-02 16:00:41
|
Update of /cvsroot/boost-sandbox/boost-sandbox/boost/thread_safe_signals In directory sc8-pr-cvs3.sourceforge.net:/tmp/cvs-serv32237/boost/thread_safe_signals Modified Files: connection.hpp Added Files: shared_connection_block.hpp Log Message: Got rid of signalslib::connection::block() and unblock() and replaced them with exception-safe signalslib::shared_connection_block() class. The new way is also more useable in a multi-threaded context, since it prevents one thread from unexpectedly unblocking a connection that another thread wants blocked. --- NEW FILE: shared_connection_block.hpp --- // Boost.Signals library // Copyright Frank Mori Hess 2007. // Use, modification and // distribution is subject to the Boost Software License, Version // 1.0. (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // For more information, see http://www.boost.org #ifndef BOOST_SHARED_CONNECTION_BLOCK_HEADER #define BOOST_SHARED_CONNECTION_BLOCK_HEADER #include <boost/shared_ptr.hpp> #include <boost/thread_safe_signals/connection.hpp> #ifdef BOOST_HAS_ABI_HEADERS # include BOOST_ABI_PREFIX #endif namespace boost { namespace signalslib { class shared_connection_block { public: shared_connection_block(connection &conn): _blocker(conn.get_blocker()) {} void unblock() { _blocker.reset(); } private: shared_ptr<void> _blocker; }; } } // end namespace boost #ifdef BOOST_HAS_ABI_HEADERS # include BOOST_ABI_SUFFIX #endif #endif // BOOST_SHARED_CONNECTION_BLOCK_HEADER Index: connection.hpp =================================================================== RCS file: /cvsroot/boost-sandbox/boost-sandbox/boost/thread_safe_signals/connection.hpp,v retrieving revision 1.21 retrieving revision 1.22 diff -u -d -r1.21 -r1.22 --- connection.hpp 1 Mar 2007 15:57:25 -0000 1.21 +++ connection.hpp 2 Mar 2007 16:00:38 -0000 1.22 @@ -36,13 +36,14 @@ { namespace signalslib { + void null_deleter(const void*) {} namespace detail { class ConnectionBodyBase { public: ConnectionBodyBase(): - _connected(true), _blocked(false) + _connected(true) { } virtual ~ConnectionBodyBase() {} @@ -55,16 +56,20 @@ } } virtual bool connected() const = 0; - virtual void block(bool should_block) = 0; - virtual bool blocked() const = 0; + virtual shared_ptr<void> get_blocker() = 0; + bool blocked() const + { + return !_weak_blocker.expired(); + } bool nolock_nograb_blocked() const { - return _blocked || (nolock_nograb_connected() == false); + return nolock_nograb_connected() == false || blocked(); } bool nolock_nograb_connected() const {return _connected;} protected: + mutable bool _connected; - bool _blocked; + weak_ptr<void> _weak_blocker; }; template<typename GroupKey, typename SlotType, typename ThreadingModel> @@ -88,16 +93,16 @@ nolock_grab_tracked_objects(); return nolock_nograb_connected(); } - virtual void block(bool should_block) - { - typename mutex_type::scoped_lock lock(mutex); - _blocked = should_block; - } - virtual bool blocked() const + virtual shared_ptr<void> get_blocker() { typename mutex_type::scoped_lock lock(mutex); - nolock_grab_tracked_objects(); - return nolock_nograb_blocked(); + shared_ptr<void> blocker = _weak_blocker.lock(); + if(blocker == 0) + { + blocker.reset(this, &null_deleter); + _weak_blocker = blocker; + } + return blocker; } const GroupKey& group_key() const {return _group_key;} void set_group_key(const GroupKey &key) {_group_key = key;} @@ -131,9 +136,13 @@ }; } + class shared_connection_block; + class connection { public: + friend class shared_connection_block; + connection() {} connection(const connection &other): _weakConnectionBody(other._weakConnectionBody) {} @@ -153,16 +162,6 @@ if(connectionBody == 0) return false; return connectionBody->connected(); } - void block(bool should_block=true) - { - boost::shared_ptr<detail::ConnectionBodyBase> connectionBody(_weakConnectionBody.lock()); - if(connectionBody == 0) return; - connectionBody->block(should_block); - } - void unblock() - { - block(false); - } bool blocked() const { boost::shared_ptr<detail::ConnectionBodyBase> connectionBody(_weakConnectionBody.lock()); @@ -186,6 +185,13 @@ std::swap(_weakConnectionBody, other._weakConnectionBody); } private: + shared_ptr<void> get_blocker() + { + boost::shared_ptr<detail::ConnectionBodyBase> connectionBody(_weakConnectionBody.lock()); + if(connectionBody == 0) return shared_ptr<void>(); + return connectionBody->get_blocker(); + } + boost::weak_ptr<detail::ConnectionBodyBase> _weakConnectionBody; }; |
|
From: Frank M. H. <fm...@us...> - 2007-03-02 16:00:41
|
Update of /cvsroot/boost-sandbox/boost-sandbox/boost/thread_safe_signals/detail In directory sc8-pr-cvs3.sourceforge.net:/tmp/cvs-serv32237/boost/thread_safe_signals/detail Modified Files: signal_template.hpp Log Message: Got rid of signalslib::connection::block() and unblock() and replaced them with exception-safe signalslib::shared_connection_block() class. The new way is also more useable in a multi-threaded context, since it prevents one thread from unexpectedly unblocking a connection that another thread wants blocked. Index: signal_template.hpp =================================================================== RCS file: /cvsroot/boost-sandbox/boost-sandbox/boost/thread_safe_signals/detail/signal_template.hpp,v retrieving revision 1.41 retrieving revision 1.42 diff -u -d -r1.41 -r1.42 --- signal_template.hpp 1 Mar 2007 19:06:09 -0000 1.41 +++ signal_template.hpp 2 Mar 2007 16:00:39 -0000 1.42 @@ -31,7 +31,7 @@ // typename R, typename T1, typename T2, ..., typename TN, typename Combiner = boost::last_value<R>, ... #define BOOST_SIGNAL_TEMPLATE_DEFAULTED_DECL \ BOOST_SIGNAL_SIGNATURE_TEMPLATE_DECL(BOOST_SIGNALS_NUM_ARGS), \ - typename Combiner = boost::last_value<R>, \ + typename Combiner = last_value<R>, \ typename Group = int, \ typename GroupCompare = std::less<Group>, \ typename SlotFunction = BOOST_FUNCTION_N_DECL(BOOST_SIGNALS_NUM_ARGS), \ |
|
From: Frank M. H. <fm...@us...> - 2007-03-02 16:00:41
|
Update of /cvsroot/boost-sandbox/boost-sandbox/libs/thread_safe_signals/test In directory sc8-pr-cvs3.sourceforge.net:/tmp/cvs-serv32237/libs/thread_safe_signals/test Modified Files: deletion_test.cpp Log Message: Got rid of signalslib::connection::block() and unblock() and replaced them with exception-safe signalslib::shared_connection_block() class. The new way is also more useable in a multi-threaded context, since it prevents one thread from unexpectedly unblocking a connection that another thread wants blocked. Index: deletion_test.cpp =================================================================== RCS file: /cvsroot/boost-sandbox/boost-sandbox/libs/thread_safe_signals/test/deletion_test.cpp,v retrieving revision 1.2 retrieving revision 1.3 diff -u -d -r1.2 -r1.3 --- deletion_test.cpp 28 Feb 2007 19:44:09 -0000 1.2 +++ deletion_test.cpp 2 Mar 2007 16:00:39 -0000 1.3 @@ -94,14 +94,15 @@ std::cout << "Blocking 2" << std::endl; - connections[2].block(); - test_output = ""; - s0(); std::cout << std::endl; - BOOST_CHECK(test_output == "13"); + { + boost::BOOST_SIGNALS_NAMESPACE::shared_connection_block block(connections[2]); + test_output = ""; + s0(); std::cout << std::endl; + BOOST_CHECK(test_output == "13"); + } std::cout << "Unblocking 2" << std::endl; - connections[2].unblock(); test_output = ""; s0(); std::cout << std::endl; BOOST_CHECK(test_output == "123"); |
|
From: Frank M. H. <fm...@us...> - 2007-03-01 19:06:12
|
Update of /cvsroot/boost-sandbox/boost-sandbox/boost/thread_safe_signals/detail In directory sc8-pr-cvs3.sourceforge.net:/tmp/cvs-serv18067/boost/thread_safe_signals/detail Modified Files: signal_template.hpp Log Message: Tweaked constant-time garbage collection to clean up long contiguous blocks of dangling connections in one pass. Index: signal_template.hpp =================================================================== RCS file: /cvsroot/boost-sandbox/boost-sandbox/boost/thread_safe_signals/detail/signal_template.hpp,v retrieving revision 1.40 retrieving revision 1.41 diff -u -d -r1.40 -r1.41 --- signal_template.hpp 1 Mar 2007 15:57:25 -0000 1.40 +++ signal_template.hpp 1 Mar 2007 19:06:09 -0000 1.41 @@ -290,15 +290,14 @@ // clean up disconnected connections void nolock_cleanup_connections(bool grab_tracked, - const typename connection_list_type::iterator &begin, const typename connection_list_type::iterator &end) const + const typename connection_list_type::iterator &begin, bool break_on_connected = false) const { - assert(_shared_state.unique()); + BOOST_ASSERT(_shared_state.unique()); typename connection_list_type::iterator it; - for(it = begin; it != end;) + for(it = begin; it != _shared_state->connection_bodies.end();) { bool 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(); @@ -310,13 +309,15 @@ }else { ++it; + if(break_on_connected) break; } } - _garbage_collector_it = end; + _garbage_collector_it = it; } // clean up a few connections in constant time void nolock_cleanup_connections(bool grab_tracked) const { + BOOST_ASSERT(_shared_state.unique()); typename connection_list_type::iterator begin; if(_garbage_collector_it == _shared_state->connection_bodies.end()) { @@ -325,10 +326,7 @@ { begin = _garbage_collector_it; } - typename connection_list_type::iterator end = begin; - ++end; - if(end != _shared_state->connection_bodies.end()) ++end; - nolock_cleanup_connections(grab_tracked, begin, end); + nolock_cleanup_connections(grab_tracked, begin, true); } /* Make a new copy of the slot list if it is currently being read somewhere else */ @@ -338,7 +336,7 @@ { shared_ptr<invocation_state> newState(new invocation_state(*_shared_state)); _shared_state = newState; - nolock_cleanup_connections(true, _shared_state->connection_bodies.begin(), _shared_state->connection_bodies.end()); + nolock_cleanup_connections(true, _shared_state->connection_bodies.begin()); }else { nolock_cleanup_connections(true); |
|
From: Frank M. H. <fm...@us...> - 2007-03-01 18:57:42
|
Update of /cvsroot/boost-sandbox/boost-sandbox/boost/thread_safe_signals/detail In directory sc8-pr-cvs3.sourceforge.net:/tmp/cvs-serv14588/boost/thread_safe_signals/detail Modified Files: slot_groups.hpp Log Message: Fixed some problems with slot ordering due to my misunderstanding of how std::map::insert() handles the case of an already existing key. Index: slot_groups.hpp =================================================================== RCS file: /cvsroot/boost-sandbox/boost-sandbox/boost/thread_safe_signals/detail/slot_groups.hpp,v retrieving revision 1.13 retrieving revision 1.14 diff -u -d -r1.13 -r1.14 --- slot_groups.hpp 28 Feb 2007 17:08:48 -0000 1.13 +++ slot_groups.hpp 1 Mar 2007 18:57:35 -0000 1.14 @@ -16,7 +16,6 @@ #include <boost/thread_safe_signals/connection.hpp> #include <boost/optional.hpp> -#include <cassert> #include <list> #include <map> #include <utility> @@ -108,7 +107,7 @@ { map_iterator map_it; if(key.first == back_ungrouped_slots) - { + {// optimization map_it = _group_map.end(); }else { @@ -129,19 +128,18 @@ } iterator erase(const group_key_type &key, const iterator &it) { - assert(it != _list.end()); + BOOST_ASSERT(it != _list.end()); map_iterator map_it = _group_map.lower_bound(key); - assert(map_it != _group_map.end()); - assert(weakly_equivalent(map_it->first, key)); + BOOST_ASSERT(map_it != _group_map.end()); + BOOST_ASSERT(weakly_equivalent(map_it->first, key)); if(map_it->second == it) { iterator next = it; ++next; // if next is in same group - if(next != _list.end() && next != upper_bound(key)) + if(next != upper_bound(key)) { - // also erases old entry - _group_map.insert(map_it, typename map_type::value_type(key, next)); + _group_map[key] = next; }else { _group_map.erase(map_it); @@ -173,7 +171,7 @@ if(lower_bound_it == _group_map.end() || weakly_equivalent(lower_bound_it->first, key) == false) { - _group_map.insert(typename map_type::value_type(key, new_it)); + _group_map[key] = new_it; } } iterator get_list_iterator(const map_iterator &map_it) |
|
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: |
|
From: Frank M. H. <fm...@us...> - 2007-03-01 15:57:29
|
Update of /cvsroot/boost-sandbox/boost-sandbox/boost In directory sc8-pr-cvs3.sourceforge.net:/tmp/cvs-serv10496/boost Modified Files: thread_safe_signal.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: thread_safe_signal.hpp =================================================================== RCS file: /cvsroot/boost-sandbox/boost-sandbox/boost/thread_safe_signal.hpp,v retrieving revision 1.15 retrieving revision 1.16 diff -u -d -r1.15 -r1.16 --- thread_safe_signal.hpp 27 Feb 2007 21:19:25 -0000 1.15 +++ thread_safe_signal.hpp 1 Mar 2007 15:57:25 -0000 1.16 @@ -31,6 +31,7 @@ #define BOOST_SIGNALS_NAMESPACE signalslib #include <algorithm> +#include <boost/assert.hpp> #include <boost/function.hpp> #include <boost/last_value.hpp> #include <boost/preprocessor/arithmetic.hpp> @@ -44,6 +45,7 @@ #include <boost/thread_safe_signals/detail/slot_groups.hpp> #include <boost/thread_safe_signals/detail/slot_call_iterator.hpp> #include <boost/thread_safe_signals/connection.hpp> +#include <boost/thread_safe_signals/auto_threaded.hpp> #include <boost/thread_safe_signals/single_threaded.hpp> #include <boost/thread_safe_signals/slot.hpp> #include <boost/thread_safe_signals/track.hpp> @@ -64,7 +66,7 @@ typename Group = int, typename GroupCompare = std::less<Group>, typename SlotFunction = boost::function<Signature>, - typename ThreadingModel = signalslib::single_threaded > + typename ThreadingModel = signalslib::auto_threaded > class signal: public signalslib::detail::signalN<function_traits<Signature>::arity, Signature, Combiner, Group, GroupCompare, SlotFunction, ThreadingModel>::type { |
Update of /cvsroot/boost-sandbox/boost-sandbox/boost/thread_safe_signals In directory sc8-pr-cvs3.sourceforge.net:/tmp/cvs-serv10496/boost/thread_safe_signals Modified Files: connection.hpp slot.hpp Added Files: auto_threaded.hpp multi_threaded.hpp single_threaded.hpp Removed Files: trackable.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. --- NEW FILE: auto_threaded.hpp --- // Boost.Signals library // Copyright Frank Mori Hess 2007. // distribution is subject to the Boost Software License, Version // 1.0. (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // For more information, see http://www.boost.org #ifndef BOOST_SIGNALS_MULTI_THREADED_MODEL_HEADER #define BOOST_SIGNALS_MULTI_THREADED_MODEL_HEADER #include <boost/detail/lightweight_mutex.hpp> #ifdef BOOST_HAS_ABI_HEADERS # include BOOST_ABI_PREFIX #endif namespace boost { namespace signalslib { class auto_threaded { public: typedef boost::detail::lightweight_mutex mutex_type; }; } // end namespace signalslib } // end namespace boost #ifdef BOOST_HAS_ABI_HEADERS # include BOOST_ABI_SUFFIX #endif #endif // BOOST_SIGNALS_MULTI_THREADED_MODEL_HEADER --- NEW FILE: single_threaded.hpp --- // Boost.Signals library // Copyright Frank Mori Hess 2007. // distribution is subject to the Boost Software License, Version // 1.0. (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // For more information, see http://www.boost.org #ifndef BOOST_SIGNALS_SINGLE_THREADED_MODEL_HEADER #define BOOST_SIGNALS_SINGLE_THREADED_MODEL_HEADER #ifdef BOOST_HAS_ABI_HEADERS # include BOOST_ABI_PREFIX #endif namespace boost { namespace signalslib { namespace detail { class null_mutex; class null_scoped_lock { public: null_scoped_lock(const null_mutex &mutex) {} bool locked() const {return true;} }; class null_mutex { public: typedef null_scoped_lock scoped_lock; }; } class single_threaded { public: typedef detail::null_mutex mutex_type; }; } // end namespace signalslib } // end namespace boost #ifdef BOOST_HAS_ABI_HEADERS # include BOOST_ABI_SUFFIX #endif #endif // BOOST_SIGNALS_SINGLE_THREADED_MODEL_HEADER --- NEW FILE: multi_threaded.hpp --- // Boost.Signals library // Copyright Frank Mori Hess 2007. // distribution is subject to the Boost Software License, Version // 1.0. (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // For more information, see http://www.boost.org #ifndef BOOST_SIGNALS_MULTI_THREADED_MODEL_HEADER #define BOOST_SIGNALS_MULTI_THREADED_MODEL_HEADER #include <boost/thread/mutex.hpp> #include <boost/thread/recursive_mutex.hpp> #ifdef BOOST_HAS_ABI_HEADERS # include BOOST_ABI_PREFIX #endif namespace boost { namespace signalslib { class multi_threaded { public: typedef mutex mutex_type; }; } // end namespace signalslib } // end namespace boost #ifdef BOOST_HAS_ABI_HEADERS # include BOOST_ABI_SUFFIX #endif #endif // BOOST_SIGNALS_MULTI_THREADED_MODEL_HEADER Index: slot.hpp =================================================================== RCS file: /cvsroot/boost-sandbox/boost-sandbox/boost/thread_safe_signals/slot.hpp,v retrieving revision 1.14 retrieving revision 1.15 diff -u -d -r1.14 -r1.15 --- slot.hpp 27 Feb 2007 21:19:25 -0000 1.14 +++ slot.hpp 1 Mar 2007 15:57:25 -0000 1.15 @@ -19,7 +19,6 @@ #include <boost/thread_safe_signals/detail/signals_common_macros.hpp> #include <boost/thread_safe_signals/slot_base.hpp> #include <boost/thread_safe_signals/track.hpp> -#include <boost/thread_safe_signals/trackable.hpp> #include <boost/type_traits.hpp> #include <boost/utility/addressof.hpp> #include <boost/weak_ptr.hpp> Index: connection.hpp =================================================================== RCS file: /cvsroot/boost-sandbox/boost-sandbox/boost/thread_safe_signals/connection.hpp,v retrieving revision 1.20 retrieving revision 1.21 diff -u -d -r1.20 -r1.21 --- connection.hpp 28 Feb 2007 20:48:30 -0000 1.20 +++ connection.hpp 1 Mar 2007 15:57:25 -0000 1.21 @@ -25,7 +25,6 @@ #include <boost/mpl/bool.hpp> #include <boost/noncopyable.hpp> #include <boost/shared_ptr.hpp> -#include <boost/thread_safe_signals/detail/signal_base.hpp> #include <boost/thread_safe_signals/slot.hpp> #include <boost/thread_safe_signals/track.hpp> #include <boost/type_traits.hpp> @@ -42,8 +41,7 @@ class ConnectionBodyBase { public: - typedef signal_impl_base::mutex_type mutex_type; - ConnectionBodyBase(const shared_ptr<mutex_type> &mutex): _mutex(mutex), + ConnectionBodyBase(): _connected(true), _blocked(false) { } @@ -64,41 +62,40 @@ return _blocked || (nolock_nograb_connected() == false); } bool nolock_nograb_connected() const {return _connected;} -//FIXME: make _mutex protected once slot_call_iterator no longer needs it. - shared_ptr<mutex_type> _mutex; protected: mutable bool _connected; bool _blocked; }; - template<typename GroupKey, typename SlotType> + template<typename GroupKey, typename SlotType, typename ThreadingModel> class ConnectionBody: public ConnectionBodyBase { public: - ConnectionBody(const shared_ptr<mutex_type> &mutex, const SlotType &slot_in): - ConnectionBodyBase(mutex), slot(slot_in) + typedef typename ThreadingModel::mutex_type mutex_type; + ConnectionBody(const SlotType &slot_in): + slot(slot_in) { } virtual ~ConnectionBody() {} virtual void disconnect() { - typename mutex_type::scoped_lock lock(*_mutex); + typename mutex_type::scoped_lock lock(mutex); nolock_disconnect(); } virtual bool connected() const { - typename mutex_type::scoped_lock lock(*_mutex); + typename mutex_type::scoped_lock lock(mutex); nolock_grab_tracked_objects(); return nolock_nograb_connected(); } virtual void block(bool should_block) { - typename mutex_type::scoped_lock lock(*_mutex); + typename mutex_type::scoped_lock lock(mutex); _blocked = should_block; } virtual bool blocked() const { - typename mutex_type::scoped_lock lock(*_mutex); + typename mutex_type::scoped_lock lock(mutex); nolock_grab_tracked_objects(); return nolock_nograb_blocked(); } @@ -128,6 +125,7 @@ return locked_objects; } SlotType slot; + mutable mutex_type mutex; private: GroupKey _group_key; }; --- trackable.hpp DELETED --- |
|
From: Frank M. H. <fm...@us...> - 2007-02-28 20:49:43
|
Update of /cvsroot/boost-sandbox/boost-sandbox/libs/thread_safe_signals/test In directory sc8-pr-cvs3.sourceforge.net:/tmp/cvs-serv3154 Added Files: invocation_benchmark.cpp Log Message: Added little benchmark program --- NEW FILE: invocation_benchmark.cpp --- #include <cstdlib> #include <iostream> #include <boost/bind.hpp> #include <boost/thread_safe_signal.hpp> #include <boost/thread/thread.hpp> typedef boost::signal<void ()> signal_type; void myslot() { /* std::cout << __FUNCTION__ << std::endl; sleep(1);*/ } void thread_initial(signal_type *signal, unsigned num_invocations) { unsigned i; for(i = 0; i < num_invocations; ++i) { (*signal)(); } } int main(int argc, const char **argv) { if(argc < 3) { std::cerr << "usage: " << argv[0] << " <num threads> <num connections>" << std::endl; return -1; } static const unsigned num_threads = std::strtol(argv[1], 0, 0); static const unsigned num_connections = std::strtol(argv[2], 0, 0); boost::thread_group threads; signal_type sig; std::cout << "Connecting " << num_connections << " connections to signal.\n"; unsigned i; for(i = 0; i < num_connections; ++i) { sig.connect(&myslot); } const unsigned num_slot_invocations = 1000000; const unsigned signal_invocations_per_thread = num_slot_invocations / (num_threads * num_connections); std::cout << "Launching " << num_threads << " thread(s) to invoke signal " << signal_invocations_per_thread << " times per thread.\n"; for(i = 0; i < num_threads; ++i) { threads.create_thread(boost::bind(&thread_initial, &sig, signal_invocations_per_thread)); } threads.join_all(); return 0; } |
|
From: Frank M. H. <fm...@us...> - 2007-02-28 20:48:35
|
Update of /cvsroot/boost-sandbox/boost-sandbox/boost/thread_safe_signals/detail In directory sc8-pr-cvs3.sourceforge.net:/tmp/cvs-serv2276/boost/thread_safe_signals/detail Modified Files: signal_base.hpp signal_template.hpp slot_call_iterator.hpp Log Message: Got rid of per-slot mutexes and ThreadingModel template parameter. Use boost/detail/lightweight_mutex.hpp for the mutex now. Still need to optimize locking so it doesn't lock the mutex once for every slot during invocation. 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.20 retrieving revision 1.21 diff -u -d -r1.20 -r1.21 --- slot_call_iterator.hpp 27 Feb 2007 21:19:25 -0000 1.20 +++ slot_call_iterator.hpp 28 Feb 2007 20:48:30 -0000 1.21 @@ -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.38 retrieving revision 1.39 diff -u -d -r1.38 -r1.39 --- signal_template.hpp 28 Feb 2007 19:30:18 -0000 1.38 +++ signal_template.hpp 28 Feb 2007 20:48:30 -0000 1.39 @@ -34,20 +34,18 @@ 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 ThreadingModel = signalslib::single_threaded + typename SlotFunction = BOOST_FUNCTION_N_DECL(BOOST_SIGNALS_NUM_ARGS) // 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, \ - typename ThreadingModel -// R, T1, T2, ..., TN, Combiner, Group, GroupCompare, SlotFunction, ThreadingModel + typename SlotFunction +// R, T1, T2, ..., TN, Combiner, Group, GroupCompare, SlotFunction #define BOOST_SIGNAL_TEMPLATE_INSTANTIATION \ BOOST_SIGNAL_SIGNATURE_TEMPLATE_INSTANTIATION(BOOST_SIGNALS_NUM_ARGS), \ - Combiner, Group, GroupCompare, SlotFunction, ThreadingModel + Combiner, Group, GroupCompare, SlotFunction namespace boost { @@ -56,7 +54,7 @@ namespace detail { template<BOOST_SIGNAL_TEMPLATE_DECL> - class BOOST_SIGNAL_IMPL_CLASS_NAME + class BOOST_SIGNAL_IMPL_CLASS_NAME: public signal_impl_base { public: typedef SlotFunction slot_function_type; @@ -66,7 +64,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, ThreadingModel> > connection_body_type; + typedef shared_ptr<ConnectionBody<group_key_type, slot_type> > 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; @@ -75,7 +73,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, ThreadingModel> > slot_call_iterator; + typename connection_list_type::iterator, ConnectionBody<group_key_type, SlotFunction> > slot_call_iterator; BOOST_SIGNAL_IMPL_CLASS_NAME(const combiner_type &combiner, const group_compare_type &group_compare): @@ -85,7 +83,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; @@ -104,7 +102,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 @@ -157,7 +155,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); @@ -178,7 +176,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); @@ -221,19 +219,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 ThreadingModel::mutex_type mutex_type; + typedef typename signal_impl_base::mutex_type mutex_type; // slot_invoker is passed to slot_call_iterator_t to run slots class slot_invoker @@ -297,19 +295,9 @@ for(it = begin; it != end;) { bool connected; - { - // skip over slots that are busy - typename ConnectionBody<group_key_type, SlotFunction, ThreadingModel>::mutex_type::scoped_try_lock lock((*it)->mutex); - if(lock.locked() == false) - { - connected = true; - }else - { - if(grab_tracked) - (*it)->nolock_slot_expired(); - connected = (*it)->nolock_nograb_connected(); - } - }// scoped lock destructs here, safe to erase now + if(grab_tracked) + (*it)->nolock_slot_expired(); + connected = (*it)->nolock_nograb_connected(); if(connected == false) { it = _shared_state->connection_bodies.erase((*it)->group_key(), it); @@ -352,13 +340,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, ThreadingModel>(slot)); + return connection_body_type(new ConnectionBody<group_key_type, slot_type>(_mutex, slot)); } void do_disconnect(const group_type &group, mpl::bool_<true> is_group) { @@ -373,7 +361,7 @@ for(it = local_state->connection_bodies.begin(); it != local_state->connection_bodies.end(); ++it) { - typename ConnectionBody<group_key_type, slot_function_type, ThreadingModel>::mutex_type::scoped_lock lock((*it)->mutex); + typename mutex_type::scoped_lock lock(*_mutex); if((*it)->slot.slot_function() == slot) { (*it)->nolock_disconnect(); @@ -383,9 +371,6 @@ 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> @@ -524,19 +509,19 @@ }; template<unsigned arity, typename Signature, typename Combiner, - typename Group, typename GroupCompare, typename SlotFunction, typename ThreadingModel> + typename Group, typename GroupCompare, typename SlotFunction> class signalN; // partial template specialization template<typename Signature, typename Combiner, typename Group, - typename GroupCompare, typename SlotFunction, typename ThreadingModel> + typename GroupCompare, typename SlotFunction> class signalN<BOOST_SIGNALS_NUM_ARGS, Signature, Combiner, Group, - GroupCompare, SlotFunction, ThreadingModel> + GroupCompare, SlotFunction> { public: typedef BOOST_SIGNAL_CLASS_NAME< BOOST_SIGNAL_PORTABLE_SIGNATURE(BOOST_SIGNALS_NUM_ARGS, Signature), Combiner, Group, - GroupCompare, SlotFunction, ThreadingModel> type; + GroupCompare, SlotFunction> type; }; } } Index: signal_base.hpp =================================================================== RCS file: /cvsroot/boost-sandbox/boost-sandbox/boost/thread_safe_signals/detail/signal_base.hpp,v retrieving revision 1.2 retrieving revision 1.3 diff -u -d -r1.2 -r1.3 --- signal_base.hpp 27 Feb 2007 21:19:25 -0000 1.2 +++ signal_base.hpp 28 Feb 2007 20:48:30 -0000 1.3 @@ -10,7 +10,9 @@ #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 @@ -21,6 +23,17 @@ 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: |
|
From: Frank M. H. <fm...@us...> - 2007-02-28 20:48:32
|
Update of /cvsroot/boost-sandbox/boost-sandbox/boost/thread_safe_signals In directory sc8-pr-cvs3.sourceforge.net:/tmp/cvs-serv2276/boost/thread_safe_signals Modified Files: connection.hpp Removed Files: multi_threaded.hpp single_threaded.hpp Log Message: Got rid of per-slot mutexes and ThreadingModel template parameter. Use boost/detail/lightweight_mutex.hpp for the mutex now. Still need to optimize locking so it doesn't lock the mutex once for every slot during invocation. Index: connection.hpp =================================================================== RCS file: /cvsroot/boost-sandbox/boost-sandbox/boost/thread_safe_signals/connection.hpp,v retrieving revision 1.19 retrieving revision 1.20 diff -u -d -r1.19 -r1.20 --- connection.hpp 27 Feb 2007 21:19:25 -0000 1.19 +++ connection.hpp 28 Feb 2007 20:48:30 -0000 1.20 @@ -25,6 +25,7 @@ #include <boost/mpl/bool.hpp> #include <boost/noncopyable.hpp> #include <boost/shared_ptr.hpp> +#include <boost/thread_safe_signals/detail/signal_base.hpp> #include <boost/thread_safe_signals/slot.hpp> #include <boost/thread_safe_signals/track.hpp> #include <boost/type_traits.hpp> @@ -41,7 +42,8 @@ class ConnectionBodyBase { public: - ConnectionBodyBase(): + typedef signal_impl_base::mutex_type mutex_type; + ConnectionBodyBase(const shared_ptr<mutex_type> &mutex): _mutex(mutex), _connected(true), _blocked(false) { } @@ -62,40 +64,41 @@ return _blocked || (nolock_nograb_connected() == false); } bool nolock_nograb_connected() const {return _connected;} +//FIXME: make _mutex protected once slot_call_iterator no longer needs it. + shared_ptr<mutex_type> _mutex; protected: mutable bool _connected; bool _blocked; }; - template<typename GroupKey, typename SlotType, typename ThreadingModel> + template<typename GroupKey, typename SlotType> class ConnectionBody: public ConnectionBodyBase { public: - typedef typename ThreadingModel::try_mutex_type mutex_type; - ConnectionBody(const SlotType &slot_in): - slot(slot_in) + ConnectionBody(const shared_ptr<mutex_type> &mutex, const SlotType &slot_in): + ConnectionBodyBase(mutex), slot(slot_in) { } virtual ~ConnectionBody() {} virtual void disconnect() { - typename mutex_type::scoped_lock lock(mutex); + typename mutex_type::scoped_lock lock(*_mutex); nolock_disconnect(); } virtual bool connected() const { - typename mutex_type::scoped_lock lock(mutex); + typename mutex_type::scoped_lock lock(*_mutex); nolock_grab_tracked_objects(); return nolock_nograb_connected(); } virtual void block(bool should_block) { - typename mutex_type::scoped_lock lock(mutex); + typename mutex_type::scoped_lock lock(*_mutex); _blocked = should_block; } virtual bool blocked() const { - typename mutex_type::scoped_lock lock(mutex); + typename mutex_type::scoped_lock lock(*_mutex); nolock_grab_tracked_objects(); return nolock_nograb_blocked(); } @@ -125,7 +128,6 @@ return locked_objects; } SlotType slot; - mutable mutex_type mutex; private: GroupKey _group_key; }; --- single_threaded.hpp DELETED --- --- multi_threaded.hpp DELETED --- |
|
From: Frank M. H. <fm...@us...> - 2007-02-28 20:15:48
|
Update of /cvsroot/boost-sandbox/boost-sandbox/libs/thread_safe_signals/test In directory sc8-pr-cvs3.sourceforge.net:/tmp/cvs-serv9125 Modified Files: dead_slot_test.cpp deletion_test.cpp ordering_test.cpp signal_n_test.cpp signal_test.cpp Log Message: Altered tests to account for changes from signals to thread_safe_signals. Index: signal_test.cpp =================================================================== RCS file: /cvsroot/boost-sandbox/boost-sandbox/libs/thread_safe_signals/test/signal_test.cpp,v retrieving revision 1.1 retrieving revision 1.2 diff -u -d -r1.1 -r1.2 --- signal_test.cpp 28 Feb 2007 19:16:04 -0000 1.1 +++ signal_test.cpp 28 Feb 2007 19:44:09 -0000 1.2 @@ -8,7 +8,7 @@ // For more information, see http://www.boost.org #include <boost/test/minimal.hpp> -#include <boost/signal.hpp> +#include <boost/thread_safe_signal.hpp> #include <functional> #include <iostream> @@ -132,22 +132,22 @@ static void test_signal_signal_connect() { - boost::signal<int (int value), max_or_default<int> > s1; + typedef boost::signal<int (int value), max_or_default<int> > signal_type; + signal_type s1; s1.connect(std::negate<int>()); BOOST_CHECK(s1(3) == -3); { - boost::signal<int (int value), max_or_default<int> > s2; - s1.connect(s2); + signal_type s2; + s1.connect(signal_type::slot_type(s2).track(s2)); s2.connect(std::bind1st(std::multiplies<int>(), 2)); s2.connect(std::bind1st(std::multiplies<int>(), -3)); BOOST_CHECK(s2(-3) == 9); BOOST_CHECK(s1(3) == 6); } // s2 goes out of scope and disconnects - BOOST_CHECK(s1(3) == -3); } Index: signal_n_test.cpp =================================================================== RCS file: /cvsroot/boost-sandbox/boost-sandbox/libs/thread_safe_signals/test/signal_n_test.cpp,v retrieving revision 1.1 retrieving revision 1.2 diff -u -d -r1.1 -r1.2 --- signal_n_test.cpp 28 Feb 2007 19:16:04 -0000 1.1 +++ signal_n_test.cpp 28 Feb 2007 19:44:09 -0000 1.2 @@ -8,7 +8,7 @@ // For more information, see http://www.boost.org #include <boost/test/minimal.hpp> -#include <boost/signal.hpp> +#include <boost/thread_safe_signal.hpp> #include <functional> template<typename T> @@ -134,15 +134,16 @@ static void test_signal_signal_connect() { - boost::signal1<int, int, max_or_default<int> > s1; + typedef boost::signal1<int, int, max_or_default<int> > signal_type; + signal_type s1; s1.connect(std::negate<int>()); BOOST_CHECK(s1(3) == -3); { - boost::signal1<int, int, max_or_default<int> > s2; - s1.connect(s2); + signal_type s2; + s1.connect(signal_type::slot_type(s2).track(s2)); s2.connect(std::bind1st(std::multiplies<int>(), 2)); s2.connect(std::bind1st(std::multiplies<int>(), -3)); Index: ordering_test.cpp =================================================================== RCS file: /cvsroot/boost-sandbox/boost-sandbox/libs/thread_safe_signals/test/ordering_test.cpp,v retrieving revision 1.1 retrieving revision 1.2 diff -u -d -r1.1 -r1.2 --- ordering_test.cpp 28 Feb 2007 19:16:04 -0000 1.1 +++ ordering_test.cpp 28 Feb 2007 19:44:09 -0000 1.2 @@ -8,7 +8,7 @@ // For more information, see http://www.boost.org #include <boost/test/minimal.hpp> -#include <boost/signal.hpp> +#include <boost/thread_safe_signal.hpp> #include <iostream> #include <vector> #include <algorithm> Index: deletion_test.cpp =================================================================== RCS file: /cvsroot/boost-sandbox/boost-sandbox/libs/thread_safe_signals/test/deletion_test.cpp,v retrieving revision 1.1 retrieving revision 1.2 diff -u -d -r1.1 -r1.2 --- deletion_test.cpp 28 Feb 2007 19:16:04 -0000 1.1 +++ deletion_test.cpp 28 Feb 2007 19:44:09 -0000 1.2 @@ -8,7 +8,7 @@ // For more information, see http://www.boost.org #include <boost/test/minimal.hpp> -#include <boost/signal.hpp> +#include <boost/thread_safe_signal.hpp> #include <iostream> #include <string> Index: dead_slot_test.cpp =================================================================== RCS file: /cvsroot/boost-sandbox/boost-sandbox/libs/thread_safe_signals/test/dead_slot_test.cpp,v retrieving revision 1.1 retrieving revision 1.2 diff -u -d -r1.1 -r1.2 --- dead_slot_test.cpp 28 Feb 2007 19:16:04 -0000 1.1 +++ dead_slot_test.cpp 28 Feb 2007 19:44:09 -0000 1.2 @@ -7,13 +7,14 @@ // For more information, see http://www.boost.org +#include <boost/shared_ptr.hpp> #include <boost/test/minimal.hpp> #include <boost/thread_safe_signal.hpp> #include <boost/bind.hpp> typedef boost::signal1<int, int> sig_type; -class with_constant : public boost::BOOST_SIGNALS_NAMESPACE::trackable { +class with_constant { public: with_constant(int c) : constant(c) {} @@ -23,12 +24,12 @@ int constant; }; -void do_delayed_connect(with_constant* wc, +void do_delayed_connect(boost::shared_ptr<with_constant> &wc, sig_type& sig, sig_type::slot_type slot) { // Should invalidate the slot, so that we cannot connect to it - delete wc; + wc.reset(); boost::BOOST_SIGNALS_NAMESPACE::connection c = sig.connect(slot); BOOST_CHECK(!c.connected()); @@ -37,9 +38,9 @@ int test_main(int, char*[]) { sig_type s1; - with_constant* wc1 = new with_constant(7); + boost::shared_ptr<with_constant> wc1(new with_constant(7)); - do_delayed_connect(wc1, s1, boost::bind(&with_constant::add, wc1, _1)); + do_delayed_connect(wc1, s1, sig_type::slot_type(&with_constant::add, wc1.get(), _1).track(wc1)); return 0; } |
|
From: Frank M. H. <fm...@us...> - 2007-02-28 19:30:21
|
Update of /cvsroot/boost-sandbox/boost-sandbox/boost/thread_safe_signals/detail In directory sc8-pr-cvs3.sourceforge.net:/tmp/cvs-serv3517/boost/thread_safe_signals/detail Modified Files: signal_template.hpp slot_template.hpp Log Message: Fixed signal::disconnect() with a slot function argument, which was broken by recent changes to slot class. Index: signal_template.hpp =================================================================== RCS file: /cvsroot/boost-sandbox/boost-sandbox/boost/thread_safe_signals/detail/signal_template.hpp,v retrieving revision 1.37 retrieving revision 1.38 diff -u -d -r1.37 -r1.38 --- signal_template.hpp 28 Feb 2007 17:08:48 -0000 1.37 +++ signal_template.hpp 28 Feb 2007 19:30:18 -0000 1.38 @@ -374,7 +374,7 @@ it != local_state->connection_bodies.end(); ++it) { typename ConnectionBody<group_key_type, slot_function_type, ThreadingModel>::mutex_type::scoped_lock lock((*it)->mutex); - if((*it)->slot == slot) + if((*it)->slot.slot_function() == slot) { (*it)->nolock_disconnect(); } Index: slot_template.hpp =================================================================== RCS file: /cvsroot/boost-sandbox/boost-sandbox/boost/thread_safe_signals/detail/slot_template.hpp,v retrieving revision 1.4 retrieving revision 1.5 diff -u -d -r1.4 -r1.5 --- slot_template.hpp 28 Feb 2007 17:06:53 -0000 1.4 +++ slot_template.hpp 28 Feb 2007 19:30:18 -0000 1.5 @@ -29,6 +29,7 @@ template<BOOST_SIGNAL_PREFIXED_SIGNATURE_TEMPLATE_DECL(BOOST_SIGNALS_NUM_ARGS, Other), typename OtherSlotFunction> friend class BOOST_SLOT_CLASS_NAME(BOOST_SIGNALS_NUM_ARGS); + typedef SlotFunction slot_function_type; typedef R result_type; // typedef Tn argn_type; #define BOOST_SIGNAL_MISC_STATEMENT(z, n, data) \ @@ -98,8 +99,8 @@ track_signal(signal); return *this; } + const slot_function_type& slot_function() const {return _slot_function;} private: - SlotFunction _slot_function; }; namespace signalslib |
|
From: Frank M. H. <fm...@us...> - 2007-02-28 19:16:06
|
Update of /cvsroot/boost-sandbox/boost-sandbox/libs/thread_safe_signals/test In directory sc8-pr-cvs3.sourceforge.net:/tmp/cvs-serv30354 Added Files: dead_slot_test.cpp deletion_test.cpp ordering_test.cpp signal_n_test.cpp signal_test.cpp Log Message: Added test programs from boost/libs/signals/test --- NEW FILE: signal_test.cpp --- // Boost.Signals library // Copyright Douglas Gregor 2001-2003. Use, modification and // distribution is subject to the Boost Software License, Version // 1.0. (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // For more information, see http://www.boost.org #include <boost/test/minimal.hpp> #include <boost/signal.hpp> #include <functional> #include <iostream> template<typename T> struct max_or_default { typedef T result_type; template<typename InputIterator> typename InputIterator::value_type operator()(InputIterator first, InputIterator last) const { if (first == last) return T(); T max = *first++; for (; first != last; ++first) max = (*first > max)? *first : max; return max; } }; struct make_int { make_int(int n, int cn) : N(n), CN(cn) {} int operator()() { return N; } int operator()() const { return CN; } int N; int CN; }; template<int N> struct make_increasing_int { make_increasing_int() : n(N) {} int operator()() const { return n++; } mutable int n; }; static void test_zero_args() { make_int i42(42, 41); make_int i2(2, 1); make_int i72(72, 71); make_int i63(63, 63); make_int i62(62, 61); { boost::signal<int (), max_or_default<int> > s0; std::cout << "sizeof(signal) = " << sizeof(s0) << std::endl; boost::BOOST_SIGNALS_NAMESPACE::connection c2 = s0.connect(i2); boost::BOOST_SIGNALS_NAMESPACE::connection c72 = s0.connect(72, i72); boost::BOOST_SIGNALS_NAMESPACE::connection c62 = s0.connect(60, i62); boost::BOOST_SIGNALS_NAMESPACE::connection c42 = s0.connect(i42); BOOST_CHECK(s0() == 72); s0.disconnect(72); BOOST_CHECK(s0() == 62); c72.disconnect(); // Double-disconnect should be safe BOOST_CHECK(s0() == 62); s0.disconnect(72); // Triple-disconect should be safe BOOST_CHECK(s0() == 62); // Also connect 63 in the same group as 62 s0.connect(60, i63); BOOST_CHECK(s0() == 63); // Disconnect all of the 60's s0.disconnect(60); BOOST_CHECK(s0() == 42); c42.disconnect(); BOOST_CHECK(s0() == 2); c2.disconnect(); BOOST_CHECK(s0() == 0); } { boost::signal<int (), max_or_default<int> > s0; boost::BOOST_SIGNALS_NAMESPACE::connection c2 = s0.connect(i2); boost::BOOST_SIGNALS_NAMESPACE::connection c72 = s0.connect(i72); boost::BOOST_SIGNALS_NAMESPACE::connection c62 = s0.connect(i62); boost::BOOST_SIGNALS_NAMESPACE::connection c42 = s0.connect(i42); const boost::signal<int (), max_or_default<int> >& cs0 = s0; BOOST_CHECK(cs0() == 72); } { make_increasing_int<7> i7; make_increasing_int<10> i10; boost::signal<int (), max_or_default<int> > s0; boost::BOOST_SIGNALS_NAMESPACE::connection c7 = s0.connect(i7); boost::BOOST_SIGNALS_NAMESPACE::connection c10 = s0.connect(i10); BOOST_CHECK(s0() == 10); BOOST_CHECK(s0() == 11); } } static void test_one_arg() { boost::signal<int (int value), max_or_default<int> > s1; s1.connect(std::negate<int>()); s1.connect(std::bind1st(std::multiplies<int>(), 2)); BOOST_CHECK(s1(1) == 2); BOOST_CHECK(s1(-1) == 1); } static void test_signal_signal_connect() { boost::signal<int (int value), max_or_default<int> > s1; s1.connect(std::negate<int>()); BOOST_CHECK(s1(3) == -3); { boost::signal<int (int value), max_or_default<int> > s2; s1.connect(s2); s2.connect(std::bind1st(std::multiplies<int>(), 2)); s2.connect(std::bind1st(std::multiplies<int>(), -3)); BOOST_CHECK(s2(-3) == 9); BOOST_CHECK(s1(3) == 6); } // s2 goes out of scope and disconnects BOOST_CHECK(s1(3) == -3); } int test_main(int, char* []) { test_zero_args(); test_one_arg(); test_signal_signal_connect(); return 0; } --- NEW FILE: signal_n_test.cpp --- // Boost.Signals library // Copyright Douglas Gregor 2001-2003. Use, modification and // distribution is subject to the Boost Software License, Version // 1.0. (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // For more information, see http://www.boost.org #include <boost/test/minimal.hpp> #include <boost/signal.hpp> #include <functional> template<typename T> struct max_or_default { typedef T result_type; template<typename InputIterator> typename InputIterator::value_type operator()(InputIterator first, InputIterator last) const { if (first == last) return T(); T max = *first++; for (; first != last; ++first) max = (*first > max)? *first : max; return max; } }; struct make_int { make_int(int n, int cn) : N(n), CN(n) {} int operator()() { return N; } int operator()() const { return CN; } int N; int CN; }; template<int N> struct make_increasing_int { make_increasing_int() : n(N) {} int operator()() const { return n++; } mutable int n; }; int get_37() { return 37; } static void test_zero_args() { make_int i42(42, 41); make_int i2(2, 1); make_int i72(72, 71); make_int i63(63, 63); make_int i62(62, 61); { boost::signal0<int, max_or_default<int>, std::string> s0; boost::BOOST_SIGNALS_NAMESPACE::connection c2 = s0.connect(i2); boost::BOOST_SIGNALS_NAMESPACE::connection c72 = s0.connect("72", i72); boost::BOOST_SIGNALS_NAMESPACE::connection c62 = s0.connect("6x", i62); boost::BOOST_SIGNALS_NAMESPACE::connection c42 = s0.connect(i42); boost::BOOST_SIGNALS_NAMESPACE::connection c37 = s0.connect(&get_37); BOOST_CHECK(s0() == 72); s0.disconnect("72"); BOOST_CHECK(s0() == 62); c72.disconnect(); // Double-disconnect should be safe BOOST_CHECK(s0() == 62); s0.disconnect("72"); // Triple-disconect should be safe BOOST_CHECK(s0() == 62); // Also connect 63 in the same group as 62 s0.connect("6x", i63); BOOST_CHECK(s0() == 63); // Disconnect all of the 60's s0.disconnect("6x"); BOOST_CHECK(s0() == 42); c42.disconnect(); BOOST_CHECK(s0() == 37); c37.disconnect(); BOOST_CHECK(s0() == 2); c2.disconnect(); BOOST_CHECK(s0() == 0); } { boost::signal0<int, max_or_default<int> > s0; boost::BOOST_SIGNALS_NAMESPACE::connection c2 = s0.connect(i2); boost::BOOST_SIGNALS_NAMESPACE::connection c72 = s0.connect(i72); boost::BOOST_SIGNALS_NAMESPACE::connection c62 = s0.connect(i62); boost::BOOST_SIGNALS_NAMESPACE::connection c42 = s0.connect(i42); const boost::signal0<int, max_or_default<int> >& cs0 = s0; BOOST_CHECK(cs0() == 72); } { make_increasing_int<7> i7; make_increasing_int<10> i10; boost::signal0<int, max_or_default<int> > s0; boost::BOOST_SIGNALS_NAMESPACE::connection c7 = s0.connect(i7); boost::BOOST_SIGNALS_NAMESPACE::connection c10 = s0.connect(i10); BOOST_CHECK(s0() == 10); BOOST_CHECK(s0() == 11); } } static void test_one_arg() { boost::signal1<int, int, max_or_default<int> > s1; s1.connect(std::negate<int>()); s1.connect(std::bind1st(std::multiplies<int>(), 2)); BOOST_CHECK(s1(1) == 2); BOOST_CHECK(s1(-1) == 1); } static void test_signal_signal_connect() { boost::signal1<int, int, max_or_default<int> > s1; s1.connect(std::negate<int>()); BOOST_CHECK(s1(3) == -3); { boost::signal1<int, int, max_or_default<int> > s2; s1.connect(s2); s2.connect(std::bind1st(std::multiplies<int>(), 2)); s2.connect(std::bind1st(std::multiplies<int>(), -3)); BOOST_CHECK(s2(-3) == 9); BOOST_CHECK(s1(3) == 6); } // s2 goes out of scope and disconnects BOOST_CHECK(s1(3) == -3); } struct EventCounter { EventCounter() : count(0) {} void operator()() { ++count; } int count; }; static void test_ref() { EventCounter ec; boost::signal0<void> s; { boost::BOOST_SIGNALS_NAMESPACE::scoped_connection c = s.connect(boost::ref(ec)); BOOST_CHECK(ec.count == 0); s(); BOOST_CHECK(ec.count == 1); } s(); BOOST_CHECK(ec.count == 1); } int test_main(int, char* []) { test_zero_args(); test_one_arg(); test_signal_signal_connect(); test_ref(); return 0; } --- NEW FILE: ordering_test.cpp --- // Boost.Signals library // Copyright Douglas Gregor 2002-2004. Use, modification and // distribution is subject to the Boost Software License, Version // 1.0. (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // For more information, see http://www.boost.org #include <boost/test/minimal.hpp> #include <boost/signal.hpp> #include <iostream> #include <vector> #include <algorithm> #include <cstdlib> #include <ctime> std::vector<int> valuesOutput; bool ungrouped1 = false; bool ungrouped2 = false; bool ungrouped3 = false; struct emit_int { emit_int(int v) : value(v) {} void operator()() const { BOOST_CHECK(value == 42 || (!ungrouped1 && !ungrouped2 && !ungrouped3)); valuesOutput.push_back(value); std::cout << value << ' '; } private: int value; }; struct write_ungrouped1 { void operator()() const { BOOST_CHECK(!ungrouped1); ungrouped1 = true; std::cout << "(Ungrouped #1)" << ' '; } }; struct write_ungrouped2 { void operator()() const { BOOST_CHECK(!ungrouped2); ungrouped2 = true; std::cout << "(Ungrouped #2)" << ' '; } }; struct write_ungrouped3 { void operator()() const { BOOST_CHECK(!ungrouped3); ungrouped3 = true; std::cout << "(Ungrouped #3)" << ' '; } }; int test_main(int, char* []) { using namespace std; srand(time(0)); std::vector<int> sortedValues; boost::signal0<void> sig; sig.connect(write_ungrouped1()); for (int i = 0; i < 100; ++i) { #ifdef BOOST_NO_STDC_NAMESPACE int v = rand() % 100; #else int v = std::rand() % 100; #endif sortedValues.push_back(v); sig.connect(v, emit_int(v)); if (i == 50) { sig.connect(write_ungrouped2()); } } sig.connect(write_ungrouped3()); std::sort(sortedValues.begin(), sortedValues.end()); // 17 at beginning, 42 at end sortedValues.insert(sortedValues.begin(), 17); sig.connect(emit_int(17), boost::BOOST_SIGNALS_NAMESPACE::at_front); sortedValues.push_back(42); sig.connect(emit_int(42)); sig(); std::cout << std::endl; BOOST_CHECK(valuesOutput == sortedValues); BOOST_CHECK(ungrouped1); BOOST_CHECK(ungrouped2); BOOST_CHECK(ungrouped3); return 0; } --- NEW FILE: deletion_test.cpp --- // Boost.Signals library // Copyright Douglas Gregor 2001-2003. Use, modification and // distribution is subject to the Boost Software License, Version // 1.0. (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // For more information, see http://www.boost.org #include <boost/test/minimal.hpp> #include <boost/signal.hpp> #include <iostream> #include <string> static boost::BOOST_SIGNALS_NAMESPACE::connection connections[5]; static std::string test_output; struct remove_connection { explicit remove_connection(int v = 0, int i = -1) : value(v), idx(i) {} void operator()() const { if (idx >= 0) connections[idx].disconnect(); //return value; std::cout << value << " "; test_output += static_cast<char>(value + '0'); } int value; int idx; }; bool operator==(const remove_connection& x, const remove_connection& y) { return x.value == y.value && x.idx == y.idx; } static void test_remove_self() { boost::signal0<void> s0; connections[0] = s0.connect(remove_connection(0)); connections[1] = s0.connect(remove_connection(1)); connections[2] = s0.connect(remove_connection(2, 2)); connections[3] = s0.connect(remove_connection(3)); std::cout << "Deleting 2" << std::endl; test_output = ""; s0(); std::cout << std::endl; BOOST_CHECK(test_output == "0123"); test_output = ""; s0(); std::cout << std::endl; BOOST_CHECK(test_output == "013"); s0.disconnect_all_slots(); BOOST_CHECK(s0.empty()); connections[0] = s0.connect(remove_connection(0)); connections[1] = s0.connect(remove_connection(1)); connections[2] = s0.connect(remove_connection(2)); connections[3] = s0.connect(remove_connection(3, 3)); std::cout << "Deleting 3" << std::endl; test_output = ""; s0(); std::cout << std::endl; BOOST_CHECK(test_output == "0123"); test_output = ""; s0(); std::cout << std::endl; BOOST_CHECK(test_output == "012"); s0.disconnect_all_slots(); BOOST_CHECK(s0.num_slots() == 0); connections[0] = s0.connect(remove_connection(0, 0)); connections[1] = s0.connect(remove_connection(1)); connections[2] = s0.connect(remove_connection(2)); connections[3] = s0.connect(remove_connection(3)); std::cout << "Deleting 0" << std::endl; test_output = ""; s0(); std::cout << std::endl; BOOST_CHECK(test_output == "0123"); test_output = ""; s0(); std::cout << std::endl; BOOST_CHECK(test_output == "123"); std::cout << "Blocking 2" << std::endl; connections[2].block(); test_output = ""; s0(); std::cout << std::endl; BOOST_CHECK(test_output == "13"); std::cout << "Unblocking 2" << std::endl; connections[2].unblock(); test_output = ""; s0(); std::cout << std::endl; BOOST_CHECK(test_output == "123"); s0.disconnect_all_slots(); BOOST_CHECK(s0.empty()); connections[0] = s0.connect(remove_connection(0, 0)); connections[1] = s0.connect(remove_connection(1, 1)); connections[2] = s0.connect(remove_connection(2, 2)); connections[3] = s0.connect(remove_connection(3, 3)); std::cout << "Mass suicide" << std::endl; test_output = ""; s0(); std::cout << std::endl; BOOST_CHECK(test_output == "0123"); test_output = ""; s0(); std::cout << std::endl; BOOST_CHECK(test_output == ""); } static void test_remove_prior() { boost::signal0<void> s0; connections[0] = s0.connect(remove_connection(0)); connections[1] = s0.connect(remove_connection(1, 0)); connections[2] = s0.connect(remove_connection(2)); connections[3] = s0.connect(remove_connection(3)); std::cout << "1 removes 0" << std::endl; test_output = ""; s0(); std::cout << std::endl; BOOST_CHECK(test_output == "0123"); test_output = ""; s0(); std::cout << std::endl; BOOST_CHECK(test_output == "123"); s0.disconnect_all_slots(); BOOST_CHECK(s0.empty()); connections[0] = s0.connect(remove_connection(0)); connections[1] = s0.connect(remove_connection(1)); connections[2] = s0.connect(remove_connection(2)); connections[3] = s0.connect(remove_connection(3, 2)); std::cout << "3 removes 2" << std::endl; test_output = ""; s0(); std::cout << std::endl; BOOST_CHECK(test_output == "0123"); test_output = ""; s0(); std::cout << std::endl; BOOST_CHECK(test_output == "013"); } static void test_remove_after() { boost::signal0<void> s0; connections[0] = s0.connect(remove_connection(0, 1)); connections[1] = s0.connect(remove_connection(1)); connections[2] = s0.connect(remove_connection(2)); connections[3] = s0.connect(remove_connection(3)); std::cout << "0 removes 1" << std::endl; test_output = ""; s0(); std::cout << std::endl; BOOST_CHECK(test_output == "023"); test_output = ""; s0(); std::cout << std::endl; BOOST_CHECK(test_output == "023"); s0.disconnect_all_slots(); BOOST_CHECK(s0.empty()); connections[0] = s0.connect(remove_connection(0)); connections[1] = s0.connect(remove_connection(1, 3)); connections[2] = s0.connect(remove_connection(2)); connections[3] = s0.connect(remove_connection(3)); std::cout << "1 removes 3" << std::endl; test_output = ""; s0(); std::cout << std::endl; BOOST_CHECK(test_output == "012"); test_output = ""; s0(); std::cout << std::endl; BOOST_CHECK(test_output == "012"); } static void test_bloodbath() { boost::signal0<void> s0; connections[0] = s0.connect(remove_connection(0, 1)); connections[1] = s0.connect(remove_connection(1, 1)); connections[2] = s0.connect(remove_connection(2, 0)); connections[3] = s0.connect(remove_connection(3, 2)); std::cout << "0 removes 1, 2 removes 0, 3 removes 2" << std::endl; test_output = ""; s0(); std::cout << std::endl; BOOST_CHECK(test_output == "023"); test_output = ""; s0(); std::cout << std::endl; BOOST_CHECK(test_output == "3"); } static void test_disconnect_equal() { boost::signal0<void> s0; connections[0] = s0.connect(remove_connection(0)); connections[1] = s0.connect(remove_connection(1)); connections[2] = s0.connect(remove_connection(2)); connections[3] = s0.connect(remove_connection(3)); std::cout << "Deleting 2" << std::endl; test_output = ""; s0(); std::cout << std::endl; BOOST_CHECK(test_output == "0123"); #if BOOST_WORKAROUND(BOOST_MSVC, <= 1300) connections[2].disconnect(); #else s0.disconnect(remove_connection(2)); #endif test_output = ""; s0(); std::cout << std::endl; BOOST_CHECK(test_output == "013"); } int test_main(int, char* []) { test_remove_self(); test_remove_prior(); test_remove_after(); test_bloodbath(); test_disconnect_equal(); return 0; } --- NEW FILE: dead_slot_test.cpp --- // Boost.Signals library // Copyright (C) Douglas Gregor 2001-2006. Use, modification and // distribution is subject to the Boost Software License, Version // 1.0. (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // For more information, see http://www.boost.org #include <boost/test/minimal.hpp> #include <boost/thread_safe_signal.hpp> #include <boost/bind.hpp> typedef boost::signal1<int, int> sig_type; class with_constant : public boost::BOOST_SIGNALS_NAMESPACE::trackable { public: with_constant(int c) : constant(c) {} int add(int i) { return i + constant; } private: int constant; }; void do_delayed_connect(with_constant* wc, sig_type& sig, sig_type::slot_type slot) { // Should invalidate the slot, so that we cannot connect to it delete wc; boost::BOOST_SIGNALS_NAMESPACE::connection c = sig.connect(slot); BOOST_CHECK(!c.connected()); } int test_main(int, char*[]) { sig_type s1; with_constant* wc1 = new with_constant(7); do_delayed_connect(wc1, s1, boost::bind(&with_constant::add, wc1, _1)); return 0; } |
|
From: Frank M. H. <fm...@us...> - 2007-02-28 17:08:50
|
Update of /cvsroot/boost-sandbox/boost-sandbox/boost/thread_safe_signals/detail In directory sc8-pr-cvs3.sourceforge.net:/tmp/cvs-serv13043/boost/thread_safe_signals/detail Modified Files: signal_template.hpp slot_groups.hpp Log Message: Added missing typename to fix compile under gcc 4.1.2 Index: signal_template.hpp =================================================================== RCS file: /cvsroot/boost-sandbox/boost-sandbox/boost/thread_safe_signals/detail/signal_template.hpp,v retrieving revision 1.36 retrieving revision 1.37 diff -u -d -r1.36 -r1.37 --- signal_template.hpp 28 Feb 2007 15:54:22 -0000 1.36 +++ signal_template.hpp 28 Feb 2007 17:08:48 -0000 1.37 @@ -290,7 +290,7 @@ // clean up disconnected connections void nolock_cleanup_connections(bool grab_tracked, - const connection_list_type::iterator &begin, const connection_list_type::iterator &end) const + const typename connection_list_type::iterator &begin, const typename connection_list_type::iterator &end) const { assert(_shared_state.unique()); typename connection_list_type::iterator it; @@ -323,7 +323,7 @@ // clean up a few connections in constant time void nolock_cleanup_connections(bool grab_tracked) const { - connection_list_type::iterator begin; + typename connection_list_type::iterator begin; if(_garbage_collector_it == _shared_state->connection_bodies.end()) { begin = _shared_state->connection_bodies.begin(); @@ -331,7 +331,7 @@ { begin = _garbage_collector_it; } - connection_list_type::iterator end = begin; + typename connection_list_type::iterator end = begin; ++end; if(end != _shared_state->connection_bodies.end()) ++end; nolock_cleanup_connections(grab_tracked, begin, end); @@ -382,7 +382,7 @@ } shared_ptr<invocation_state> _shared_state; - mutable connection_list_type::iterator _garbage_collector_it; + 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; @@ -398,7 +398,7 @@ { public: typedef signalslib::detail::BOOST_WEAK_SIGNAL_CLASS_NAME<BOOST_SIGNAL_TEMPLATE_INSTANTIATION> weak_signal_type; - friend class weak_signal_type; + friend class signalslib::detail::BOOST_WEAK_SIGNAL_CLASS_NAME<BOOST_SIGNAL_TEMPLATE_INSTANTIATION>; typedef SlotFunction slot_function_type; // typedef slotN<Signature, SlotFunction> slot_type; @@ -409,7 +409,7 @@ typedef typename combiner_type::result_type result_type; typedef Group group_type; typedef GroupCompare group_compare_type; - typedef signalslib::detail::BOOST_SIGNAL_IMPL_CLASS_NAME<BOOST_SIGNAL_TEMPLATE_INSTANTIATION>::slot_call_iterator + typedef typename signalslib::detail::BOOST_SIGNAL_IMPL_CLASS_NAME<BOOST_SIGNAL_TEMPLATE_INSTANTIATION>::slot_call_iterator slot_call_iterator; // typedef Tn argn_type; #define BOOST_SIGNAL_MISC_STATEMENT(z, n, data) \ @@ -499,7 +499,7 @@ public: typedef SlotFunction slot_function_type; typedef typename slot_function_type::result_type slot_result_type; - typedef BOOST_SIGNAL_CLASS_NAME<BOOST_SIGNAL_TEMPLATE_INSTANTIATION>::result_type + typedef typename BOOST_SIGNAL_CLASS_NAME<BOOST_SIGNAL_TEMPLATE_INSTANTIATION>::result_type result_type; BOOST_WEAK_SIGNAL_CLASS_NAME(const BOOST_SIGNAL_CLASS_NAME<BOOST_SIGNAL_TEMPLATE_INSTANTIATION> Index: slot_groups.hpp =================================================================== RCS file: /cvsroot/boost-sandbox/boost-sandbox/boost/thread_safe_signals/detail/slot_groups.hpp,v retrieving revision 1.12 retrieving revision 1.13 diff -u -d -r1.12 -r1.13 --- slot_groups.hpp 16 Feb 2007 02:05:12 -0000 1.12 +++ slot_groups.hpp 28 Feb 2007 17:08:48 -0000 1.13 @@ -141,7 +141,7 @@ if(next != _list.end() && next != upper_bound(key)) { // also erases old entry - _group_map.insert(map_it, map_type::value_type(key, next)); + _group_map.insert(map_it, typename map_type::value_type(key, next)); }else { _group_map.erase(map_it); @@ -173,7 +173,7 @@ if(lower_bound_it == _group_map.end() || weakly_equivalent(lower_bound_it->first, key) == false) { - _group_map.insert(map_type::value_type(key, new_it)); + _group_map.insert(typename map_type::value_type(key, new_it)); } } iterator get_list_iterator(const map_iterator &map_it) |
|
From: Frank M. H. <fm...@us...> - 2007-02-28 17:08:17
|
Update of /cvsroot/boost-sandbox/boost-sandbox/libs/thread_safe_signals/test In directory sc8-pr-cvs3.sourceforge.net:/tmp/cvs-serv12628/libs/thread_safe_signals/test Modified Files: track_test.cpp Log Message: My problems with bind syntactic sugar appear to be a compiler bug after all. The errors go away with gcc 4.1.2 Index: track_test.cpp =================================================================== RCS file: /cvsroot/boost-sandbox/boost-sandbox/libs/thread_safe_signals/test/track_test.cpp,v retrieving revision 1.4 retrieving revision 1.5 diff -u -d -r1.4 -r1.5 --- track_test.cpp 28 Feb 2007 16:19:41 -0000 1.4 +++ track_test.cpp 28 Feb 2007 17:08:12 -0000 1.5 @@ -60,13 +60,9 @@ // Test auto-disconnection of slot before signal connection { boost::shared_ptr<int> shorty(new int(1)); -// doesn't work? gcc says: error: type specifier omitted for parameter `shorty' +// doesn't work on gcc 3.3.5, it says: error: type specifier omitted for parameter `shorty' +// does work on gcc 4.1.2 // sig_type::slot_type slot(swallow(), shorty.get(), _1); -//works -// sig_type::slot_type slot(boost::bind(swallow(), shorty.get(), _1)); -// also works -// sig_type::slot_type slot = sig_type::slot_type(swallow(), shorty.get(), _1); -// also works swallow myswallow; sig_type::slot_type slot(myswallow, shorty.get(), _1); |
|
From: Frank M. H. <fm...@us...> - 2007-02-28 17:07:04
|
Update of /cvsroot/boost-sandbox/boost-sandbox/boost/thread_safe_signals/detail In directory sc8-pr-cvs3.sourceforge.net:/tmp/cvs-serv12171/boost/thread_safe_signals/detail Modified Files: slot_template.hpp Log Message: Added typedefs to slot class for argN_type, and added "arity" constant. Index: slot_template.hpp =================================================================== RCS file: /cvsroot/boost-sandbox/boost-sandbox/boost/thread_safe_signals/detail/slot_template.hpp,v retrieving revision 1.3 retrieving revision 1.4 diff -u -d -r1.3 -r1.4 --- slot_template.hpp 28 Feb 2007 16:19:41 -0000 1.3 +++ slot_template.hpp 28 Feb 2007 17:06:53 -0000 1.4 @@ -30,6 +30,18 @@ friend class BOOST_SLOT_CLASS_NAME(BOOST_SIGNALS_NUM_ARGS); typedef R result_type; +// typedef Tn argn_type; +#define BOOST_SIGNAL_MISC_STATEMENT(z, n, data) \ + typedef BOOST_PP_CAT(T, BOOST_PP_INC(n)) BOOST_PP_CAT(BOOST_PP_CAT(arg, BOOST_PP_INC(n)), _type); + BOOST_PP_REPEAT(BOOST_SIGNALS_NUM_ARGS, BOOST_SIGNAL_MISC_STATEMENT, ~) +#undef BOOST_SIGNAL_MISC_STATEMENT +#if BOOST_SIGNALS_NUM_ARGS == 1 + typedef arg1_type argument_type; +#elif BOOST_SIGNALS_NUM_ARGS == 2 + typedef arg1_type first_argument_type; + typedef arg2_type second_argument_type; +#endif + static const int arity = BOOST_SIGNALS_NUM_ARGS; template<typename F> BOOST_SLOT_CLASS_NAME(BOOST_SIGNALS_NUM_ARGS)(const F& f): _slot_function(signalslib::detail::get_invocable_slot(f, signalslib::detail::tag_type(f))) @@ -48,7 +60,7 @@ { } // bind syntactic sugar -// const ArgTypeN argN +// ArgTypeN argN #define BOOST_SLOT_BINDING_ARG_DECL(z, n, data) \ BOOST_PP_CAT(ArgType, n) BOOST_PP_CAT(arg, n) // template<typename Func, typename ArgType0, typename ArgType1, ..., typename ArgTypen-1> slotN(... |
|
From: Frank M. H. <fm...@us...> - 2007-02-28 16:19:47
|
Update of /cvsroot/boost-sandbox/boost-sandbox/libs/thread_safe_signals/test In directory sc8-pr-cvs3.sourceforge.net:/tmp/cvs-serv25240/libs/thread_safe_signals/test Modified Files: track_test.cpp Log Message: Fixed tracking of signals as slots, and added a test for same. Index: track_test.cpp =================================================================== RCS file: /cvsroot/boost-sandbox/boost-sandbox/libs/thread_safe_signals/test/track_test.cpp,v retrieving revision 1.3 retrieving revision 1.4 diff -u -d -r1.3 -r1.4 --- track_test.cpp 28 Feb 2007 15:54:22 -0000 1.3 +++ track_test.cpp 28 Feb 2007 16:19:41 -0000 1.4 @@ -83,8 +83,16 @@ other_slot.track(shorty); s1.connect(sig_type::slot_type(other_slot, 0.5).track(other_slot)); BOOST_CHECK(s1(3) == 2); - shorty.reset(); - BOOST_CHECK(s1(3) == 0); } + BOOST_CHECK(s1(3) == 0); + + // Test binding of a signal as a slot + { + sig_type s2; + s1.connect(sig_type::slot_type(s2).track(s2)); + s2.connect(sig_type::slot_type(&myfunc, _1, 0.7)); + BOOST_CHECK(s1(4) == 4); + } + BOOST_CHECK(s1(4) == 0); return 0; } |
|
From: Frank M. H. <fm...@us...> - 2007-02-28 16:19:43
|
Update of /cvsroot/boost-sandbox/boost-sandbox/boost/thread_safe_signals/detail In directory sc8-pr-cvs3.sourceforge.net:/tmp/cvs-serv25240/boost/thread_safe_signals/detail Modified Files: slot_template.hpp Log Message: Fixed tracking of signals as slots, and added a test for same. Index: slot_template.hpp =================================================================== RCS file: /cvsroot/boost-sandbox/boost-sandbox/boost/thread_safe_signals/detail/slot_template.hpp,v retrieving revision 1.2 retrieving revision 1.3 diff -u -d -r1.2 -r1.3 --- slot_template.hpp 28 Feb 2007 15:54:22 -0000 1.2 +++ slot_template.hpp 28 Feb 2007 16:19:41 -0000 1.3 @@ -82,7 +82,8 @@ } BOOST_SLOT_CLASS_NAME(BOOST_SIGNALS_NUM_ARGS)& track(const signalslib::detail::signal_base &signal) { - track(signal.lock_pimpl()); + // call base class function, since it is a friend of signal_base and can call lock_pimpl() + track_signal(signal); return *this; } private: |
|
From: Frank M. H. <fm...@us...> - 2007-02-28 16:19:43
|
Update of /cvsroot/boost-sandbox/boost-sandbox/boost/thread_safe_signals In directory sc8-pr-cvs3.sourceforge.net:/tmp/cvs-serv25240/boost/thread_safe_signals Modified Files: slot_base.hpp Log Message: Fixed tracking of signals as slots, and added a test for same. Index: slot_base.hpp =================================================================== RCS file: /cvsroot/boost-sandbox/boost-sandbox/boost/thread_safe_signals/slot_base.hpp,v retrieving revision 1.1 retrieving revision 1.2 diff -u -d -r1.1 -r1.2 --- slot_base.hpp 27 Feb 2007 21:19:25 -0000 1.1 +++ slot_base.hpp 28 Feb 2007 16:19:41 -0000 1.2 @@ -57,6 +57,11 @@ return false; } protected: + void track_signal(const signalslib::detail::signal_base &signal) + { + _trackedObjects.push_back(signal.lock_pimpl()); + } + tracked_container_type _trackedObjects; }; } |
|
From: Frank M. H. <fm...@us...> - 2007-02-28 15:54:29
|
Update of /cvsroot/boost-sandbox/boost-sandbox/libs/thread_safe_signals/test In directory sc8-pr-cvs3.sourceforge.net:/tmp/cvs-serv14350/libs/thread_safe_signals/test Modified Files: track_test.cpp Log Message: Added some templated copy constructors to slot class, to prevent loss of tracking on copy construction. Index: track_test.cpp =================================================================== RCS file: /cvsroot/boost-sandbox/boost-sandbox/libs/thread_safe_signals/test/track_test.cpp,v retrieving revision 1.2 retrieving revision 1.3 diff -u -d -r1.2 -r1.3 --- track_test.cpp 27 Feb 2007 22:24:33 -0000 1.2 +++ track_test.cpp 28 Feb 2007 15:54:22 -0000 1.3 @@ -39,7 +39,7 @@ static int myfunc(int i, double z) { - std::cout << __FUNCTION__ << ": z is " << z << std::endl; + std::cout << __FUNCTION__ << ": i is " << i << " and z is " << z << std::endl; return i; } @@ -59,13 +59,17 @@ // Test auto-disconnection of slot before signal connection { - boost::shared_ptr<int> shorty(new int()); - //works - sig_type::slot_type slot(boost::bind(swallow(), shorty.get(), _1)); - // also works -// sig_type::slot_type slot = sig_type::slot_type(swallow(), shorty.get(), _1); - // doesn't work? gcc says: error: type specifier omitted for parameter `shorty' + boost::shared_ptr<int> shorty(new int(1)); +// doesn't work? gcc says: error: type specifier omitted for parameter `shorty' // sig_type::slot_type slot(swallow(), shorty.get(), _1); +//works +// sig_type::slot_type slot(boost::bind(swallow(), shorty.get(), _1)); +// also works +// sig_type::slot_type slot = sig_type::slot_type(swallow(), shorty.get(), _1); +// also works + swallow myswallow; + sig_type::slot_type slot(myswallow, shorty.get(), _1); + slot.track(shorty); shorty.reset(); s1.connect(slot); |
|
From: Frank M. H. <fm...@us...> - 2007-02-28 15:54:27
|
Update of /cvsroot/boost-sandbox/boost-sandbox/boost/thread_safe_signals/detail In directory sc8-pr-cvs3.sourceforge.net:/tmp/cvs-serv14350/boost/thread_safe_signals/detail Modified Files: signal_template.hpp signals_common_macros.hpp slot_template.hpp Log Message: Added some templated copy constructors to slot class, to prevent loss of tracking on copy construction. Index: signals_common_macros.hpp =================================================================== RCS file: /cvsroot/boost-sandbox/boost-sandbox/boost/thread_safe_signals/detail/signals_common_macros.hpp,v retrieving revision 1.1 retrieving revision 1.2 diff -u -d -r1.1 -r1.2 --- signals_common_macros.hpp 27 Feb 2007 21:19:25 -0000 1.1 +++ signals_common_macros.hpp 28 Feb 2007 15:54:22 -0000 1.2 @@ -33,12 +33,18 @@ BOOST_PP_ENUM(arity, BOOST_SIGNAL_SIGNATURE_FULL_ARG, ~) // arg1, arg2, ..., argn #define BOOST_SIGNAL_SIGNATURE_ARG_NAMES(arity) BOOST_PP_ENUM(arity, BOOST_SIGNAL_SIGNATURE_ARG_NAME, ~) +// typename prefixR, typename prefixT1, typename prefixT2, ..., typename prefixTN +#define BOOST_SIGNAL_PREFIXED_SIGNATURE_TEMPLATE_DECL(arity, prefix) \ + typename BOOST_PP_CAT(prefix, R) BOOST_PP_COMMA_IF(arity) \ + BOOST_PP_ENUM_SHIFTED_PARAMS(BOOST_PP_INC(arity), typename BOOST_PP_CAT(prefix, T)) // typename R, typename T1, typename T2, ..., typename TN -#define BOOST_SIGNAL_SIGNATURE_TEMPLATE_DECL(arity) \ - typename R BOOST_PP_COMMA_IF(arity) BOOST_PP_ENUM_SHIFTED_PARAMS(BOOST_PP_INC(arity), typename T) +#define BOOST_SIGNAL_SIGNATURE_TEMPLATE_DECL(arity) BOOST_SIGNAL_PREFIXED_SIGNATURE_TEMPLATE_DECL(arity,) +// prefixR, prefixT1, prefixT2, ..., prefixTN +#define BOOST_SIGNAL_PREFIXED_SIGNATURE_TEMPLATE_INSTANTIATION(arity, prefix) \ + BOOST_PP_CAT(prefix, R) BOOST_PP_COMMA_IF(arity) BOOST_PP_ENUM_SHIFTED_PARAMS(BOOST_PP_INC(arity), BOOST_PP_CAT(prefix, T)) // R, T1, T2, ..., TN #define BOOST_SIGNAL_SIGNATURE_TEMPLATE_INSTANTIATION(arity) \ - R BOOST_PP_COMMA_IF(arity) BOOST_PP_ENUM_SHIFTED_PARAMS(BOOST_PP_INC(arity), T) + BOOST_SIGNAL_PREFIXED_SIGNATURE_TEMPLATE_INSTANTIATION(arity,) // functionN<R, T1, T2, ..., TN> #define BOOST_FUNCTION_N_DECL(arity) BOOST_PP_CAT(function, arity)<\ BOOST_SIGNAL_SIGNATURE_TEMPLATE_INSTANTIATION(arity) > Index: signal_template.hpp =================================================================== RCS file: /cvsroot/boost-sandbox/boost-sandbox/boost/thread_safe_signals/detail/signal_template.hpp,v retrieving revision 1.35 retrieving revision 1.36 diff -u -d -r1.35 -r1.36 --- signal_template.hpp 27 Feb 2007 21:19:25 -0000 1.35 +++ signal_template.hpp 28 Feb 2007 15:54:22 -0000 1.36 @@ -59,16 +59,16 @@ class BOOST_SIGNAL_IMPL_CLASS_NAME { public: + typedef SlotFunction slot_function_type; + // typedef slotN<Signature, SlotFunction> slot_type; typedef BOOST_SLOT_CLASS_NAME(BOOST_SIGNALS_NUM_ARGS)<BOOST_SIGNAL_SIGNATURE_TEMPLATE_INSTANTIATION(BOOST_SIGNALS_NUM_ARGS), - SlotFunction> slot_type; + slot_function_type> slot_type; private: class slot_invoker; typedef typename signalslib::detail::group_key<Group>::type group_key_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 SlotFunction slot_function_type; - // typedef slotN<Signature, SlotFunction> slot_type; typedef typename slot_function_type::result_type slot_result_type; typedef Combiner combiner_type; typedef typename combiner_type::result_type result_type; Index: slot_template.hpp =================================================================== RCS file: /cvsroot/boost-sandbox/boost-sandbox/boost/thread_safe_signals/detail/slot_template.hpp,v retrieving revision 1.1 retrieving revision 1.2 diff -u -d -r1.1 -r1.2 --- slot_template.hpp 27 Feb 2007 21:19:25 -0000 1.1 +++ slot_template.hpp 28 Feb 2007 15:54:22 -0000 1.2 @@ -18,18 +18,35 @@ namespace boost { + template<typename Signature, typename SlotFunction> class slot; + // slot class template. template<BOOST_SIGNAL_SIGNATURE_TEMPLATE_DECL(BOOST_SIGNALS_NUM_ARGS), typename SlotFunction = BOOST_FUNCTION_N_DECL(BOOST_SIGNALS_NUM_ARGS)> class BOOST_SLOT_CLASS_NAME(BOOST_SIGNALS_NUM_ARGS): public signalslib::detail::slot_base { public: + template<BOOST_SIGNAL_PREFIXED_SIGNATURE_TEMPLATE_DECL(BOOST_SIGNALS_NUM_ARGS, Other), typename OtherSlotFunction> + friend class BOOST_SLOT_CLASS_NAME(BOOST_SIGNALS_NUM_ARGS); + typedef R result_type; template<typename F> BOOST_SLOT_CLASS_NAME(BOOST_SIGNALS_NUM_ARGS)(const F& f): _slot_function(signalslib::detail::get_invocable_slot(f, signalslib::detail::tag_type(f))) { } + // copy constructors + template<BOOST_SIGNAL_PREFIXED_SIGNATURE_TEMPLATE_DECL(BOOST_SIGNALS_NUM_ARGS, Other), typename OtherSlotFunction> + BOOST_SLOT_CLASS_NAME(BOOST_SIGNALS_NUM_ARGS)(const BOOST_SLOT_CLASS_NAME(BOOST_SIGNALS_NUM_ARGS) + <BOOST_SIGNAL_PREFIXED_SIGNATURE_TEMPLATE_INSTANTIATION(BOOST_SIGNALS_NUM_ARGS, Other), OtherSlotFunction> &other_slot): + signalslib::detail::slot_base(other_slot), _slot_function(other_slot._slot_function) + { + } + template<typename Signature, typename OtherSlotFunction> + BOOST_SLOT_CLASS_NAME(BOOST_SIGNALS_NUM_ARGS)(const slot<Signature, OtherSlotFunction> &other_slot): + signalslib::detail::slot_base(other_slot), _slot_function(other_slot._slot_function) + { + } // bind syntactic sugar // const ArgTypeN argN #define BOOST_SLOT_BINDING_ARG_DECL(z, n, data) \ |