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