diff options
Diffstat (limited to '3rdParty/Boost/src/boost/signals2/connection.hpp')
-rw-r--r-- | 3rdParty/Boost/src/boost/signals2/connection.hpp | 297 |
1 files changed, 297 insertions, 0 deletions
diff --git a/3rdParty/Boost/src/boost/signals2/connection.hpp b/3rdParty/Boost/src/boost/signals2/connection.hpp new file mode 100644 index 0000000..0ab4dac --- /dev/null +++ b/3rdParty/Boost/src/boost/signals2/connection.hpp @@ -0,0 +1,297 @@ +/* + boost::signals2::connection provides a handle to a signal/slot connection. + + Author: Frank Mori Hess <fmhess@users.sourceforge.net> + Begin: 2007-01-23 +*/ +// Copyright Frank Mori Hess 2007-2008. +// Distributed under the Boost Software License, Version +// 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org/libs/signals2 for library home page. + +#ifndef BOOST_SIGNALS2_CONNECTION_HPP +#define BOOST_SIGNALS2_CONNECTION_HPP + +#include <boost/function.hpp> +#include <boost/mpl/bool.hpp> +#include <boost/noncopyable.hpp> +#include <boost/shared_ptr.hpp> +#include <boost/signals2/detail/null_output_iterator.hpp> +#include <boost/signals2/detail/unique_lock.hpp> +#include <boost/signals2/slot.hpp> +#include <boost/weak_ptr.hpp> + +namespace boost +{ + namespace signals2 + { + extern inline void null_deleter(const void*) {} + namespace detail + { + class connection_body_base + { + public: + connection_body_base(): + _connected(true) + { + } + virtual ~connection_body_base() {} + void disconnect() + { + unique_lock<connection_body_base> local_lock(*this); + nolock_disconnect(); + } + void nolock_disconnect() + { + _connected = false; + } + virtual bool connected() const = 0; + shared_ptr<void> get_blocker() + { + unique_lock<connection_body_base> local_lock(*this); + shared_ptr<void> blocker = _weak_blocker.lock(); + if(blocker == shared_ptr<void>()) + { + blocker.reset(this, &null_deleter); + _weak_blocker = blocker; + } + return blocker; + } + bool blocked() const + { + return !_weak_blocker.expired(); + } + bool nolock_nograb_blocked() const + { + return nolock_nograb_connected() == false || blocked(); + } + bool nolock_nograb_connected() const {return _connected;} + // expose part of Lockable concept of mutex + virtual void lock() = 0; + virtual void unlock() = 0; + + protected: + + mutable bool _connected; + weak_ptr<void> _weak_blocker; + }; + + template<typename GroupKey, typename SlotType, typename Mutex> + class connection_body: public connection_body_base + { + public: + typedef Mutex mutex_type; + connection_body(const SlotType &slot_in): + slot(slot_in) + { + } + virtual ~connection_body() {} + virtual bool connected() const + { + unique_lock<mutex_type> local_lock(_mutex); + nolock_grab_tracked_objects(detail::null_output_iterator()); + return nolock_nograb_connected(); + } + const GroupKey& group_key() const {return _group_key;} + void set_group_key(const GroupKey &key) {_group_key = key;} + bool nolock_slot_expired() const + { + bool expired = slot.expired(); + if(expired == true) + { + _connected = false; + } + return expired; + } + template<typename OutputIterator> + void nolock_grab_tracked_objects(OutputIterator inserter) const + { + slot_base::tracked_container_type::const_iterator it; + for(it = slot.tracked_objects().begin(); + it != slot.tracked_objects().end(); + ++it) + { + void_shared_ptr_variant locked_object + ( + apply_visitor + ( + detail::lock_weak_ptr_visitor(), + *it + ) + ); + if(apply_visitor(detail::expired_weak_ptr_visitor(), *it)) + { + _connected = false; + return; + } + *inserter++ = locked_object; + } + } + // expose Lockable concept of mutex + virtual void lock() + { + _mutex.lock(); + } + virtual void unlock() + { + _mutex.unlock(); + } + SlotType slot; + private: + mutable mutex_type _mutex; + GroupKey _group_key; + }; + } + + class shared_connection_block; + + class connection + { + public: + friend class shared_connection_block; + + connection() {} + connection(const connection &other): _weak_connection_body(other._weak_connection_body) + {} + connection(const boost::weak_ptr<detail::connection_body_base> &connectionBody): + _weak_connection_body(connectionBody) + {} + + // move support +#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + connection(connection && other): _weak_connection_body(std::move(other._weak_connection_body)) + { + // make sure other is reset, in case it is a scoped_connection (so it + // won't disconnect on destruction after being moved away from). + other._weak_connection_body.reset(); + } + connection & operator=(connection && other) + { + if(&other == this) return *this; + _weak_connection_body = std::move(other._weak_connection_body); + // make sure other is reset, in case it is a scoped_connection (so it + // won't disconnect on destruction after being moved away from). + other._weak_connection_body.reset(); + return *this; + } +#endif // !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + connection & operator=(const connection & other) + { + if(&other == this) return *this; + _weak_connection_body = other._weak_connection_body; + return *this; + } + + ~connection() {} + void disconnect() const + { + boost::shared_ptr<detail::connection_body_base> connectionBody(_weak_connection_body.lock()); + if(connectionBody == 0) return; + connectionBody->disconnect(); + } + bool connected() const + { + boost::shared_ptr<detail::connection_body_base> connectionBody(_weak_connection_body.lock()); + if(connectionBody == 0) return false; + return connectionBody->connected(); + } + bool blocked() const + { + boost::shared_ptr<detail::connection_body_base> connectionBody(_weak_connection_body.lock()); + if(connectionBody == 0) return true; + return connectionBody->blocked(); + } + bool operator==(const connection& other) const + { + boost::shared_ptr<detail::connection_body_base> connectionBody(_weak_connection_body.lock()); + boost::shared_ptr<detail::connection_body_base> otherConnectionBody(other._weak_connection_body.lock()); + return connectionBody == otherConnectionBody; + } + bool operator!=(const connection& other) const + { + return !(*this == other); + } + bool operator<(const connection& other) const + { + boost::shared_ptr<detail::connection_body_base> connectionBody(_weak_connection_body.lock()); + boost::shared_ptr<detail::connection_body_base> otherConnectionBody(other._weak_connection_body.lock()); + return connectionBody < otherConnectionBody; + } + void swap(connection &other) + { + using std::swap; + swap(_weak_connection_body, other._weak_connection_body); + } + protected: + + boost::weak_ptr<detail::connection_body_base> _weak_connection_body; + }; + inline void swap(connection &conn1, connection &conn2) + { + conn1.swap(conn2); + } + + class scoped_connection: public connection + { + public: + scoped_connection() {} + scoped_connection(const connection &other): + connection(other) + {} + ~scoped_connection() + { + disconnect(); + } + scoped_connection& operator=(const connection &rhs) + { + disconnect(); + connection::operator=(rhs); + return *this; + } + + // move support +#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + scoped_connection(scoped_connection && other): connection(std::move(other)) + { + } + scoped_connection(connection && other): connection(std::move(other)) + { + } + scoped_connection & operator=(scoped_connection && other) + { + if(&other == this) return *this; + disconnect(); + connection::operator=(std::move(other)); + return *this; + } + scoped_connection & operator=(connection && other) + { + if(&other == this) return *this; + disconnect(); + connection::operator=(std::move(other)); + return *this; + } +#endif // !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + + connection release() + { + connection conn(_weak_connection_body); + _weak_connection_body.reset(); + return conn; + } + private: + scoped_connection(const scoped_connection &other); + scoped_connection& operator=(const scoped_connection &rhs); + }; + // Sun 5.9 compiler doesn't find the swap for base connection class when + // arguments are scoped_connection, so we provide this explicitly. + inline void swap(scoped_connection &conn1, scoped_connection &conn2) + { + conn1.swap(conn2); + } + } +} + +#endif // BOOST_SIGNALS2_CONNECTION_HPP |