]> git.lyx.org Git - lyx.git/blob - boost/boost/signals/connection.hpp
Boost 1.31.0
[lyx.git] / boost / boost / signals / connection.hpp
1 // Boost.Signals library
2
3 // Copyright Doug Gregor 2001-2003. 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_CONNECTION_HPP
11 #define BOOST_SIGNALS_CONNECTION_HPP
12
13 #include <boost/signals/detail/signals_common.hpp>
14 #include <boost/smart_ptr.hpp>
15 #include <boost/operators.hpp>
16 #include <boost/any.hpp>
17 #include <list>
18 #include <cassert>
19 #include <utility>
20
21 #ifdef BOOST_HAS_ABI_HEADERS
22 #  include BOOST_ABI_PREFIX
23 #endif
24
25 namespace boost {
26   namespace BOOST_SIGNALS_NAMESPACE {
27     class trackable;
28
29     namespace detail {
30       // Represents an object that has been bound as part of a slot, and how
31       // to notify that object of a disconnect
32       struct bound_object {
33         void* obj;
34         void* data;
35         void (*disconnect)(void*, void*);
36
37         bool operator==(const bound_object& other) const
38           { return obj == other.obj && data == other.data; }
39         bool operator<(const bound_object& other) const
40           { return obj < other.obj; }
41       };
42
43       // Describes the connection between a signal and the objects that are
44       // bound for a specific slot. Enables notification of the signal and the
45       // slots when a disconnect is requested.
46       struct basic_connection {
47         void* signal;
48         void* signal_data;
49         void (*signal_disconnect)(void*, void*);
50
51         std::list<bound_object> bound_objects;
52       };
53     } // end namespace detail
54
55     // The user may freely pass around the "connection" object and terminate
56     // the connection at any time using disconnect().
57     class BOOST_SIGNALS_DECL connection :
58       private less_than_comparable1<connection>,
59       private equality_comparable1<connection>
60     {
61     public:
62       connection() : con(), controlling_connection(false) {}
63       connection(const connection&);
64       ~connection();
65
66       // Disconnect the signal and slot, if they are connected
67       void disconnect() const;
68
69       // Returns true if the signal and slot are connected
70       bool connected() const { return con.get() && con->signal_disconnect; }
71
72       // Comparison of connections
73       inline bool operator==(const connection& other) const;
74       inline bool operator<(const connection& other) const;
75
76       // Connection assignment
77       connection& operator=(const connection& other) ;
78
79       // Swap connections
80       inline void swap(connection& other);
81
82     public: // TBD: CHANGE THIS
83       // Set whether this connection object is controlling or not
84       void set_controlling() { controlling_connection = true; }
85
86     private:
87       friend class detail::signal_base_impl;
88       friend class detail::slot_base;
89       friend class trackable;
90
91       // Reset this connection to refer to a different actual connection
92       void reset(BOOST_SIGNALS_NAMESPACE::detail::basic_connection*);
93
94       // Add a bound object to this connection (not for users)
95       void add_bound_object(const BOOST_SIGNALS_NAMESPACE::detail::bound_object& b);
96
97       friend class BOOST_SIGNALS_NAMESPACE::detail::bound_objects_visitor;
98
99       // Pointer to the actual contents of the connection
100       shared_ptr<BOOST_SIGNALS_NAMESPACE::detail::basic_connection> con;
101
102       // True if the destruction of this connection object should disconnect
103       bool controlling_connection;
104     };
105
106     // Similar to connection, but will disconnect the connection when it is
107     // destroyed unless release() has been called.
108     class BOOST_SIGNALS_DECL scoped_connection : public connection {
109     public:
110       scoped_connection() : connection(), released(false) {}
111       scoped_connection(const connection&);
112       scoped_connection(const scoped_connection&);
113       ~scoped_connection();
114
115       connection release();
116
117       inline void swap(scoped_connection&);
118
119       scoped_connection& operator=(const connection&);
120       scoped_connection& operator=(const scoped_connection&);
121
122     private:
123       bool released;
124     };
125
126     inline connection::connection(const connection& other) :
127       con(other.con), controlling_connection(other.controlling_connection)
128     {
129     }
130
131     inline connection::~connection()
132     {
133       if (controlling_connection) {
134         disconnect();
135       }
136     }
137
138     inline void
139     connection::reset(BOOST_SIGNALS_NAMESPACE::detail::basic_connection* new_con)
140     {
141       con.reset(new_con);
142     }
143
144     inline bool connection::operator==(const connection& other) const
145     {
146       return con.get() == other.con.get();
147     }
148
149     inline bool connection::operator<(const connection& other) const
150     {
151       return con.get() < other.con.get();
152     }
153
154     inline connection& connection::operator=(const connection& other)
155     {
156       connection(other).swap(*this);
157       return *this;
158     }
159
160     inline void connection::swap(connection& other)
161     {
162       this->con.swap(other.con);
163       std::swap(this->controlling_connection, other.controlling_connection);
164     }
165
166     inline void swap(connection& c1, connection& c2)
167     {
168       c1.swap(c2);
169     }
170
171     inline scoped_connection::scoped_connection(const connection& other) :
172       connection(other),
173       released(false)
174     {
175     }
176
177     inline
178     scoped_connection::scoped_connection(const scoped_connection& other) :
179       connection(other),
180       released(other.released)
181     {
182     }
183
184     inline scoped_connection::~scoped_connection()
185     {
186       if (!released) {
187         this->disconnect();
188       }
189     }
190
191     inline connection scoped_connection::release()
192     {
193       released = true;
194       return *this;
195     }
196
197     inline void scoped_connection::swap(scoped_connection& other)
198     {
199       this->connection::swap(other);
200       bool other_released = other.released;
201       other.released = this->released;
202       this->released = other_released;
203     }
204
205     inline void swap(scoped_connection& c1, scoped_connection& c2)
206     {
207       c1.swap(c2);
208     }
209
210     inline scoped_connection&
211     scoped_connection::operator=(const connection& other)
212     {
213       scoped_connection(other).swap(*this);
214       return *this;
215     }
216
217     inline scoped_connection&
218     scoped_connection::operator=(const scoped_connection& other)
219     {
220       scoped_connection(other).swap(*this);
221       return *this;
222     }
223
224     namespace detail {
225       struct connection_slot_pair {
226         connection first;
227         any second;
228
229         connection_slot_pair() {}
230
231         connection_slot_pair(const connection& c, const any& a)
232           : first(c), second(a)
233         {
234         }
235
236         // Dummys to allow explicit instantiation to work
237         bool operator==(const connection_slot_pair&) const { return false; }
238         bool operator<(const connection_slot_pair&) const { return false;}
239       };
240
241       // Determines if the underlying connection is disconnected
242       struct is_disconnected {
243         typedef std::pair<const any, connection_slot_pair> argument_type;
244         typedef bool result_type;
245
246         inline bool operator()(const argument_type& c) const
247         {
248           return !c.second.first.connected();
249         }
250       };
251
252       // Autodisconnects the bound object when it is destroyed unless the
253       // release method is invoked.
254       class auto_disconnect_bound_object {
255       public:
256         auto_disconnect_bound_object(const bound_object& b) :
257           binding(b), auto_disconnect(true)
258         {
259         }
260
261         ~auto_disconnect_bound_object()
262         {
263           if (auto_disconnect)
264             binding.disconnect(binding.obj, binding.data);
265         }
266
267         void release() { auto_disconnect = false; }
268
269       private:
270         bound_object binding;
271         bool auto_disconnect;
272       };
273     } // end namespace detail
274   } // end namespace BOOST_SIGNALS_NAMESPACE
275 } // end namespace boost
276
277 #ifdef BOOST_HAS_ABI_HEADERS
278 #  include BOOST_ABI_SUFFIX
279 #endif
280
281 #endif // BOOST_SIGNALS_CONNECTION_HPP