1 // Boost.Signals library 2 3 // Copyright Douglas Gregor 2001-2004. Use, modification and 4 // distribution is subject to the Boost Software License, Version 5 // 1.0. (See accompanying file LICENSE_1_0.txt or copy at 6 // http://www.boost.org/LICENSE_1_0.txt) 7 8 // For more information, see http://www.boost.org 9 10 #ifndef BOOST_SIGNALS_SLOT_HEADER 11 #define BOOST_SIGNALS_SLOT_HEADER 12 13 #include <boost/signals/detail/signals_common.hpp> 14 #include <boost/signals/connection.hpp> 15 #include <boost/signals/trackable.hpp> 16 #include <boost/visit_each.hpp> 17 #include <boost/shared_ptr.hpp> 18 #include <cassert> 19 20 #ifdef BOOST_HAS_ABI_HEADERS 21 # include BOOST_ABI_PREFIX 22 #endif 23 24 namespace boost { 25 namespace BOOST_SIGNALS_NAMESPACE { 26 namespace detail { 27 class BOOST_SIGNALS_DECL slot_base { 28 // We would have to enumerate all of the signalN classes here as 29 // friends to make this private (as it otherwise should be). We can't 30 // name all of them because we don't know how many there are. 31 public: 32 struct data_t { 33 std::vector<const trackable*> bound_objects; 34 connection watch_bound_objects; 35 }; get_data() const36 shared_ptr<data_t> get_data() const { return data; } 37 38 // Get the set of bound objects get_bound_objects() const39 std::vector<const trackable*>& get_bound_objects() const 40 { return data->bound_objects; } 41 42 // Determine if this slot is still "active", i.e., all of the bound 43 // objects still exist is_active() const44 bool is_active() const 45 { return data->watch_bound_objects.connected(); } 46 47 protected: 48 // Create a connection for this slot 49 void create_connection(); 50 51 shared_ptr<data_t> data; 52 53 private: bound_object_destructed(void *,void *)54 static void bound_object_destructed(void*, void*) {} 55 }; 56 } // end namespace detail 57 58 // Get the slot so that it can be copied 59 template<typename F> 60 reference_wrapper<const F> get_invocable_slot(const F & f,BOOST_SIGNALS_NAMESPACE::detail::signal_tag)61 get_invocable_slot(const F& f, BOOST_SIGNALS_NAMESPACE::detail::signal_tag) 62 { return reference_wrapper<const F>(f); } 63 64 template<typename F> 65 const F& get_invocable_slot(const F & f,BOOST_SIGNALS_NAMESPACE::detail::reference_tag)66 get_invocable_slot(const F& f, BOOST_SIGNALS_NAMESPACE::detail::reference_tag) 67 { return f; } 68 69 template<typename F> 70 const F& get_invocable_slot(const F & f,BOOST_SIGNALS_NAMESPACE::detail::value_tag)71 get_invocable_slot(const F& f, BOOST_SIGNALS_NAMESPACE::detail::value_tag) 72 { return f; } 73 74 // Get the slot so that it can be inspected for trackable objects 75 template<typename F> 76 const F& get_inspectable_slot(const F & f,BOOST_SIGNALS_NAMESPACE::detail::signal_tag)77 get_inspectable_slot(const F& f, BOOST_SIGNALS_NAMESPACE::detail::signal_tag) 78 { return f; } 79 80 template<typename F> 81 const F& get_inspectable_slot(const reference_wrapper<F> & f,BOOST_SIGNALS_NAMESPACE::detail::reference_tag)82 get_inspectable_slot(const reference_wrapper<F>& f, BOOST_SIGNALS_NAMESPACE::detail::reference_tag) 83 { return f.get(); } 84 85 template<typename F> 86 const F& get_inspectable_slot(const F & f,BOOST_SIGNALS_NAMESPACE::detail::value_tag)87 get_inspectable_slot(const F& f, BOOST_SIGNALS_NAMESPACE::detail::value_tag) 88 { return f; } 89 90 // Determines the type of the slot - is it a signal, a reference to a 91 // slot or just a normal slot. 92 template<typename F> 93 typename BOOST_SIGNALS_NAMESPACE::detail::get_slot_tag<F>::type tag_type(const F &)94 tag_type(const F&) 95 { 96 typedef typename BOOST_SIGNALS_NAMESPACE::detail::get_slot_tag<F>::type 97 the_tag_type; 98 the_tag_type tag = the_tag_type(); 99 return tag; 100 } 101 102 } // end namespace BOOST_SIGNALS_NAMESPACE 103 104 template<typename SlotFunction> 105 class slot : public BOOST_SIGNALS_NAMESPACE::detail::slot_base { 106 typedef BOOST_SIGNALS_NAMESPACE::detail::slot_base inherited; 107 typedef typename inherited::data_t data_t; 108 109 public: 110 template<typename F> slot(const F & f)111 slot(const F& f) : slot_function(BOOST_SIGNALS_NAMESPACE::get_invocable_slot(f, BOOST_SIGNALS_NAMESPACE::tag_type(f))) 112 { 113 this->data.reset(new data_t); 114 115 // Visit each of the bound objects and store them for later use 116 // An exception thrown here will allow the basic_connection to be 117 // destroyed when this goes out of scope, and no other connections 118 // have been made. 119 BOOST_SIGNALS_NAMESPACE::detail::bound_objects_visitor 120 do_bind(this->data->bound_objects); 121 visit_each(do_bind, 122 BOOST_SIGNALS_NAMESPACE::get_inspectable_slot 123 (f, BOOST_SIGNALS_NAMESPACE::tag_type(f))); 124 create_connection(); 125 } 126 127 #ifdef __BORLANDC__ 128 template<typename F> slot(F * f)129 slot(F* f) : slot_function(f) 130 { 131 this->data.reset(new data_t); 132 create_connection(); 133 } 134 #endif // __BORLANDC__ 135 136 // We would have to enumerate all of the signalN classes here as friends 137 // to make this private (as it otherwise should be). We can't name all of 138 // them because we don't know how many there are. 139 public: 140 // Get the slot function to call the actual slot get_slot_function() const141 const SlotFunction& get_slot_function() const { return slot_function; } 142 release() const143 void release() const { data->watch_bound_objects.set_controlling(false); } 144 145 private: 146 slot(); // no default constructor 147 slot& operator=(const slot&); // no assignment operator 148 149 SlotFunction slot_function; 150 }; 151 } // end namespace boost 152 153 #ifdef BOOST_HAS_ABI_HEADERS 154 # include BOOST_ABI_SUFFIX 155 #endif 156 157 #endif // BOOST_SIGNALS_SLOT_HEADER 158