1 // Boost.Signals library
3 // Copyright (C) 2001 Doug Gregor (gregod@cs.rpi.edu)
5 // Permission to copy, use, sell and distribute this software is granted
6 // provided this copyright notice appears in all copies.
7 // Permission to modify the code and to distribute modified code is granted
8 // provided this copyright notice appears in all copies, and a notice
9 // that the code was modified is included with the copyright notice.
11 // This software is provided "as is" without express or implied warranty,
12 // and with no claim as to its suitability for any purpose.
14 // For more information, see http://www.boost.org
16 #ifndef BOOST_SIGNALS_CONNECTION_HPP
17 #define BOOST_SIGNALS_CONNECTION_HPP
19 #include <boost/signals/detail/signals_common.hpp>
20 #include <boost/smart_ptr.hpp>
21 #include <boost/operators.hpp>
22 #include <boost/any.hpp>
32 // Represents an object that has been bound as part of a slot, and how
33 // to notify that object of a disconnect
37 void (*disconnect)(void*, void*);
39 bool operator==(const bound_object& other) const
40 { return obj == other.obj && data == other.data; }
41 bool operator<(const bound_object& other) const
42 { return obj < other.obj; }
45 // Describes the connection between a signal and the objects that are
46 // bound for a specific slot. Enables notification of the signal and the
47 // slots when a disconnect is requested.
48 struct basic_connection {
51 void (*signal_disconnect)(void*, void*);
53 std::list<bound_object> bound_objects;
55 } // end namespace detail
57 // The user may freely pass around the "connection" object and terminate
58 // the connection at any time using disconnect().
60 private less_than_comparable1<connection>,
61 private equality_comparable1<connection>
65 connection(const connection&);
68 // Disconnect the signal and slot, if they are connected
69 void disconnect() const;
71 // Returns true if the signal and slot are connected
72 bool connected() const { return con.get() && con->signal_disconnect; }
74 // Comparison of connections
75 inline bool operator==(const connection& other) const;
76 inline bool operator<(const connection& other) const;
78 // Connection assignment
79 connection& operator=(const connection& other) ;
82 inline void swap(connection& other);
84 public: // TBD: CHANGE THIS
85 // Set whether this connection object is controlling or not
86 void set_controlling() { controlling_connection = true; }
89 friend class detail::signal_base_impl;
90 friend class detail::slot_base;
91 friend class trackable;
93 // Reset this connection to refer to a different actual connection
94 void reset(signals::detail::basic_connection*);
96 // Add a bound object to this connection (not for users)
97 void add_bound_object(const signals::detail::bound_object& b);
99 friend class signals::detail::bound_objects_visitor;
101 // Pointer to the actual contents of the connection
102 shared_ptr<signals::detail::basic_connection> con;
104 // True if the destruction of this connection object should disconnect
105 bool controlling_connection;
108 // Similar to connection, but will disconnect the connection when it is
109 // destroyed unless release() has been called.
110 class scoped_connection : public connection {
112 scoped_connection() : connection(), released(false) {}
113 scoped_connection(const connection&);
114 scoped_connection(const scoped_connection&);
115 ~scoped_connection();
117 connection release();
119 void swap(scoped_connection&);
121 scoped_connection& operator=(const connection&);
122 scoped_connection& operator=(const scoped_connection&);
128 inline connection::connection() :
129 con(), controlling_connection(false)
133 inline connection::connection(const connection& other) :
134 con(other.con), controlling_connection(other.controlling_connection)
138 inline connection::~connection()
140 if (controlling_connection) {
146 connection::reset(signals::detail::basic_connection* new_con)
152 connection::add_bound_object(const signals::detail::bound_object& b)
154 // c-assert expects an int, so don't pass it a pointer
155 assert(con.get() != 0);
156 con->bound_objects.push_back(b);
159 inline bool connection::operator==(const connection& other) const
161 return con.get() == other.con.get();
164 inline bool connection::operator<(const connection& other) const
166 return con.get() < other.con.get();
169 inline connection& connection::operator=(const connection& other)
171 connection(other).swap(*this);
175 inline void connection::swap(connection& other)
177 this->con.swap(other.con);
178 std::swap(this->controlling_connection, other.controlling_connection);
181 inline void swap(connection& c1, connection& c2)
186 inline scoped_connection::scoped_connection(const connection& other) :
193 scoped_connection::scoped_connection(const scoped_connection& other) :
195 released(other.released)
199 inline scoped_connection::~scoped_connection()
206 inline connection scoped_connection::release()
212 inline void scoped_connection::swap(scoped_connection& other)
214 this->connection::swap(other);
215 bool other_released = other.released;
216 other.released = this->released;
217 this->released = other_released;
220 inline void swap(scoped_connection& c1, scoped_connection& c2)
225 inline scoped_connection&
226 scoped_connection::operator=(const connection& other)
228 scoped_connection(other).swap(*this);
232 inline scoped_connection&
233 scoped_connection::operator=(const scoped_connection& other)
235 scoped_connection(other).swap(*this);
240 struct connection_slot_pair {
244 connection_slot_pair() {}
246 connection_slot_pair(const connection& c, const any& a)
247 : first(c), second(a)
251 // Dummys to allow explicit instantiation to work
252 bool operator==(const connection_slot_pair&) const { return false; }
253 bool operator<(const connection_slot_pair&) const { return false;}
256 // Determines if the underlying connection is disconnected
257 struct is_disconnected {
258 typedef std::pair<const any, connection_slot_pair> argument_type;
259 typedef bool result_type;
261 inline bool operator()(const argument_type& c) const
263 return !c.second.first.connected();
267 // Autodisconnects the bound object when it is destroyed unless the
268 // release method is invoked.
269 class auto_disconnect_bound_object {
271 auto_disconnect_bound_object(const bound_object& b) :
272 binding(b), auto_disconnect(true)
276 ~auto_disconnect_bound_object()
279 binding.disconnect(binding.obj, binding.data);
282 void release() { auto_disconnect = false; }
285 bound_object binding;
286 bool auto_disconnect;
288 } // end namespace detail
289 } // end namespace signals
290 } // end namespace boost
292 #endif // BOOST_SIGNALS_CONNECTION_HPP