Chris@16: // Boost.Signals library Chris@16: Chris@16: // Copyright Douglas Gregor 2001-2004. Use, modification and Chris@16: // distribution is subject to the Boost Software License, Version Chris@16: // 1.0. (See accompanying file LICENSE_1_0.txt or copy at Chris@16: // http://www.boost.org/LICENSE_1_0.txt) Chris@16: Chris@16: // For more information, see http://www.boost.org Chris@16: Chris@16: #ifndef BOOST_SIGNALS_CONNECTION_HPP Chris@16: #define BOOST_SIGNALS_CONNECTION_HPP Chris@16: Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: Chris@16: #ifdef BOOST_HAS_ABI_HEADERS Chris@16: # include BOOST_ABI_PREFIX Chris@16: #endif Chris@16: Chris@16: namespace boost { Chris@16: namespace BOOST_SIGNALS_NAMESPACE { Chris@16: class trackable; Chris@16: Chris@16: namespace detail { Chris@16: // Represents an object that has been bound as part of a slot, and how Chris@16: // to notify that object of a disconnect Chris@16: struct bound_object { Chris@16: void* obj; Chris@16: void* data; Chris@16: void (*disconnect)(void*, void*); Chris@16: Chris@16: bool operator==(const bound_object& other) const Chris@16: { return obj == other.obj && data == other.data; } Chris@16: bool operator<(const bound_object& other) const Chris@16: { return obj < other.obj; } Chris@16: Chris@16: // To support intel 80 compiler, 2004/03/18 (Mark Rodgers) Chris@16: bool operator!=(const bound_object& other) const Chris@16: { return !(*this==other); } Chris@16: bool operator>(const bound_object& other) const Chris@16: { return !(*this < other); } Chris@16: }; Chris@16: Chris@16: // Describes the connection between a signal and the objects that are Chris@16: // bound for a specific slot. Enables notification of the signal and the Chris@16: // slots when a disconnect is requested. Chris@16: struct basic_connection { Chris@16: void* signal; Chris@16: void* signal_data; Chris@16: void (*signal_disconnect)(void*, void*); Chris@16: bool blocked_; Chris@16: Chris@16: std::list bound_objects; Chris@16: }; Chris@16: } // end namespace detail Chris@16: Chris@16: // The user may freely pass around the "connection" object and terminate Chris@16: // the connection at any time using disconnect(). Chris@16: class BOOST_SIGNALS_DECL connection : Chris@16: private less_than_comparable1, Chris@16: private equality_comparable1 Chris@16: { Chris@16: public: Chris@16: connection() : con(), controlling_connection(false) {} Chris@16: connection(const connection&); Chris@16: ~connection(); Chris@16: Chris@16: // Block he connection: if the connection is still active, there Chris@16: // will be no notification Chris@16: void block(bool should_block = true) { con->blocked_ = should_block; } Chris@16: void unblock() { con->blocked_ = false; } Chris@16: bool blocked() const { return !connected() || con->blocked_; } Chris@16: Chris@16: // Disconnect the signal and slot, if they are connected Chris@16: void disconnect() const; Chris@16: Chris@16: // Returns true if the signal and slot are connected Chris@16: bool connected() const { return con.get() && con->signal_disconnect; } Chris@16: Chris@16: // Comparison of connections Chris@16: bool operator==(const connection& other) const; Chris@16: bool operator<(const connection& other) const; Chris@16: Chris@16: // Connection assignment Chris@16: connection& operator=(const connection& other) ; Chris@16: Chris@16: // Swap connections Chris@16: void swap(connection& other); Chris@16: Chris@16: public: // TBD: CHANGE THIS Chris@16: // Set whether this connection object is controlling or not Chris@16: void set_controlling(bool control = true) Chris@16: { controlling_connection = control; } Chris@16: Chris@16: shared_ptr Chris@16: get_connection() const Chris@16: { return con; } Chris@16: Chris@16: private: Chris@16: friend class detail::signal_base_impl; Chris@16: friend class detail::slot_base; Chris@16: friend class trackable; Chris@16: Chris@16: // Reset this connection to refer to a different actual connection Chris@16: void reset(BOOST_SIGNALS_NAMESPACE::detail::basic_connection*); Chris@16: Chris@16: // Add a bound object to this connection (not for users) Chris@16: void add_bound_object(const BOOST_SIGNALS_NAMESPACE::detail::bound_object& b); Chris@16: Chris@16: friend class BOOST_SIGNALS_NAMESPACE::detail::bound_objects_visitor; Chris@16: Chris@16: // Pointer to the actual contents of the connection Chris@16: shared_ptr con; Chris@16: Chris@16: // True if the destruction of this connection object should disconnect Chris@16: bool controlling_connection; Chris@16: }; Chris@16: Chris@16: // Similar to connection, but will disconnect the connection when it is Chris@16: // destroyed unless release() has been called. Chris@16: class BOOST_SIGNALS_DECL scoped_connection : public connection { Chris@16: public: Chris@16: scoped_connection() : connection(), released(false) {} Chris@16: scoped_connection(const connection&); Chris@16: scoped_connection(const scoped_connection&); Chris@16: ~scoped_connection(); Chris@16: Chris@16: connection release(); Chris@16: Chris@16: void swap(scoped_connection&); Chris@16: Chris@16: scoped_connection& operator=(const connection&); Chris@16: scoped_connection& operator=(const scoped_connection&); Chris@16: Chris@16: private: Chris@16: bool released; Chris@16: }; Chris@16: Chris@16: namespace detail { Chris@16: struct connection_slot_pair { Chris@16: connection first; Chris@16: any second; Chris@16: Chris@16: connection_slot_pair() {} Chris@16: Chris@16: connection_slot_pair(const connection& c, const any& a) Chris@16: : first(c), second(a) Chris@16: { Chris@16: } Chris@16: Chris@16: // Dummys to allow explicit instantiation to work Chris@16: bool operator==(const connection_slot_pair&) const { return false; } Chris@16: bool operator<(const connection_slot_pair&) const { return false;} Chris@16: }; Chris@16: Chris@16: // Determines if the underlying connection is disconnected Chris@16: struct is_disconnected { Chris@16: typedef connection_slot_pair argument_type; Chris@16: typedef bool result_type; Chris@16: Chris@16: inline bool operator()(const argument_type& c) const Chris@16: { Chris@16: return !c.first.connected(); Chris@16: } Chris@16: }; Chris@16: Chris@16: // Determines if the underlying connection is callable, ie if Chris@16: // it is connected and not blocked Chris@16: struct is_callable { Chris@16: typedef connection_slot_pair argument_type; Chris@16: typedef bool result_type; Chris@16: Chris@16: inline bool operator()(const argument_type& c) const Chris@16: { Chris@16: return c.first.connected() && !c.first.blocked() ; Chris@16: } Chris@16: }; Chris@16: Chris@16: // Autodisconnects the bound object when it is destroyed unless the Chris@16: // release method is invoked. Chris@16: class auto_disconnect_bound_object { Chris@16: public: Chris@16: auto_disconnect_bound_object(const bound_object& b) : Chris@16: binding(b), auto_disconnect(true) Chris@16: { Chris@16: } Chris@16: Chris@16: ~auto_disconnect_bound_object() Chris@16: { Chris@16: if (auto_disconnect) Chris@16: binding.disconnect(binding.obj, binding.data); Chris@16: } Chris@16: Chris@16: void release() { auto_disconnect = false; } Chris@16: Chris@16: private: Chris@16: bound_object binding; Chris@16: bool auto_disconnect; Chris@16: }; Chris@16: } // end namespace detail Chris@16: } // end namespace BOOST_SIGNALS_NAMESPACE Chris@16: } // end namespace boost Chris@16: Chris@16: #ifdef BOOST_HAS_ABI_HEADERS Chris@16: # include BOOST_ABI_SUFFIX Chris@16: #endif Chris@16: Chris@16: #endif // BOOST_SIGNALS_CONNECTION_HPP