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