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_SLOT_HEADER sl@0: #define BOOST_SIGNALS_SLOT_HEADER sl@0: 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: namespace detail { sl@0: class BOOST_SIGNALS_DECL slot_base { sl@0: // We would have to enumerate all of the signalN classes here as sl@0: // friends to make this private (as it otherwise should be). We can't sl@0: // name all of them because we don't know how many there are. sl@0: public: sl@0: struct data_t { sl@0: std::vector bound_objects; sl@0: connection watch_bound_objects; sl@0: }; sl@0: shared_ptr get_data() const { return data; } sl@0: sl@0: // Get the set of bound objects sl@0: std::vector& get_bound_objects() const sl@0: { return data->bound_objects; } sl@0: sl@0: // Determine if this slot is still "active", i.e., all of the bound sl@0: // objects still exist sl@0: bool is_active() const sl@0: { return data->watch_bound_objects.connected(); } sl@0: sl@0: protected: sl@0: // Create a connection for this slot sl@0: void create_connection(); sl@0: sl@0: shared_ptr data; sl@0: sl@0: private: sl@0: static void bound_object_destructed(void*, void*) {} sl@0: }; sl@0: } // end namespace detail sl@0: sl@0: // Get the slot so that it can be copied sl@0: template sl@0: reference_wrapper sl@0: get_invocable_slot(const F& f, BOOST_SIGNALS_NAMESPACE::detail::signal_tag) sl@0: { return reference_wrapper(f); } sl@0: sl@0: template sl@0: const F& sl@0: get_invocable_slot(const F& f, BOOST_SIGNALS_NAMESPACE::detail::reference_tag) sl@0: { return f; } sl@0: sl@0: template sl@0: const F& sl@0: get_invocable_slot(const F& f, BOOST_SIGNALS_NAMESPACE::detail::value_tag) sl@0: { return f; } sl@0: sl@0: // Get the slot so that it can be inspected for trackable objects sl@0: template sl@0: const F& sl@0: get_inspectable_slot(const F& f, BOOST_SIGNALS_NAMESPACE::detail::signal_tag) sl@0: { return f; } sl@0: sl@0: template sl@0: const F& sl@0: get_inspectable_slot(const reference_wrapper& f, BOOST_SIGNALS_NAMESPACE::detail::reference_tag) sl@0: { return f.get(); } sl@0: sl@0: template sl@0: const F& sl@0: get_inspectable_slot(const F& f, BOOST_SIGNALS_NAMESPACE::detail::value_tag) sl@0: { return f; } sl@0: sl@0: // Determines the type of the slot - is it a signal, a reference to a sl@0: // slot or just a normal slot. sl@0: template sl@0: typename BOOST_SIGNALS_NAMESPACE::detail::get_slot_tag::type sl@0: tag_type(const F&) sl@0: { sl@0: typedef typename BOOST_SIGNALS_NAMESPACE::detail::get_slot_tag::type sl@0: the_tag_type; sl@0: the_tag_type tag = the_tag_type(); sl@0: return tag; sl@0: } sl@0: sl@0: } // end namespace BOOST_SIGNALS_NAMESPACE sl@0: sl@0: template sl@0: class slot : public BOOST_SIGNALS_NAMESPACE::detail::slot_base { sl@0: typedef BOOST_SIGNALS_NAMESPACE::detail::slot_base inherited; sl@0: typedef typename inherited::data_t data_t; sl@0: sl@0: public: sl@0: template sl@0: slot(const F& f) : slot_function(BOOST_SIGNALS_NAMESPACE::get_invocable_slot(f, BOOST_SIGNALS_NAMESPACE::tag_type(f))) sl@0: { sl@0: this->data.reset(new data_t); sl@0: sl@0: // Visit each of the bound objects and store them for later use sl@0: // An exception thrown here will allow the basic_connection to be sl@0: // destroyed when this goes out of scope, and no other connections sl@0: // have been made. sl@0: BOOST_SIGNALS_NAMESPACE::detail::bound_objects_visitor sl@0: do_bind(this->data->bound_objects); sl@0: visit_each(do_bind, sl@0: BOOST_SIGNALS_NAMESPACE::get_inspectable_slot sl@0: (f, BOOST_SIGNALS_NAMESPACE::tag_type(f))); sl@0: create_connection(); sl@0: } sl@0: sl@0: #ifdef __BORLANDC__ sl@0: template sl@0: slot(F* f) : slot_function(f) sl@0: { sl@0: this->data.reset(new data_t); sl@0: create_connection(); sl@0: } sl@0: #endif // __BORLANDC__ sl@0: sl@0: // We would have to enumerate all of the signalN classes here as friends sl@0: // to make this private (as it otherwise should be). We can't name all of sl@0: // them because we don't know how many there are. sl@0: public: sl@0: // Get the slot function to call the actual slot sl@0: const SlotFunction& get_slot_function() const { return slot_function; } sl@0: sl@0: void release() const { data->watch_bound_objects.set_controlling(false); } sl@0: sl@0: private: sl@0: slot(); // no default constructor sl@0: slot& operator=(const slot&); // no assignment operator sl@0: sl@0: SlotFunction slot_function; 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_SLOT_HEADER