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