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