1 // Boost.Signals2 library 2 3 // Copyright Frank Mori Hess 2007-2008. 4 // Copyright Timmo Stange 2007. 5 // Copyright Douglas Gregor 2001-2004. Use, modification and 6 // distribution is subject to the Boost Software License, Version 7 // 1.0. (See accompanying file LICENSE_1_0.txt or copy at 8 // http://www.boost.org/LICENSE_1_0.txt) 9 10 // For more information, see http://www.boost.org 11 12 #ifndef BOOST_SIGNALS2_SLOT_BASE_HPP 13 #define BOOST_SIGNALS2_SLOT_BASE_HPP 14 15 #include <boost/shared_ptr.hpp> 16 #include <boost/weak_ptr.hpp> 17 #include <boost/signals2/detail/foreign_ptr.hpp> 18 #include <boost/signals2/expired_slot.hpp> 19 #include <boost/signals2/signal_base.hpp> 20 #include <boost/throw_exception.hpp> 21 #include <boost/variant/apply_visitor.hpp> 22 #include <boost/variant/variant.hpp> 23 #include <vector> 24 25 namespace boost 26 { 27 namespace signals2 28 { 29 namespace detail 30 { 31 class tracked_objects_visitor; 32 class trackable_pointee; 33 34 typedef boost::variant<boost::weak_ptr<trackable_pointee>, boost::weak_ptr<void>, detail::foreign_void_weak_ptr > void_weak_ptr_variant; 35 typedef boost::variant<boost::shared_ptr<void>, detail::foreign_void_shared_ptr > void_shared_ptr_variant; 36 class lock_weak_ptr_visitor 37 { 38 public: 39 typedef void_shared_ptr_variant result_type; 40 template<typename WeakPtr> operator ()(const WeakPtr & wp) const41 result_type operator()(const WeakPtr &wp) const 42 { 43 return wp.lock(); 44 } 45 // overload to prevent incrementing use count of shared_ptr associated 46 // with signals2::trackable objects operator ()(const weak_ptr<trackable_pointee> &) const47 result_type operator()(const weak_ptr<trackable_pointee> &) const 48 { 49 return boost::shared_ptr<void>(); 50 } 51 }; 52 class expired_weak_ptr_visitor 53 { 54 public: 55 typedef bool result_type; 56 template<typename WeakPtr> operator ()(const WeakPtr & wp) const57 bool operator()(const WeakPtr &wp) const 58 { 59 return wp.expired(); 60 } 61 }; 62 } 63 64 class slot_base 65 { 66 public: 67 typedef std::vector<detail::void_weak_ptr_variant> tracked_container_type; 68 typedef std::vector<detail::void_shared_ptr_variant> locked_container_type; 69 tracked_objects() const70 const tracked_container_type& tracked_objects() const {return _tracked_objects;} lock() const71 locked_container_type lock() const 72 { 73 locked_container_type locked_objects; 74 tracked_container_type::const_iterator it; 75 for(it = tracked_objects().begin(); it != tracked_objects().end(); ++it) 76 { 77 locked_objects.push_back(apply_visitor(detail::lock_weak_ptr_visitor(), *it)); 78 if(apply_visitor(detail::expired_weak_ptr_visitor(), *it)) 79 { 80 boost::throw_exception(expired_slot()); 81 } 82 } 83 return locked_objects; 84 } expired() const85 bool expired() const 86 { 87 tracked_container_type::const_iterator it; 88 for(it = tracked_objects().begin(); it != tracked_objects().end(); ++it) 89 { 90 if(apply_visitor(detail::expired_weak_ptr_visitor(), *it)) return true; 91 } 92 return false; 93 } 94 protected: 95 friend class detail::tracked_objects_visitor; 96 track_signal(const signal_base & signal)97 void track_signal(const signal_base &signal) 98 { 99 _tracked_objects.push_back(signal.lock_pimpl()); 100 } 101 102 tracked_container_type _tracked_objects; 103 }; 104 } 105 } // end namespace boost 106 107 #endif // BOOST_SIGNALS2_SLOT_BASE_HPP 108