1 // Boost.Signals library
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)
8 // For more information, see http://www.boost.org
10 #ifndef BOOST_SIGNALS_CONNECTION_HPP
11 #define BOOST_SIGNALS_CONNECTION_HPP
13 #include <boost/signals/detail/signals_common.hpp>
14 #include <boost/smart_ptr.hpp>
15 #include <boost/operators.hpp>
16 #include <boost/any.hpp>
21 #ifdef BOOST_HAS_ABI_HEADERS
22 # include BOOST_ABI_PREFIX
26 namespace BOOST_SIGNALS_NAMESPACE {
30 // Represents an object that has been bound as part of a slot, and how
31 // to notify that object of a disconnect
35 void (*disconnect)(void*, void*);
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; }
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 {
49 void (*signal_disconnect)(void*, void*);
51 std::list<bound_object> bound_objects;
53 } // end namespace detail
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>
62 connection() : con(), controlling_connection(false) {}
63 connection(const connection&);
66 // Disconnect the signal and slot, if they are connected
67 void disconnect() const;
69 // Returns true if the signal and slot are connected
70 bool connected() const { return con.get() && con->signal_disconnect; }
72 // Comparison of connections
73 inline bool operator==(const connection& other) const;
74 inline bool operator<(const connection& other) const;
76 // Connection assignment
77 connection& operator=(const connection& other) ;
80 inline void swap(connection& other);
82 public: // TBD: CHANGE THIS
83 // Set whether this connection object is controlling or not
84 void set_controlling() { controlling_connection = true; }
87 friend class detail::signal_base_impl;
88 friend class detail::slot_base;
89 friend class trackable;
91 // Reset this connection to refer to a different actual connection
92 void reset(BOOST_SIGNALS_NAMESPACE::detail::basic_connection*);
94 // Add a bound object to this connection (not for users)
95 void add_bound_object(const BOOST_SIGNALS_NAMESPACE::detail::bound_object& b);
97 friend class BOOST_SIGNALS_NAMESPACE::detail::bound_objects_visitor;
99 // Pointer to the actual contents of the connection
100 shared_ptr<BOOST_SIGNALS_NAMESPACE::detail::basic_connection> con;
102 // True if the destruction of this connection object should disconnect
103 bool controlling_connection;
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 {
110 scoped_connection() : connection(), released(false) {}
111 scoped_connection(const connection&);
112 scoped_connection(const scoped_connection&);
113 ~scoped_connection();
115 connection release();
117 inline void swap(scoped_connection&);
119 scoped_connection& operator=(const connection&);
120 scoped_connection& operator=(const scoped_connection&);
126 inline connection::connection(const connection& other) :
127 con(other.con), controlling_connection(other.controlling_connection)
131 inline connection::~connection()
133 if (controlling_connection) {
139 connection::reset(BOOST_SIGNALS_NAMESPACE::detail::basic_connection* new_con)
144 inline bool connection::operator==(const connection& other) const
146 return con.get() == other.con.get();
149 inline bool connection::operator<(const connection& other) const
151 return con.get() < other.con.get();
154 inline connection& connection::operator=(const connection& other)
156 connection(other).swap(*this);
160 inline void connection::swap(connection& other)
162 this->con.swap(other.con);
163 std::swap(this->controlling_connection, other.controlling_connection);
166 inline void swap(connection& c1, connection& c2)
171 inline scoped_connection::scoped_connection(const connection& other) :
178 scoped_connection::scoped_connection(const scoped_connection& other) :
180 released(other.released)
184 inline scoped_connection::~scoped_connection()
191 inline connection scoped_connection::release()
197 inline void scoped_connection::swap(scoped_connection& other)
199 this->connection::swap(other);
200 bool other_released = other.released;
201 other.released = this->released;
202 this->released = other_released;
205 inline void swap(scoped_connection& c1, scoped_connection& c2)
210 inline scoped_connection&
211 scoped_connection::operator=(const connection& other)
213 scoped_connection(other).swap(*this);
217 inline scoped_connection&
218 scoped_connection::operator=(const scoped_connection& other)
220 scoped_connection(other).swap(*this);
225 struct connection_slot_pair {
229 connection_slot_pair() {}
231 connection_slot_pair(const connection& c, const any& a)
232 : first(c), second(a)
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;}
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;
246 inline bool operator()(const argument_type& c) const
248 return !c.second.first.connected();
252 // Autodisconnects the bound object when it is destroyed unless the
253 // release method is invoked.
254 class auto_disconnect_bound_object {
256 auto_disconnect_bound_object(const bound_object& b) :
257 binding(b), auto_disconnect(true)
261 ~auto_disconnect_bound_object()
264 binding.disconnect(binding.obj, binding.data);
267 void release() { auto_disconnect = false; }
270 bound_object binding;
271 bool auto_disconnect;
273 } // end namespace detail
274 } // end namespace BOOST_SIGNALS_NAMESPACE
275 } // end namespace boost
277 #ifdef BOOST_HAS_ABI_HEADERS
278 # include BOOST_ABI_SUFFIX
281 #endif // BOOST_SIGNALS_CONNECTION_HPP