]> git.sesse.net Git - casparcg/blob - dependencies/boost/boost/signals/signal_template.hpp
Manually merged pull request #222
[casparcg] / dependencies / boost / boost / signals / signal_template.hpp
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