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>
28 namespace BOOST_SIGNALS_NAMESPACE {
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(BOOST_SIGNALS_NAMESPACE::detail::basic_connection*);
96 // Add a bound object to this connection (not for users)
97 void add_bound_object(const BOOST_SIGNALS_NAMESPACE::detail::bound_object& b);
99 friend class BOOST_SIGNALS_NAMESPACE::detail::bound_objects_visitor;
101 // Pointer to the actual contents of the connection
102 shared_ptr<BOOST_SIGNALS_NAMESPACE::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 inline 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(BOOST_SIGNALS_NAMESPACE::detail::basic_connection* new_con)
152 connection::add_bound_object(const BOOST_SIGNALS_NAMESPACE::detail::bound_object& b)
154 assert(con.get() != 0);
155 con->bound_objects.push_back(b);
158 inline bool connection::operator==(const connection& other) const
160 return con.get() == other.con.get();
163 inline bool connection::operator<(const connection& other) const
165 return con.get() < other.con.get();
168 inline connection& connection::operator=(const connection& other)
170 connection(other).swap(*this);
174 inline void connection::swap(connection& other)
176 this->con.swap(other.con);
177 std::swap(this->controlling_connection, other.controlling_connection);
180 inline void swap(connection& c1, connection& c2)
185 inline scoped_connection::scoped_connection(const connection& other) :
192 scoped_connection::scoped_connection(const scoped_connection& other) :
194 released(other.released)
198 inline scoped_connection::~scoped_connection()
205 inline connection scoped_connection::release()
211 inline void scoped_connection::swap(scoped_connection& other)
213 this->connection::swap(other);
214 bool other_released = other.released;
215 other.released = this->released;
216 this->released = other_released;
219 inline void swap(scoped_connection& c1, scoped_connection& c2)
224 inline scoped_connection&
225 scoped_connection::operator=(const connection& other)
227 scoped_connection(other).swap(*this);
231 inline scoped_connection&
232 scoped_connection::operator=(const scoped_connection& other)
234 scoped_connection(other).swap(*this);
239 struct connection_slot_pair {
243 connection_slot_pair() {}
245 connection_slot_pair(const connection& c, const any& a)
246 : first(c), second(a)
250 // Dummys to allow explicit instantiation to work
251 bool operator==(const connection_slot_pair&) const { return false; }
252 bool operator<(const connection_slot_pair&) const { return false;}
255 // Determines if the underlying connection is disconnected
256 struct is_disconnected {
257 typedef std::pair<const any, connection_slot_pair> argument_type;
258 typedef bool result_type;
260 inline bool operator()(const argument_type& c) const
262 return !c.second.first.connected();
266 // Autodisconnects the bound object when it is destroyed unless the
267 // release method is invoked.
268 class auto_disconnect_bound_object {
270 auto_disconnect_bound_object(const bound_object& b) :
271 binding(b), auto_disconnect(true)
275 ~auto_disconnect_bound_object()
278 binding.disconnect(binding.obj, binding.data);
281 void release() { auto_disconnect = false; }
284 bound_object binding;
285 bool auto_disconnect;
287 } // end namespace detail
288 } // end namespace BOOST_SIGNALS_NAMESPACE
289 } // end namespace boost
291 #endif // BOOST_SIGNALS_CONNECTION_HPP