2 boost::signals2::connection provides a handle to a signal/slot connection.
4 Author: Frank Mori Hess <fmhess@users.sourceforge.net>
7 // Copyright Frank Mori Hess 2007-2008.
8 // Distributed under the Boost Software License, Version
9 // 1.0. (See accompanying file LICENSE_1_0.txt or copy at
10 // http://www.boost.org/LICENSE_1_0.txt)
12 // See http://www.boost.org/libs/signals2 for library home page.
14 #ifndef BOOST_SIGNALS2_CONNECTION_HPP
15 #define BOOST_SIGNALS2_CONNECTION_HPP
17 #include <boost/function.hpp>
18 #include <boost/mpl/bool.hpp>
19 #include <boost/noncopyable.hpp>
20 #include <boost/shared_ptr.hpp>
21 #include <boost/signals2/detail/null_output_iterator.hpp>
22 #include <boost/signals2/detail/unique_lock.hpp>
23 #include <boost/signals2/slot.hpp>
24 #include <boost/weak_ptr.hpp>
30 extern inline void null_deleter(const void*) {}
33 class connection_body_base
36 connection_body_base():
40 virtual ~connection_body_base() {}
43 unique_lock<connection_body_base> local_lock(*this);
46 void nolock_disconnect()
50 virtual bool connected() const = 0;
51 shared_ptr<void> get_blocker()
53 unique_lock<connection_body_base> local_lock(*this);
54 shared_ptr<void> blocker = _weak_blocker.lock();
55 if(blocker == shared_ptr<void>())
57 blocker.reset(this, &null_deleter);
58 _weak_blocker = blocker;
64 return !_weak_blocker.expired();
66 bool nolock_nograb_blocked() const
68 return nolock_nograb_connected() == false || blocked();
70 bool nolock_nograb_connected() const {return _connected;}
71 // expose part of Lockable concept of mutex
72 virtual void lock() = 0;
73 virtual void unlock() = 0;
77 mutable bool _connected;
78 weak_ptr<void> _weak_blocker;
81 template<typename GroupKey, typename SlotType, typename Mutex>
82 class connection_body: public connection_body_base
85 typedef Mutex mutex_type;
86 connection_body(const SlotType &slot_in):
90 virtual ~connection_body() {}
91 virtual bool connected() const
93 unique_lock<mutex_type> local_lock(_mutex);
94 nolock_grab_tracked_objects(detail::null_output_iterator());
95 return nolock_nograb_connected();
97 const GroupKey& group_key() const {return _group_key;}
98 void set_group_key(const GroupKey &key) {_group_key = key;}
99 bool nolock_slot_expired() const
101 bool expired = slot.expired();
108 template<typename OutputIterator>
109 void nolock_grab_tracked_objects(OutputIterator inserter) const
111 slot_base::tracked_container_type::const_iterator it;
112 for(it = slot.tracked_objects().begin();
113 it != slot.tracked_objects().end();
116 void_shared_ptr_variant locked_object
120 detail::lock_weak_ptr_visitor(),
124 if(apply_visitor(detail::expired_weak_ptr_visitor(), *it))
129 *inserter++ = locked_object;
132 // expose Lockable concept of mutex
137 virtual void unlock()
143 mutable mutex_type _mutex;
148 class shared_connection_block;
153 friend class shared_connection_block;
156 connection(const connection &other): _weak_connection_body(other._weak_connection_body)
158 connection(const boost::weak_ptr<detail::connection_body_base> &connectionBody):
159 _weak_connection_body(connectionBody)
162 void disconnect() const
164 boost::shared_ptr<detail::connection_body_base> connectionBody(_weak_connection_body.lock());
165 if(connectionBody == 0) return;
166 connectionBody->disconnect();
168 bool connected() const
170 boost::shared_ptr<detail::connection_body_base> connectionBody(_weak_connection_body.lock());
171 if(connectionBody == 0) return false;
172 return connectionBody->connected();
176 boost::shared_ptr<detail::connection_body_base> connectionBody(_weak_connection_body.lock());
177 if(connectionBody == 0) return true;
178 return connectionBody->blocked();
180 bool operator==(const connection& other) const
182 boost::shared_ptr<detail::connection_body_base> connectionBody(_weak_connection_body.lock());
183 boost::shared_ptr<detail::connection_body_base> otherConnectionBody(other._weak_connection_body.lock());
184 return connectionBody == otherConnectionBody;
186 bool operator!=(const connection& other) const
188 return !(*this == other);
190 bool operator<(const connection& other) const
192 boost::shared_ptr<detail::connection_body_base> connectionBody(_weak_connection_body.lock());
193 boost::shared_ptr<detail::connection_body_base> otherConnectionBody(other._weak_connection_body.lock());
194 return connectionBody < otherConnectionBody;
196 void swap(connection &other)
199 swap(_weak_connection_body, other._weak_connection_body);
203 boost::weak_ptr<detail::connection_body_base> _weak_connection_body;
205 inline void swap(connection &conn1, connection &conn2)
210 class scoped_connection: public connection
213 scoped_connection() {}
214 scoped_connection(const connection &other):
221 scoped_connection& operator=(const connection &rhs)
224 connection::operator=(rhs);
229 connection conn(_weak_connection_body);
230 _weak_connection_body.reset();
234 scoped_connection(const scoped_connection &other);
235 scoped_connection& operator=(const scoped_connection &rhs);
237 // Sun 5.9 compiler doesn't find the swap for base connection class when
238 // arguments are scoped_connection, so we provide this explicitly.
239 inline void swap(scoped_connection &conn1, scoped_connection &conn2)
246 #endif // BOOST_SIGNALS2_CONNECTION_HPP