annotate DEPENDENCIES/generic/include/boost/signals2/connection.hpp @ 133:4acb5d8d80b6 tip

Don't fail environmental check if README.md exists (but .txt and no-suffix don't)
author Chris Cannam
date Tue, 30 Jul 2019 12:25:44 +0100
parents c530137014c0
children
rev   line source
Chris@16 1 /*
Chris@16 2 boost::signals2::connection provides a handle to a signal/slot connection.
Chris@16 3
Chris@16 4 Author: Frank Mori Hess <fmhess@users.sourceforge.net>
Chris@16 5 Begin: 2007-01-23
Chris@16 6 */
Chris@16 7 // Copyright Frank Mori Hess 2007-2008.
Chris@16 8 // Distributed under the Boost Software License, Version
Chris@16 9 // 1.0. (See accompanying file LICENSE_1_0.txt or copy at
Chris@16 10 // http://www.boost.org/LICENSE_1_0.txt)
Chris@16 11
Chris@16 12 // See http://www.boost.org/libs/signals2 for library home page.
Chris@16 13
Chris@16 14 #ifndef BOOST_SIGNALS2_CONNECTION_HPP
Chris@16 15 #define BOOST_SIGNALS2_CONNECTION_HPP
Chris@16 16
Chris@16 17 #include <boost/function.hpp>
Chris@16 18 #include <boost/mpl/bool.hpp>
Chris@16 19 #include <boost/noncopyable.hpp>
Chris@16 20 #include <boost/shared_ptr.hpp>
Chris@16 21 #include <boost/signals2/detail/null_output_iterator.hpp>
Chris@16 22 #include <boost/signals2/detail/unique_lock.hpp>
Chris@16 23 #include <boost/signals2/slot.hpp>
Chris@16 24 #include <boost/weak_ptr.hpp>
Chris@16 25
Chris@16 26 namespace boost
Chris@16 27 {
Chris@16 28 namespace signals2
Chris@16 29 {
Chris@16 30 extern inline void null_deleter(const void*) {}
Chris@16 31 namespace detail
Chris@16 32 {
Chris@16 33 class connection_body_base
Chris@16 34 {
Chris@16 35 public:
Chris@16 36 connection_body_base():
Chris@16 37 _connected(true)
Chris@16 38 {
Chris@16 39 }
Chris@16 40 virtual ~connection_body_base() {}
Chris@16 41 void disconnect()
Chris@16 42 {
Chris@16 43 unique_lock<connection_body_base> local_lock(*this);
Chris@16 44 nolock_disconnect();
Chris@16 45 }
Chris@16 46 void nolock_disconnect()
Chris@16 47 {
Chris@16 48 _connected = false;
Chris@16 49 }
Chris@16 50 virtual bool connected() const = 0;
Chris@16 51 shared_ptr<void> get_blocker()
Chris@16 52 {
Chris@16 53 unique_lock<connection_body_base> local_lock(*this);
Chris@16 54 shared_ptr<void> blocker = _weak_blocker.lock();
Chris@16 55 if(blocker == shared_ptr<void>())
Chris@16 56 {
Chris@16 57 blocker.reset(this, &null_deleter);
Chris@16 58 _weak_blocker = blocker;
Chris@16 59 }
Chris@16 60 return blocker;
Chris@16 61 }
Chris@16 62 bool blocked() const
Chris@16 63 {
Chris@16 64 return !_weak_blocker.expired();
Chris@16 65 }
Chris@16 66 bool nolock_nograb_blocked() const
Chris@16 67 {
Chris@16 68 return nolock_nograb_connected() == false || blocked();
Chris@16 69 }
Chris@16 70 bool nolock_nograb_connected() const {return _connected;}
Chris@16 71 // expose part of Lockable concept of mutex
Chris@16 72 virtual void lock() = 0;
Chris@16 73 virtual void unlock() = 0;
Chris@16 74
Chris@16 75 protected:
Chris@16 76
Chris@16 77 mutable bool _connected;
Chris@16 78 weak_ptr<void> _weak_blocker;
Chris@16 79 };
Chris@16 80
Chris@16 81 template<typename GroupKey, typename SlotType, typename Mutex>
Chris@16 82 class connection_body: public connection_body_base
Chris@16 83 {
Chris@16 84 public:
Chris@16 85 typedef Mutex mutex_type;
Chris@16 86 connection_body(const SlotType &slot_in):
Chris@16 87 slot(slot_in)
Chris@16 88 {
Chris@16 89 }
Chris@16 90 virtual ~connection_body() {}
Chris@16 91 virtual bool connected() const
Chris@16 92 {
Chris@16 93 unique_lock<mutex_type> local_lock(_mutex);
Chris@16 94 nolock_grab_tracked_objects(detail::null_output_iterator());
Chris@16 95 return nolock_nograb_connected();
Chris@16 96 }
Chris@16 97 const GroupKey& group_key() const {return _group_key;}
Chris@16 98 void set_group_key(const GroupKey &key) {_group_key = key;}
Chris@16 99 bool nolock_slot_expired() const
Chris@16 100 {
Chris@16 101 bool expired = slot.expired();
Chris@16 102 if(expired == true)
Chris@16 103 {
Chris@16 104 _connected = false;
Chris@16 105 }
Chris@16 106 return expired;
Chris@16 107 }
Chris@16 108 template<typename OutputIterator>
Chris@16 109 void nolock_grab_tracked_objects(OutputIterator inserter) const
Chris@16 110 {
Chris@16 111 slot_base::tracked_container_type::const_iterator it;
Chris@16 112 for(it = slot.tracked_objects().begin();
Chris@16 113 it != slot.tracked_objects().end();
Chris@16 114 ++it)
Chris@16 115 {
Chris@16 116 void_shared_ptr_variant locked_object
Chris@16 117 (
Chris@16 118 apply_visitor
Chris@16 119 (
Chris@16 120 detail::lock_weak_ptr_visitor(),
Chris@16 121 *it
Chris@16 122 )
Chris@16 123 );
Chris@16 124 if(apply_visitor(detail::expired_weak_ptr_visitor(), *it))
Chris@16 125 {
Chris@16 126 _connected = false;
Chris@16 127 return;
Chris@16 128 }
Chris@16 129 *inserter++ = locked_object;
Chris@16 130 }
Chris@16 131 }
Chris@16 132 // expose Lockable concept of mutex
Chris@16 133 virtual void lock()
Chris@16 134 {
Chris@16 135 _mutex.lock();
Chris@16 136 }
Chris@16 137 virtual void unlock()
Chris@16 138 {
Chris@16 139 _mutex.unlock();
Chris@16 140 }
Chris@16 141 SlotType slot;
Chris@16 142 private:
Chris@16 143 mutable mutex_type _mutex;
Chris@16 144 GroupKey _group_key;
Chris@16 145 };
Chris@16 146 }
Chris@16 147
Chris@16 148 class shared_connection_block;
Chris@16 149
Chris@16 150 class connection
Chris@16 151 {
Chris@16 152 public:
Chris@16 153 friend class shared_connection_block;
Chris@16 154
Chris@16 155 connection() {}
Chris@16 156 connection(const connection &other): _weak_connection_body(other._weak_connection_body)
Chris@16 157 {}
Chris@16 158 connection(const boost::weak_ptr<detail::connection_body_base> &connectionBody):
Chris@16 159 _weak_connection_body(connectionBody)
Chris@16 160 {}
Chris@101 161
Chris@101 162 // move support
Chris@101 163 #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
Chris@101 164 connection(connection && other): _weak_connection_body(std::move(other._weak_connection_body))
Chris@101 165 {
Chris@101 166 // make sure other is reset, in case it is a scoped_connection (so it
Chris@101 167 // won't disconnect on destruction after being moved away from).
Chris@101 168 other._weak_connection_body.reset();
Chris@101 169 }
Chris@101 170 connection & operator=(connection && other)
Chris@101 171 {
Chris@101 172 if(&other == this) return *this;
Chris@101 173 _weak_connection_body = std::move(other._weak_connection_body);
Chris@101 174 // make sure other is reset, in case it is a scoped_connection (so it
Chris@101 175 // won't disconnect on destruction after being moved away from).
Chris@101 176 other._weak_connection_body.reset();
Chris@101 177 return *this;
Chris@101 178 }
Chris@101 179 #endif // !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
Chris@101 180 connection & operator=(const connection & other)
Chris@101 181 {
Chris@101 182 if(&other == this) return *this;
Chris@101 183 _weak_connection_body = other._weak_connection_body;
Chris@101 184 return *this;
Chris@101 185 }
Chris@101 186
Chris@16 187 ~connection() {}
Chris@16 188 void disconnect() const
Chris@16 189 {
Chris@16 190 boost::shared_ptr<detail::connection_body_base> connectionBody(_weak_connection_body.lock());
Chris@16 191 if(connectionBody == 0) return;
Chris@16 192 connectionBody->disconnect();
Chris@16 193 }
Chris@16 194 bool connected() const
Chris@16 195 {
Chris@16 196 boost::shared_ptr<detail::connection_body_base> connectionBody(_weak_connection_body.lock());
Chris@16 197 if(connectionBody == 0) return false;
Chris@16 198 return connectionBody->connected();
Chris@16 199 }
Chris@16 200 bool blocked() const
Chris@16 201 {
Chris@16 202 boost::shared_ptr<detail::connection_body_base> connectionBody(_weak_connection_body.lock());
Chris@16 203 if(connectionBody == 0) return true;
Chris@16 204 return connectionBody->blocked();
Chris@16 205 }
Chris@16 206 bool operator==(const connection& other) const
Chris@16 207 {
Chris@16 208 boost::shared_ptr<detail::connection_body_base> connectionBody(_weak_connection_body.lock());
Chris@16 209 boost::shared_ptr<detail::connection_body_base> otherConnectionBody(other._weak_connection_body.lock());
Chris@16 210 return connectionBody == otherConnectionBody;
Chris@16 211 }
Chris@16 212 bool operator!=(const connection& other) const
Chris@16 213 {
Chris@16 214 return !(*this == other);
Chris@16 215 }
Chris@16 216 bool operator<(const connection& other) const
Chris@16 217 {
Chris@16 218 boost::shared_ptr<detail::connection_body_base> connectionBody(_weak_connection_body.lock());
Chris@16 219 boost::shared_ptr<detail::connection_body_base> otherConnectionBody(other._weak_connection_body.lock());
Chris@16 220 return connectionBody < otherConnectionBody;
Chris@16 221 }
Chris@16 222 void swap(connection &other)
Chris@16 223 {
Chris@16 224 using std::swap;
Chris@16 225 swap(_weak_connection_body, other._weak_connection_body);
Chris@16 226 }
Chris@16 227 protected:
Chris@16 228
Chris@16 229 boost::weak_ptr<detail::connection_body_base> _weak_connection_body;
Chris@16 230 };
Chris@16 231 inline void swap(connection &conn1, connection &conn2)
Chris@16 232 {
Chris@16 233 conn1.swap(conn2);
Chris@16 234 }
Chris@16 235
Chris@16 236 class scoped_connection: public connection
Chris@16 237 {
Chris@16 238 public:
Chris@16 239 scoped_connection() {}
Chris@16 240 scoped_connection(const connection &other):
Chris@16 241 connection(other)
Chris@16 242 {}
Chris@16 243 ~scoped_connection()
Chris@16 244 {
Chris@16 245 disconnect();
Chris@16 246 }
Chris@16 247 scoped_connection& operator=(const connection &rhs)
Chris@16 248 {
Chris@16 249 disconnect();
Chris@16 250 connection::operator=(rhs);
Chris@16 251 return *this;
Chris@16 252 }
Chris@101 253
Chris@101 254 // move support
Chris@101 255 #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
Chris@101 256 scoped_connection(scoped_connection && other): connection(std::move(other))
Chris@101 257 {
Chris@101 258 }
Chris@101 259 scoped_connection(connection && other): connection(std::move(other))
Chris@101 260 {
Chris@101 261 }
Chris@101 262 scoped_connection & operator=(scoped_connection && other)
Chris@101 263 {
Chris@101 264 if(&other == this) return *this;
Chris@101 265 disconnect();
Chris@101 266 connection::operator=(std::move(other));
Chris@101 267 return *this;
Chris@101 268 }
Chris@101 269 scoped_connection & operator=(connection && other)
Chris@101 270 {
Chris@101 271 if(&other == this) return *this;
Chris@101 272 disconnect();
Chris@101 273 connection::operator=(std::move(other));
Chris@101 274 return *this;
Chris@101 275 }
Chris@101 276 #endif // !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
Chris@101 277
Chris@16 278 connection release()
Chris@16 279 {
Chris@16 280 connection conn(_weak_connection_body);
Chris@16 281 _weak_connection_body.reset();
Chris@16 282 return conn;
Chris@16 283 }
Chris@16 284 private:
Chris@16 285 scoped_connection(const scoped_connection &other);
Chris@16 286 scoped_connection& operator=(const scoped_connection &rhs);
Chris@16 287 };
Chris@16 288 // Sun 5.9 compiler doesn't find the swap for base connection class when
Chris@16 289 // arguments are scoped_connection, so we provide this explicitly.
Chris@16 290 inline void swap(scoped_connection &conn1, scoped_connection &conn2)
Chris@16 291 {
Chris@16 292 conn1.swap(conn2);
Chris@16 293 }
Chris@16 294 }
Chris@16 295 }
Chris@16 296
Chris@16 297 #endif // BOOST_SIGNALS2_CONNECTION_HPP