1 // Boost.Signals library 2 3 // Copyright Douglas Gregor 2001-2004. Use, modification and 4 // distribution is subject to the Boost Software License, Version 5 // 1.0. (See accompanying file LICENSE_1_0.txt or copy at 6 // http://www.boost.org/LICENSE_1_0.txt) 7 8 // For more information, see http://www.boost.org 9 10 #ifndef BOOST_SIGNALS_TRACKABLE_HPP 11 #define BOOST_SIGNALS_TRACKABLE_HPP 12 13 #include <boost/type_traits.hpp> 14 #include <boost/signals/connection.hpp> 15 #include <boost/ref.hpp> 16 #include <boost/utility/addressof.hpp> 17 #include <list> 18 #include <vector> 19 20 #ifdef BOOST_HAS_ABI_HEADERS 21 # include BOOST_ABI_PREFIX 22 #endif 23 24 namespace boost { 25 26 namespace BOOST_SIGNALS_NAMESPACE { 27 // Base class for "trackable" objects that can be tracked when they are 28 // bound in slot target functions. When a trackable object is destroyed, 29 // the signal/slot connections are disconnected automatically. 30 class BOOST_SIGNALS_DECL trackable { 31 private: 32 static void signal_disconnected(void* obj, void* data); 33 34 friend class detail::signal_base_impl; 35 friend class detail::slot_base; 36 void signal_connected(connection, BOOST_SIGNALS_NAMESPACE::detail::bound_object&) const; 37 38 protected: trackable()39 trackable() : connected_signals(), dying(false) {} trackable(const trackable &)40 trackable(const trackable&) : connected_signals(), dying(false) {} 41 ~trackable(); 42 operator =(const trackable &)43 trackable& operator=(const trackable&) 44 { 45 dying = true; 46 connected_signals.clear(); 47 dying = false; 48 return *this; 49 } 50 51 private: 52 typedef std::list<connection> connection_list; 53 typedef connection_list::iterator connection_iterator; 54 55 // List of connections that this object is part of 56 mutable connection_list connected_signals; 57 58 // True when the object is being destroyed 59 mutable bool dying; 60 }; 61 62 namespace detail { 63 template<bool Cond> struct truth {}; 64 65 // A visitor that adds each trackable object to a vector 66 class bound_objects_visitor { 67 public: bound_objects_visitor(std::vector<const trackable * > & v)68 bound_objects_visitor(std::vector<const trackable*>& v) : 69 bound_objects(v) 70 { 71 } 72 73 template<typename T> operator ()(const T & t) const74 void operator()(const T& t) const 75 { 76 decode(t, 0); 77 } 78 79 private: 80 // decode() decides between a reference wrapper and anything else 81 template<typename T> decode(const reference_wrapper<T> & t,int) const82 void decode(const reference_wrapper<T>& t, int) const 83 { 84 add_if_trackable(t.get_pointer()); 85 } 86 87 template<typename T> decode(const T & t,long) const88 void decode(const T& t, long) const 89 { 90 typedef truth<(is_pointer<T>::value)> is_a_pointer; 91 maybe_get_pointer(t, is_a_pointer()); 92 } 93 94 // maybe_get_pointer() decides between a pointer and a non-pointer 95 template<typename T> maybe_get_pointer(const T & t,truth<true>) const96 void maybe_get_pointer(const T& t, truth<true>) const 97 { 98 add_if_trackable(t); 99 } 100 101 template<typename T> maybe_get_pointer(const T & t,truth<false>) const102 void maybe_get_pointer(const T& t, truth<false>) const 103 { 104 // Take the address of this object, because the object itself may be 105 // trackable 106 add_if_trackable(boost::addressof(t)); 107 } 108 109 // add_if_trackable() adds trackable objects to the list of bound objects add_if_trackable(const trackable * b) const110 inline void add_if_trackable(const trackable* b) const 111 { 112 if (b) { 113 bound_objects.push_back(b); 114 } 115 } 116 add_if_trackable(const void *) const117 inline void add_if_trackable(const void*) const { } 118 119 template<typename R> add_if_trackable(R (*)()) const120 inline void add_if_trackable(R (*)()) const { } 121 122 template<typename R, typename T1> add_if_trackable(R (*)(T1)) const123 inline void add_if_trackable(R (*)(T1)) const { } 124 125 template<typename R, typename T1, typename T2> add_if_trackable(R (*)(T1,T2)) const126 inline void add_if_trackable(R (*)(T1, T2)) const { } 127 128 template<typename R, typename T1, typename T2, typename T3> add_if_trackable(R (*)(T1,T2,T3)) const129 inline void add_if_trackable(R (*)(T1, T2, T3)) const { } 130 131 template<typename R, typename T1, typename T2, typename T3, typename T4> add_if_trackable(R (*)(T1,T2,T3,T4)) const132 inline void add_if_trackable(R (*)(T1, T2, T3, T4)) const { } 133 134 template<typename R, typename T1, typename T2, typename T3, typename T4, 135 typename T5> add_if_trackable(R (*)(T1,T2,T3,T4,T5)) const136 inline void add_if_trackable(R (*)(T1, T2, T3, T4, T5)) const { } 137 138 template<typename R, typename T1, typename T2, typename T3, typename T4, 139 typename T5, typename T6> add_if_trackable(R (*)(T1,T2,T3,T4,T5,T6)) const140 inline void add_if_trackable(R (*)(T1, T2, T3, T4, T5, T6)) const { } 141 142 template<typename R, typename T1, typename T2, typename T3, typename T4, 143 typename T5, typename T6, typename T7> add_if_trackable(R (*)(T1,T2,T3,T4,T5,T6,T7)) const144 inline void add_if_trackable(R (*)(T1, T2, T3, T4, T5, T6, T7)) const { } 145 146 template<typename R, typename T1, typename T2, typename T3, typename T4, 147 typename T5, typename T6, typename T7, typename T8> 148 inline void add_if_trackable(R (*)(T1,T2,T3,T4,T5,T6,T7,T8)) const149 add_if_trackable(R (*)(T1, T2, T3, T4, T5, T6, T7, T8)) const { } 150 151 template<typename R, typename T1, typename T2, typename T3, typename T4, 152 typename T5, typename T6, typename T7, typename T8, typename T9> 153 inline void add_if_trackable(R (*)(T1,T2,T3,T4,T5,T6,T7,T8,T9)) const154 add_if_trackable(R (*)(T1, T2, T3, T4, T5, T6, T7, T8, T9)) const { } 155 156 template<typename R, typename T1, typename T2, typename T3, typename T4, 157 typename T5, typename T6, typename T7, typename T8, typename T9, 158 typename T10> 159 inline void add_if_trackable(R (*)(T1,T2,T3,T4,T5,T6,T7,T8,T9,T10)) const160 add_if_trackable(R (*)(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10)) const { } 161 162 std::vector<const trackable*>& bound_objects; 163 }; 164 } // end namespace detail 165 } // end namespace BOOST_SIGNALS_NAMESPACE 166 167 } // end namespace boost 168 169 #ifdef BOOST_HAS_ABI_HEADERS 170 # include BOOST_ABI_SUFFIX 171 #endif 172 173 #endif // BOOST_SIGNALS_TRACKABLE_HPP 174