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_TRACKABLE_HPP sl@0: #define BOOST_SIGNALS_TRACKABLE_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: sl@0: namespace BOOST_SIGNALS_NAMESPACE { sl@0: // Base class for "trackable" objects that can be tracked when they are sl@0: // bound in slot target functions. When a trackable object is destroyed, sl@0: // the signal/slot connections are disconnected automatically. sl@0: class BOOST_SIGNALS_DECL trackable { sl@0: private: sl@0: static void signal_disconnected(void* obj, void* data); sl@0: sl@0: friend class detail::signal_base_impl; sl@0: friend class detail::slot_base; sl@0: void signal_connected(connection, BOOST_SIGNALS_NAMESPACE::detail::bound_object&) const; sl@0: sl@0: protected: sl@0: trackable() : connected_signals(), dying(false) {} sl@0: trackable(const trackable&) : connected_signals(), dying(false) {} sl@0: ~trackable(); sl@0: sl@0: trackable& operator=(const trackable&) sl@0: { sl@0: connected_signals.clear(); sl@0: return *this; sl@0: } sl@0: sl@0: private: sl@0: typedef std::list connection_list; sl@0: typedef connection_list::iterator connection_iterator; sl@0: sl@0: // List of connections that this object is part of sl@0: mutable connection_list connected_signals; sl@0: sl@0: // True when the object is being destroyed sl@0: mutable bool dying; sl@0: }; sl@0: sl@0: namespace detail { sl@0: template struct truth {}; sl@0: sl@0: // A visitor that adds each trackable object to a vector sl@0: class bound_objects_visitor { sl@0: public: sl@0: bound_objects_visitor(std::vector& v) : sl@0: bound_objects(v) sl@0: { sl@0: } sl@0: sl@0: template sl@0: void operator()(const T& t) const sl@0: { sl@0: decode(t, 0); sl@0: } sl@0: sl@0: private: sl@0: // decode() decides between a reference wrapper and anything else sl@0: template sl@0: void decode(const reference_wrapper& t, int) const sl@0: { sl@0: add_if_trackable(t.get_pointer()); sl@0: } sl@0: sl@0: template sl@0: void decode(const T& t, long) const sl@0: { sl@0: typedef truth<(is_pointer::value)> is_a_pointer; sl@0: maybe_get_pointer(t, is_a_pointer()); sl@0: } sl@0: sl@0: // maybe_get_pointer() decides between a pointer and a non-pointer sl@0: template sl@0: void maybe_get_pointer(const T& t, truth) const sl@0: { sl@0: add_if_trackable(t); sl@0: } sl@0: sl@0: template sl@0: void maybe_get_pointer(const T& t, truth) const sl@0: { sl@0: // Take the address of this object, because the object itself may be sl@0: // trackable sl@0: add_if_trackable(boost::addressof(t)); sl@0: } sl@0: sl@0: // add_if_trackable() adds trackable objects to the list of bound objects sl@0: inline void add_if_trackable(const trackable* b) const sl@0: { sl@0: if (b) { sl@0: bound_objects.push_back(b); sl@0: } sl@0: } sl@0: sl@0: inline void add_if_trackable(const void*) const sl@0: { sl@0: } sl@0: sl@0: template sl@0: inline void add_if_trackable(R (*)()) const sl@0: { sl@0: } sl@0: sl@0: template sl@0: inline void add_if_trackable(R (*)(T1)) const sl@0: { sl@0: } sl@0: sl@0: template sl@0: inline void add_if_trackable(R (*)(T1, T2)) const sl@0: { sl@0: } sl@0: sl@0: template sl@0: inline void add_if_trackable(R (*)(T1, T2, T3)) const sl@0: { sl@0: } sl@0: sl@0: template sl@0: inline void add_if_trackable(R (*)(T1, T2, T3, T4)) const sl@0: { sl@0: } sl@0: sl@0: template sl@0: inline void add_if_trackable(R (*)(T1, T2, T3, T4, T5)) const sl@0: { sl@0: } sl@0: sl@0: template sl@0: inline void add_if_trackable(R (*)(T1, T2, T3, T4, T5, T6)) const sl@0: { sl@0: } sl@0: sl@0: template sl@0: inline void add_if_trackable(R (*)(T1, T2, T3, T4, T5, T6, T7)) const sl@0: { sl@0: } sl@0: sl@0: template sl@0: inline void add_if_trackable(R (*)(T1, T2, T3, T4, T5, T6, T7, T8)) const sl@0: { sl@0: } sl@0: sl@0: template sl@0: inline void sl@0: add_if_trackable(R (*)(T1, T2, T3, T4, T5, T6, T7, T8, T9)) const sl@0: { sl@0: } sl@0: sl@0: template sl@0: inline void sl@0: add_if_trackable(R (*)(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10)) const sl@0: { sl@0: } sl@0: sl@0: std::vector& bound_objects; sl@0: }; sl@0: } // end namespace detail sl@0: } // end namespace BOOST_SIGNALS_NAMESPACE sl@0: 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_TRACKABLE_HPP