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 |
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 | }; |
36 | shared_ptr<data_t> get_data() const { return data; } |
37 | |
38 | // Get the set of bound objects |
39 | 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 |
44 | 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: |
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> |
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& |
66 | get_invocable_slot(const F& f, BOOST_SIGNALS_NAMESPACE::detail::reference_tag) |
67 | { return f; } |
68 | |
69 | template<typename F> |
70 | const F& |
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& |
77 | get_inspectable_slot(const F& f, BOOST_SIGNALS_NAMESPACE::detail::signal_tag) |
78 | { return f; } |
79 | |
80 | template<typename F> |
81 | const F& |
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& |
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 |
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> |
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> |
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 |
141 | const SlotFunction& get_slot_function() const { return slot_function; } |
142 | |
143 | 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 | |