|
From: Frank M. H. <fm...@us...> - 2007-02-27 21:19:26
|
Update of /cvsroot/boost-sandbox/boost-sandbox/boost/thread_safe_signals In directory sc8-pr-cvs3.sourceforge.net:/tmp/cvs-serv22644/boost/thread_safe_signals Modified Files: connection.hpp slot.hpp track.hpp Added Files: slot_base.hpp Log Message: Added Signature template parameter to slot class, so that an operator() could be added. Bind can be used to bind together slots with different signatures now. Added some syntactic sugar to slot constructors, so a bind() call is inserted automatically for the constructors that take more than one argument. All tracking for automatic connection management is now done through slot::track(). Added track_test.cpp test program, which tests some of the new functionality. Index: track.hpp =================================================================== RCS file: /cvsroot/boost-sandbox/boost-sandbox/boost/thread_safe_signals/track.hpp,v retrieving revision 1.12 retrieving revision 1.13 diff -u -d -r1.12 -r1.13 --- track.hpp 22 Feb 2007 20:47:20 -0000 1.12 +++ track.hpp 27 Feb 2007 21:19:25 -0000 1.13 @@ -26,17 +26,18 @@ class tracked { public: - typedef typename unwrap_reference<T>::type value_type; + typedef T value_type; + typedef typename unwrap_reference<T>::type unwrapped_value_type; tracked(const shared_ptr<void>& tracked_ptr, const T &value): _value(value), _tracked_ptr(tracked_ptr) {} // implicit conversions so tracked objects can be bound with bind - operator value_type & () + operator unwrapped_value_type & () { return _value; } - operator const value_type & () const + operator const unwrapped_value_type & () const { return _value; } @@ -83,7 +84,7 @@ T* get_pointer(const signalslib::tracked<weak_ptr<T> > &tracked) {return shared_ptr<T>(static_cast<weak_ptr<T> >(tracked)).get();} // handles T=shared_ptr or similar case template<typename T> - typename T::pointer get_pointer(const signalslib::tracked<T> &tracked) {return static_cast<const T&>(tracked).get();} + typename T::element_type* get_pointer(const signalslib::tracked<T> &tracked) {return get_pointer(static_cast<const T&>(tracked));} } // end namespace BOOST_SIGNALS_NAMESPACE } // end namespace boost --- NEW FILE: slot_base.hpp --- // Boost.Signals library // Copyright Frank Mori Hess 2007. // Copyright Timmo Stange 2007. // Copyright Douglas Gregor 2001-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 #ifndef BOOST_TSS_SIGNALS_SLOT_BASE_HEADER #define BOOST_TSS_SIGNALS_SLOT_BASE_HEADER #include <boost/shared_ptr.hpp> #include <boost/weak_ptr.hpp> #include <boost/thread_safe_signals/detail/signal_base.hpp> #include <vector> #ifdef BOOST_HAS_ABI_HEADERS # include BOOST_ABI_PREFIX #endif namespace boost { namespace signalslib { namespace detail { class slot_base { public: typedef std::vector<boost::weak_ptr<void> > tracked_container_type; typedef std::vector<boost::shared_ptr<void> > locked_container_type; const tracked_container_type& tracked_objects() const {return _trackedObjects;} locked_container_type lock() const { locked_container_type locked_objects; tracked_container_type::const_iterator it; for(it = tracked_objects().begin(); it != tracked_objects().end(); ++it) { locked_objects.push_back(shared_ptr<void>(*it)); } return locked_objects; } bool expired() const { try { lock(); } catch(const bad_weak_ptr &err) { return true; } return false; } protected: tracked_container_type _trackedObjects; }; } } } // end namespace boost #ifdef BOOST_HAS_ABI_HEADERS # include BOOST_ABI_SUFFIX #endif #endif // BOOST_SIGNALS_SLOT_BASE_HEADER Index: connection.hpp =================================================================== RCS file: /cvsroot/boost-sandbox/boost-sandbox/boost/thread_safe_signals/connection.hpp,v retrieving revision 1.18 retrieving revision 1.19 diff -u -d -r1.18 -r1.19 --- connection.hpp 21 Feb 2007 20:28:14 -0000 1.18 +++ connection.hpp 27 Feb 2007 21:19:25 -0000 1.19 @@ -41,11 +41,8 @@ class ConnectionBodyBase { public: - typedef std::vector<boost::shared_ptr<void> > shared_ptrs_type; - typedef std::vector<boost::weak_ptr<void> > tracked_objects_container; - - ConnectionBodyBase(const tracked_objects_container &tracked_objects): - _tracked_objects(tracked_objects), _connected(true), _blocked(false) + ConnectionBodyBase(): + _connected(true), _blocked(false) { } virtual ~ConnectionBodyBase() {} @@ -65,35 +62,18 @@ return _blocked || (nolock_nograb_connected() == false); } bool nolock_nograb_connected() const {return _connected;} - // mutex should be locked when calling grabTrackedObjects - shared_ptrs_type nolock_grab_tracked_objects() const - { - shared_ptrs_type sharedPtrs; - tracked_objects_container::const_iterator it; - for(it = _tracked_objects.begin(); it != _tracked_objects.end(); ++it) - { - sharedPtrs.push_back(it->lock()); - if(sharedPtrs.back() == 0) - { - _connected = false; - return shared_ptrs_type(); - } - } - return sharedPtrs; - } protected: - tracked_objects_container _tracked_objects; mutable bool _connected; bool _blocked; }; - template<typename GroupKey, typename SlotFunction, typename ThreadingModel> + template<typename GroupKey, typename SlotType, typename ThreadingModel> class ConnectionBody: public ConnectionBodyBase { public: typedef typename ThreadingModel::try_mutex_type mutex_type; - ConnectionBody(const slot<SlotFunction> &slot_in): - ConnectionBodyBase(slot_in.get_all_tracked()), slot(slot_in.get_slot_function()) + ConnectionBody(const SlotType &slot_in): + slot(slot_in) { } virtual ~ConnectionBody() {} @@ -121,8 +101,30 @@ } const GroupKey& group_key() const {return _group_key;} void set_group_key(const GroupKey &key) {_group_key = key;} - - const SlotFunction slot; + bool nolock_slot_expired() const + { + bool expired = slot.expired(); + if(expired == true) + { + _connected = false; + } + return expired; + } + typename slot_base::locked_container_type nolock_grab_tracked_objects() const + { + slot_base::locked_container_type locked_objects; + try + { + locked_objects = slot.lock(); + } + catch(const bad_weak_ptr &err) + { + _connected = false; + return locked_objects; + } + return locked_objects; + } + SlotType slot; mutable mutex_type mutex; private: GroupKey _group_key; Index: slot.hpp =================================================================== RCS file: /cvsroot/boost-sandbox/boost-sandbox/boost/thread_safe_signals/slot.hpp,v retrieving revision 1.13 retrieving revision 1.14 diff -u -d -r1.13 -r1.14 --- slot.hpp 22 Feb 2007 16:57:12 -0000 1.13 +++ slot.hpp 27 Feb 2007 21:19:25 -0000 1.14 @@ -12,9 +12,12 @@ #ifndef BOOST_TSS_SIGNALS_SLOT_HEADER #define BOOST_TSS_SIGNALS_SLOT_HEADER +#include <boost/bind.hpp> #include <boost/mpl/bool.hpp> #include <boost/ref.hpp> #include <boost/thread_safe_signals/detail/signals_common.hpp> +#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> @@ -32,84 +35,6 @@ { namespace detail { - class slot_base; - template<typename GroupKey, typename SlotFunction, typename ThreadingModel> - class ConnectionBody; - - // Visitor to collect tracked objects from a bound function. - class tracked_objects_visitor - { - public: - tracked_objects_visitor(slot_base *slot) : slot_(slot) - {} - template<typename T> - void operator()(const T& t) const - { - m_visit_reference_wrapper(t, mpl::bool_<is_reference_wrapper<T>::value>()); - } - private: - template<typename T> - void m_visit_reference_wrapper(const reference_wrapper<T> &t, const mpl::bool_<true> &) const - { - m_visit_pointer(t.get_pointer(), mpl::bool_<true>()); - } - template<typename T> - void m_visit_reference_wrapper(const T &t, const mpl::bool_<false> &) const - { - m_visit_pointer(t, mpl::bool_<is_pointer<T>::value>()); - } - template<typename T> - void m_visit_pointer(const T &t, const mpl::bool_<true> &) const - { - m_visit_not_function_pointer(t, mpl::bool_<is_convertible<T, const void*>::value>()); - } - template<typename T> - void m_visit_pointer(const T &t, const mpl::bool_<false> &) const - { - m_visit_pointer(addressof(t), mpl::bool_<true>()); - } - template<typename T> - void m_visit_not_function_pointer(const T *t, const mpl::bool_<true> &) const - { - m_visit_signal(t, mpl::bool_<is_signal<T>::value>()); - } - template<typename T> - void m_visit_not_function_pointer(const T &t, const mpl::bool_<false> &) const - {} - template<typename T> - void m_visit_signal(const T *t, const mpl::bool_<true> &) const; - template<typename T> - void m_visit_signal(const T &t, const mpl::bool_<false> &) const - { - add_if_trackable(t); - } - template<typename T> - void add_if_trackable(const tracked<T> *t) const; - void add_if_trackable(const trackable *trackable) const; - void add_if_trackable(const void *trackable) const {} - - mutable slot_base * slot_; - }; - - class slot_base - { - public: - friend class signalslib::detail::tracked_objects_visitor; - template<typename GroupKey, typename SlotFunction> - friend class ConnectionBody; - - private: - typedef std::vector<boost::weak_ptr<void> > tracked_objects_container; - - void add_tracked(const weak_ptr<void> &tracked) - { - _trackedObjects.push_back(tracked); - } - const tracked_objects_container& get_all_tracked() const {return _trackedObjects;} - - tracked_objects_container _trackedObjects; - }; - // Get the slot so that it can be copied template<typename F> typename F::weak_signal_type @@ -139,50 +64,43 @@ } } } - // slot class template. - template<typename SlotFunction> - class slot: public signalslib::detail::slot_base +} // end namespace boost + +#define BOOST_PP_ITERATION_LIMITS (0, BOOST_SIGNALS_MAX_ARGS) +#define BOOST_PP_FILENAME_1 <boost/thread_safe_signals/detail/slot_template.hpp> +#include BOOST_PP_ITERATE() + +namespace boost +{ + template<typename Signature, + typename SlotFunction = boost::function<Signature> > + class slot: public signalslib::detail::slotN<function_traits<Signature>::arity, + Signature, SlotFunction>::type { + private: + typedef typename signalslib::detail::slotN<boost::function_traits<Signature>::arity, + Signature, SlotFunction>::type base_type; public: template<typename F> - slot(const F& f): slot_function(signalslib::detail::get_invocable_slot(f, signalslib::detail::tag_type(f))) - { - signalslib::detail::tracked_objects_visitor visitor(this); - boost::visit_each(visitor, f); - } - // We would have to enumerate all of the signalN classes here as friends - // to make this private (as it otherwise should be). We can't name all of - // them because we don't know how many there are. - public: - // Get the slot function to call the actual slot - const SlotFunction& get_slot_function() const { return slot_function; } - private: - - slot(); // no default constructor - slot& operator=(const slot&); // no assignment operator - - SlotFunction slot_function; + slot(const F& f): base_type(f) + {} + // bind syntactic sugar +// AN aN +#define BOOST_SLOT_BINDING_ARG_DECL(z, n, data) \ + BOOST_PP_CAT(A, n) BOOST_PP_CAT(a, n) +// template<typename F, typename A0, typename A1, ..., typename An-1> slotN(... +#define BOOST_SLOT_BINDING_CONSTRUCTOR(z, n, data) \ + template<typename F, BOOST_PP_ENUM_PARAMS(n, typename A)> \ + slot(F f, BOOST_PP_ENUM(n, BOOST_SLOT_BINDING_ARG_DECL, ~)): \ + base_type(f, BOOST_PP_ENUM_PARAMS(n, a)) \ + {} +#define BOOST_SLOT_MAX_BINDING_ARGS 10 + BOOST_PP_REPEAT_FROM_TO(1, BOOST_SLOT_MAX_BINDING_ARGS, BOOST_SLOT_BINDING_CONSTRUCTOR, ~) +#undef BOOST_SLOT_MAX_BINDING_ARGS +#undef BOOST_SLOT_BINDING_ARG_DECL +#undef BOOST_SLOT_BINDING_CONSTRUCTOR }; -} // end namespace boost - -template<typename T> -void boost::signalslib::detail::tracked_objects_visitor::m_visit_signal( - const T *signal, const mpl::bool_<true> &) const -{ - if(signal) - slot_->add_tracked(signal->lock_pimpl()); -}; -template<typename T> -void boost::signalslib::detail::tracked_objects_visitor::add_if_trackable(const tracked<T> *t) const -{ - if(t) - slot_->add_tracked(t->get_tracked_ptr()); } -void boost::signalslib::detail::tracked_objects_visitor::add_if_trackable(const trackable *trackable) const -{ - if(trackable) - slot_->add_tracked(trackable->get_shared_ptr()); -}; #ifdef BOOST_HAS_ABI_HEADERS # include BOOST_ABI_SUFFIX |