123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246 |
- /*
- 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)
- {}
- ~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;
- }
- 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
|