comparison DEPENDENCIES/generic/include/boost/signals/signal_template.hpp @ 16:2665513ce2d3

Add boost headers
author Chris Cannam
date Tue, 05 Aug 2014 11:11:38 +0100
parents
children c530137014c0
comparison
equal deleted inserted replaced
15:663ca0da4350 16:2665513ce2d3
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 // This file intentionally does not have include guards, because it is meant
11 // to be included multiple times (one for each signalN class). The
12 // BOOST_SIGNALS_SIGNAL_TEMPLATE_HEADER_INCLUDED macro merely serves to
13 // suppress reinclusion of the files that this header depends on.
14
15 #ifndef BOOST_SIGNALS_SIGNAL_TEMPLATE_HEADER_INCLUDED
16 #define BOOST_SIGNALS_SIGNAL_TEMPLATE_HEADER_INCLUDED
17 # include <boost/config.hpp>
18 # include <boost/signals/connection.hpp>
19 # include <boost/utility.hpp>
20 # include <boost/ref.hpp>
21 # include <boost/signals/slot.hpp>
22 # include <boost/last_value.hpp>
23 # include <boost/signals/detail/signal_base.hpp>
24 # include <boost/signals/detail/slot_call_iterator.hpp>
25 # include <boost/mpl/bool.hpp>
26 # include <boost/type_traits/is_convertible.hpp>
27 # include <cassert>
28 # include <functional>
29 # include <memory>
30 #endif // !BOOST_SIGNALS_SIGNAL_TEMPLATE_HEADER_INCLUDED
31
32 #ifdef BOOST_HAS_ABI_HEADERS
33 # include BOOST_ABI_PREFIX
34 #endif
35
36 // Include the appropriate functionN header
37 #define BOOST_SIGNAL_FUNCTION_N_HEADER BOOST_JOIN(<boost/function/function,BOOST_SIGNALS_NUM_ARGS.hpp>)
38 #include BOOST_SIGNAL_FUNCTION_N_HEADER
39
40 // Determine if a comma should follow a listing of the arguments/parameters
41 #if BOOST_SIGNALS_NUM_ARGS == 0
42 # define BOOST_SIGNALS_COMMA_IF_NONZERO_ARGS
43 #else
44 # define BOOST_SIGNALS_COMMA_IF_NONZERO_ARGS ,
45 #endif // BOOST_SIGNALS_NUM_ARGS > 0
46
47 // Define class names used
48 #define BOOST_SIGNALS_SIGNAL BOOST_JOIN(signal,BOOST_SIGNALS_NUM_ARGS)
49 #define BOOST_SIGNALS_FUNCTION BOOST_JOIN(function,BOOST_SIGNALS_NUM_ARGS)
50 #define BOOST_SIGNALS_ARGS_STRUCT BOOST_JOIN(args,BOOST_SIGNALS_NUM_ARGS)
51 #define BOOST_SIGNALS_CALL_BOUND BOOST_JOIN(call_bound,BOOST_SIGNALS_NUM_ARGS)
52
53 // Define commonly-used instantiations
54 #define BOOST_SIGNALS_ARGS_STRUCT_INST \
55 BOOST_SIGNALS_NAMESPACE::detail::BOOST_SIGNALS_ARGS_STRUCT<BOOST_SIGNALS_TEMPLATE_ARGS>
56
57 namespace boost {
58 namespace BOOST_SIGNALS_NAMESPACE {
59 namespace detail {
60 // Holds the arguments for a bound slot call in a single place
61 template<BOOST_SIGNALS_TEMPLATE_PARMS
62 BOOST_SIGNALS_COMMA_IF_NONZERO_ARGS
63 typename Dummy = int>
64 struct BOOST_SIGNALS_ARGS_STRUCT {
65 BOOST_SIGNALS_ARGS_STRUCT(BOOST_SIGNALS_COPY_PARMS)
66 BOOST_SIGNALS_INIT_ARGS
67 {
68 }
69
70 BOOST_SIGNALS_ARGS_AS_MEMBERS
71 };
72
73 // Function object that calls the function object given to it, passing
74 // the bound arguments along to that underlying function object
75 template<typename R>
76 struct BOOST_SIGNALS_CALL_BOUND {
77 template<BOOST_SIGNALS_TEMPLATE_PARMS
78 BOOST_SIGNALS_COMMA_IF_NONZERO_ARGS
79 typename F>
80 struct caller {
81 typedef BOOST_SIGNALS_ARGS_STRUCT<BOOST_SIGNALS_TEMPLATE_ARGS>*
82 args_type;
83
84 args_type args;
85
86 typedef R result_type;
87
88 caller() {}
89 caller(args_type a) : args(a) {}
90
91 template<typename Pair>
92 R operator()(const Pair& slot) const
93 {
94 F* target = const_cast<F*>(unsafe_any_cast<F>(&slot.second));
95 return (*target)(BOOST_SIGNALS_BOUND_ARGS);
96 }
97 };
98 };
99
100 template<>
101 struct BOOST_SIGNALS_CALL_BOUND<void> {
102 template<BOOST_SIGNALS_TEMPLATE_PARMS
103 BOOST_SIGNALS_COMMA_IF_NONZERO_ARGS
104 typename F>
105 struct caller {
106 typedef BOOST_SIGNALS_ARGS_STRUCT<BOOST_SIGNALS_TEMPLATE_ARGS>*
107 args_type;
108
109 args_type args;
110
111 typedef unusable result_type;
112
113 caller(args_type a) : args(a) {}
114
115 template<typename Pair>
116 unusable operator()(const Pair& slot) const
117 {
118 F* target = const_cast<F*>(unsafe_any_cast<F>(&slot.second));
119 (*target)(BOOST_SIGNALS_BOUND_ARGS);
120 return unusable();
121 }
122 };
123 };
124 } // namespace detail
125 } // namespace BOOST_SIGNALS_NAMESPACE
126
127 // The actual signalN class
128 template<
129 typename R,
130 BOOST_SIGNALS_TEMPLATE_PARMS
131 BOOST_SIGNALS_COMMA_IF_NONZERO_ARGS
132 typename Combiner = last_value<R>,
133 typename Group = int,
134 typename GroupCompare = std::less<Group>,
135 typename SlotFunction = BOOST_SIGNALS_FUNCTION<
136 R BOOST_SIGNALS_COMMA_IF_NONZERO_ARGS
137 BOOST_SIGNALS_TEMPLATE_ARGS>
138 >
139 class BOOST_SIGNALS_SIGNAL :
140 public BOOST_SIGNALS_NAMESPACE::detail::signal_base, // management of slot list
141 public BOOST_SIGNALS_NAMESPACE::trackable // signals are trackable
142 {
143 public:
144 // The slot function type
145 typedef SlotFunction slot_function_type;
146
147 // Result type of a slot
148 typedef typename BOOST_SIGNALS_NAMESPACE::detail::slot_result_type<R>::type
149 slot_result_type;
150
151 // Argument types
152 BOOST_SIGNALS_ARG_TYPES
153
154 #if BOOST_SIGNALS_NUM_ARGS == 1
155 typedef T1 argument_type;
156 #elif BOOST_SIGNALS_NUM_ARGS == 2
157 typedef T1 first_argument_type;
158 typedef T2 second_argument_type;
159 #endif
160
161 private:
162 // The real slot name comparison object type
163 typedef BOOST_SIGNALS_NAMESPACE::detail::group_bridge_compare<GroupCompare, Group>
164 real_group_compare_type;
165
166 // The function object passed to the slot call iterator that will call
167 // the underlying slot function with its arguments bound
168 typedef BOOST_SIGNALS_NAMESPACE::detail::BOOST_SIGNALS_CALL_BOUND<R>
169 outer_bound_slot_caller;
170 typedef typename outer_bound_slot_caller::template
171 caller<BOOST_SIGNALS_TEMPLATE_ARGS
172 BOOST_SIGNALS_COMMA_IF_NONZERO_ARGS
173 slot_function_type>
174 call_bound_slot;
175
176 public:
177 // Combiner's result type
178 typedef typename Combiner::result_type result_type;
179
180 // Combiner type
181 typedef Combiner combiner_type;
182
183 // Slot type
184 typedef slot<slot_function_type> slot_type;
185
186 // Slot name type and comparison
187 typedef Group group_type;
188 typedef GroupCompare group_compare_type;
189
190 typedef BOOST_SIGNALS_NAMESPACE::detail::slot_call_iterator<
191 call_bound_slot, iterator> slot_call_iterator;
192
193 explicit
194 BOOST_SIGNALS_SIGNAL(const Combiner& c = Combiner(),
195 const GroupCompare& comp = GroupCompare()) :
196 BOOST_SIGNALS_NAMESPACE::detail::signal_base(real_group_compare_type(comp),
197 c)
198 {
199 }
200
201 // Connect a slot to this signal
202 BOOST_SIGNALS_NAMESPACE::connection
203 connect(const slot_type&,
204 BOOST_SIGNALS_NAMESPACE::connect_position at
205 = BOOST_SIGNALS_NAMESPACE::at_back);
206
207
208 BOOST_SIGNALS_NAMESPACE::connection
209 connect(const group_type&, const slot_type&,
210 BOOST_SIGNALS_NAMESPACE::connect_position at
211 = BOOST_SIGNALS_NAMESPACE::at_back);
212
213 #if BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
214 // MSVC 6.0 and 7.0 don't handle the is_convertible test well
215 void disconnect(const group_type& group)
216 {
217 impl->disconnect(group);
218 }
219 #else
220 template<typename T>
221 void disconnect(const T& t)
222 {
223 typedef mpl::bool_<(is_convertible<T, group_type>::value)> is_group;
224 this->do_disconnect(t, is_group());
225 }
226
227 private:
228 // Disconnect a named slot
229 void do_disconnect(const group_type& group, mpl::bool_<true>)
230 {
231 impl->disconnect(group);
232 }
233
234 template<typename Function>
235 void do_disconnect(const Function& f, mpl::bool_<false>)
236 {
237 // Notify the slot handling code that we are iterating through the slots
238 BOOST_SIGNALS_NAMESPACE::detail::call_notification notification(this->impl);
239
240 for (iterator i = impl->slots_.begin(); i != impl->slots_.end(); ++i) {
241 slot_function_type& s = *unsafe_any_cast<slot_function_type>(&i->second);
242 if (s == f) i->first.disconnect();
243 }
244 }
245 #endif
246
247 public:
248
249 // Emit the signal
250 result_type operator()(BOOST_SIGNALS_PARMS);
251 result_type operator()(BOOST_SIGNALS_PARMS) const;
252
253 Combiner& combiner()
254 { return *unsafe_any_cast<Combiner>(&impl->combiner_); }
255
256 const Combiner& combiner() const
257 { return *unsafe_any_cast<const Combiner>(&impl->combiner_); }
258 };
259
260 template<
261 typename R,
262 BOOST_SIGNALS_TEMPLATE_PARMS
263 BOOST_SIGNALS_COMMA_IF_NONZERO_ARGS
264 typename Combiner,
265 typename Group,
266 typename GroupCompare,
267 typename SlotFunction
268 >
269 BOOST_SIGNALS_NAMESPACE::connection
270 BOOST_SIGNALS_SIGNAL<
271 R, BOOST_SIGNALS_TEMPLATE_ARGS
272 BOOST_SIGNALS_COMMA_IF_NONZERO_ARGS
273 Combiner, Group, GroupCompare, SlotFunction
274 >::connect(const slot_type& in_slot,
275 BOOST_SIGNALS_NAMESPACE::connect_position at)
276 {
277 using boost::BOOST_SIGNALS_NAMESPACE::detail::stored_group;
278
279 // If the slot has been disconnected, just return a disconnected
280 // connection
281 if (!in_slot.is_active()) {
282 return BOOST_SIGNALS_NAMESPACE::connection();
283 }
284
285 return impl->connect_slot(in_slot.get_slot_function(), stored_group(),
286 in_slot.get_data(), at);
287 }
288
289 template<
290 typename R,
291 BOOST_SIGNALS_TEMPLATE_PARMS
292 BOOST_SIGNALS_COMMA_IF_NONZERO_ARGS
293 typename Combiner,
294 typename Group,
295 typename GroupCompare,
296 typename SlotFunction
297 >
298 BOOST_SIGNALS_NAMESPACE::connection
299 BOOST_SIGNALS_SIGNAL<
300 R, BOOST_SIGNALS_TEMPLATE_ARGS
301 BOOST_SIGNALS_COMMA_IF_NONZERO_ARGS
302 Combiner, Group, GroupCompare, SlotFunction
303 >::connect(const group_type& group,
304 const slot_type& in_slot,
305 BOOST_SIGNALS_NAMESPACE::connect_position at)
306 {
307 // If the slot has been disconnected, just return a disconnected
308 // connection
309 if (!in_slot.is_active()) {
310 return BOOST_SIGNALS_NAMESPACE::connection();
311 }
312
313 return impl->connect_slot(in_slot.get_slot_function(), group,
314 in_slot.get_data(), at);
315 }
316
317 template<
318 typename R,
319 BOOST_SIGNALS_TEMPLATE_PARMS
320 BOOST_SIGNALS_COMMA_IF_NONZERO_ARGS
321 typename Combiner,
322 typename Group,
323 typename GroupCompare,
324 typename SlotFunction
325 >
326 typename BOOST_SIGNALS_SIGNAL<
327 R, BOOST_SIGNALS_TEMPLATE_ARGS
328 BOOST_SIGNALS_COMMA_IF_NONZERO_ARGS
329 Combiner, Group, GroupCompare, SlotFunction>::result_type
330 BOOST_SIGNALS_SIGNAL<
331 R, BOOST_SIGNALS_TEMPLATE_ARGS
332 BOOST_SIGNALS_COMMA_IF_NONZERO_ARGS
333 Combiner, Group, GroupCompare, SlotFunction
334 >::operator()(BOOST_SIGNALS_PARMS)
335 {
336 // Notify the slot handling code that we are making a call
337 BOOST_SIGNALS_NAMESPACE::detail::call_notification notification(this->impl);
338
339 // Construct a function object that will call the underlying slots
340 // with the given arguments.
341 #if BOOST_SIGNALS_NUM_ARGS == 0
342 BOOST_SIGNALS_ARGS_STRUCT_INST args;
343 #else
344 BOOST_SIGNALS_ARGS_STRUCT_INST args(BOOST_SIGNALS_ARGS);
345 #endif // BOOST_SIGNALS_NUM_ARGS > 0
346 call_bound_slot f(&args);
347
348 typedef typename call_bound_slot::result_type call_result_type;
349 optional<call_result_type> cache;
350 // Let the combiner call the slots via a pair of input iterators
351 return combiner()(slot_call_iterator(notification.impl->slots_.begin(),
352 impl->slots_.end(), f, cache),
353 slot_call_iterator(notification.impl->slots_.end(),
354 impl->slots_.end(), f, cache));
355 }
356
357 template<
358 typename R,
359 BOOST_SIGNALS_TEMPLATE_PARMS
360 BOOST_SIGNALS_COMMA_IF_NONZERO_ARGS
361 typename Combiner,
362 typename Group,
363 typename GroupCompare,
364 typename SlotFunction
365 >
366 typename BOOST_SIGNALS_SIGNAL<
367 R, BOOST_SIGNALS_TEMPLATE_ARGS
368 BOOST_SIGNALS_COMMA_IF_NONZERO_ARGS
369 Combiner, Group, GroupCompare, SlotFunction>::result_type
370 BOOST_SIGNALS_SIGNAL<
371 R, BOOST_SIGNALS_TEMPLATE_ARGS
372 BOOST_SIGNALS_COMMA_IF_NONZERO_ARGS
373 Combiner, Group, GroupCompare, SlotFunction
374 >::operator()(BOOST_SIGNALS_PARMS) const
375 {
376 // Notify the slot handling code that we are making a call
377 BOOST_SIGNALS_NAMESPACE::detail::call_notification notification(this->impl);
378
379 // Construct a function object that will call the underlying slots
380 // with the given arguments.
381 #if BOOST_SIGNALS_NUM_ARGS == 0
382 BOOST_SIGNALS_ARGS_STRUCT_INST args;
383 #else
384 BOOST_SIGNALS_ARGS_STRUCT_INST args(BOOST_SIGNALS_ARGS);
385 #endif // BOOST_SIGNALS_NUM_ARGS > 0
386
387 call_bound_slot f(&args);
388
389 typedef typename call_bound_slot::result_type call_result_type;
390 optional<call_result_type> cache;
391
392 // Let the combiner call the slots via a pair of input iterators
393 return combiner()(slot_call_iterator(notification.impl->slots_.begin(),
394 impl->slots_.end(), f, cache),
395 slot_call_iterator(notification.impl->slots_.end(),
396 impl->slots_.end(), f, cache));
397 }
398 } // namespace boost
399
400 #undef BOOST_SIGNAL_FUNCTION_N_HEADER
401 #undef BOOST_SIGNALS_ARGS_STRUCT_INST
402 #undef BOOST_SIGNALS_CALL_BOUND
403 #undef BOOST_SIGNALS_ARGS_STRUCT
404 #undef BOOST_SIGNALS_FUNCTION
405 #undef BOOST_SIGNALS_SIGNAL
406 #undef BOOST_SIGNALS_COMMA_IF_NONZERO_ARGS
407
408 #ifdef BOOST_HAS_ABI_HEADERS
409 # include BOOST_ABI_SUFFIX
410 #endif