1 // Boost.Signals library
3 // Copyright (C) 2001 Doug Gregor (gregod@cs.rpi.edu)
5 // Permission to copy, use, sell and distribute this software is granted
6 // provided this copyright notice appears in all copies.
7 // Permission to modify the code and to distribute modified code is granted
8 // provided this copyright notice appears in all copies, and a notice
9 // that the code was modified is included with the copyright notice.
11 // This software is provided "as is" without express or implied warranty,
12 // and with no claim as to its suitability for any purpose.
14 // For more information, see http://www.boost.org
16 // This file intentionally does not have include guards, because it is meant
17 // to be included multiple times (one for each signalN class). The
18 // BOOST_SIGNALS_SIGNAL_TEMPLATE_HEADER_INCLUDED macro merely serves to
19 // suppress reinclusion of the files that this header depends on.
20 #ifndef BOOST_SIGNALS_SIGNAL_TEMPLATE_HEADER_INCLUDED
21 #define BOOST_SIGNALS_SIGNAL_TEMPLATE_HEADER_INCLUDED
22 # include <boost/config.hpp>
23 # include <boost/signals/connection.hpp>
24 # include <boost/utility.hpp>
25 # include <boost/ref.hpp>
26 # include <boost/signals/slot.hpp>
27 # include <boost/last_value.hpp>
28 # include <boost/signals/detail/signal_base.hpp>
29 # include <boost/signals/detail/slot_call_iterator.hpp>
31 # include <functional>
34 #endif // !BOOST_SIGNALS_SIGNAL_TEMPLATE_HEADER_INCLUDED
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
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
44 # define BOOST_SIGNALS_COMMA_IF_NONZERO_ARGS ,
45 #endif // BOOST_SIGNALS_NUM_ARGS > 0
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)
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>
58 namespace BOOST_SIGNALS_NAMESPACE {
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
64 struct BOOST_SIGNALS_ARGS_STRUCT {
65 BOOST_SIGNALS_ARGS_STRUCT(BOOST_SIGNALS_COPY_PARMS)
66 BOOST_SIGNALS_INIT_ARGS
70 BOOST_SIGNALS_ARGS_AS_MEMBERS
73 // Function object that calls the function object given to it, passing
74 // the bound arguments along to that underlying function object
76 struct BOOST_SIGNALS_CALL_BOUND {
77 template<BOOST_SIGNALS_TEMPLATE_PARMS
78 BOOST_SIGNALS_COMMA_IF_NONZERO_ARGS
81 typedef BOOST_SIGNALS_ARGS_STRUCT<BOOST_SIGNALS_TEMPLATE_ARGS>*
86 typedef R result_type;
89 caller(args_type a) : args(a) {}
91 template<typename Pair>
92 R operator()(const Pair& slot) const
94 F* target = const_cast<F*>(any_cast<F>(&slot.second.second));
95 return (*target)(BOOST_SIGNALS_BOUND_ARGS);
101 struct BOOST_SIGNALS_CALL_BOUND<void> {
102 template<BOOST_SIGNALS_TEMPLATE_PARMS
103 BOOST_SIGNALS_COMMA_IF_NONZERO_ARGS
106 typedef BOOST_SIGNALS_ARGS_STRUCT<BOOST_SIGNALS_TEMPLATE_ARGS>*
111 typedef unusable result_type;
113 caller(args_type a) : args(a) {}
115 template<typename Pair>
116 unusable operator()(const Pair& slot) const
118 F* target = const_cast<F*>(any_cast<F>(&slot.second.second));
119 (*target)(BOOST_SIGNALS_BOUND_ARGS);
124 } // namespace detail
125 } // namespace BOOST_SIGNALS_NAMESPACE
127 // The actual signalN class
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>
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
144 // The slot function type
145 typedef SlotFunction slot_function_type;
147 // Result type of a slot
148 typedef typename BOOST_SIGNALS_NAMESPACE::detail::slot_result_type<R>::type
152 BOOST_SIGNALS_ARG_TYPES
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;
162 // The real slot name comparison object type
163 typedef BOOST_SIGNALS_NAMESPACE::detail::any_bridge_compare<GroupCompare, Group>
164 real_group_compare_type;
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
177 // Combiner's result type
178 typedef typename Combiner::result_type result_type;
181 typedef Combiner combiner_type;
184 typedef slot<slot_function_type> slot_type;
186 // Slot name type and comparison
187 typedef Group group_type;
188 typedef GroupCompare group_compare_type;
190 typedef typename BOOST_SIGNALS_NAMESPACE::detail::slot_call_iterator_generator<
192 slot_iterator>::type slot_call_iterator;
195 BOOST_SIGNALS_SIGNAL(const Combiner& c = Combiner(),
196 const GroupCompare& comp = GroupCompare()) :
197 BOOST_SIGNALS_NAMESPACE::detail::signal_base(real_group_compare_type(comp)),
202 // Connect a slot to this signal
203 BOOST_SIGNALS_NAMESPACE::connection connect(const slot_type&);
204 BOOST_SIGNALS_NAMESPACE::connection connect(const group_type&, const slot_type&);
206 // Disconnect a named slot
207 void disconnect(const group_type& group)
209 impl->disconnect(group);
213 result_type operator()(BOOST_SIGNALS_PARMS);
214 result_type operator()(BOOST_SIGNALS_PARMS) const;
222 BOOST_SIGNALS_TEMPLATE_PARMS
223 BOOST_SIGNALS_COMMA_IF_NONZERO_ARGS
226 typename GroupCompare,
227 typename SlotFunction
229 BOOST_SIGNALS_NAMESPACE::connection
230 BOOST_SIGNALS_SIGNAL<
231 R, BOOST_SIGNALS_TEMPLATE_ARGS
232 BOOST_SIGNALS_COMMA_IF_NONZERO_ARGS
233 Combiner, Group, GroupCompare, SlotFunction
234 >::connect(const slot_type& in_slot)
236 // If the slot has been disconnected, just return a disconnected
238 if (!in_slot.is_active()) {
239 return BOOST_SIGNALS_NAMESPACE::connection();
242 return impl->connect_slot(in_slot.get_slot_function(),
244 in_slot.get_bound_objects());
249 BOOST_SIGNALS_TEMPLATE_PARMS
250 BOOST_SIGNALS_COMMA_IF_NONZERO_ARGS
253 typename GroupCompare,
254 typename SlotFunction
256 BOOST_SIGNALS_NAMESPACE::connection
257 BOOST_SIGNALS_SIGNAL<
258 R, BOOST_SIGNALS_TEMPLATE_ARGS
259 BOOST_SIGNALS_COMMA_IF_NONZERO_ARGS
260 Combiner, Group, GroupCompare, SlotFunction
261 >::connect(const group_type& group,
262 const slot_type& in_slot)
264 return impl->connect_slot(in_slot.get_slot_function(),
266 in_slot.get_bound_objects());
271 BOOST_SIGNALS_TEMPLATE_PARMS
272 BOOST_SIGNALS_COMMA_IF_NONZERO_ARGS
275 typename GroupCompare,
276 typename SlotFunction
278 typename BOOST_SIGNALS_SIGNAL<
279 R, BOOST_SIGNALS_TEMPLATE_ARGS
280 BOOST_SIGNALS_COMMA_IF_NONZERO_ARGS
281 Combiner, Group, GroupCompare, SlotFunction>::result_type
282 BOOST_SIGNALS_SIGNAL<
283 R, BOOST_SIGNALS_TEMPLATE_ARGS
284 BOOST_SIGNALS_COMMA_IF_NONZERO_ARGS
285 Combiner, Group, GroupCompare, SlotFunction
286 >::operator()(BOOST_SIGNALS_PARMS)
288 // Notify the slot handling code that we are making a call
289 BOOST_SIGNALS_NAMESPACE::detail::call_notification notification(this->impl);
291 // Construct a function object that will call the underlying slots
292 // with the given arguments.
293 #if BOOST_SIGNALS_NUM_ARGS == 0
294 BOOST_SIGNALS_ARGS_STRUCT_INST args;
296 BOOST_SIGNALS_ARGS_STRUCT_INST args(BOOST_SIGNALS_ARGS);
297 #endif // BOOST_SIGNALS_NUM_ARGS > 0
298 call_bound_slot f(&args);
300 // Let the combiner call the slots via a pair of input iterators
301 return combiner(BOOST_SIGNALS_NAMESPACE::detail::make_slot_call_iterator(
302 notification.impl->slots_.begin(), impl->slots_.end(), f),
303 BOOST_SIGNALS_NAMESPACE::detail::make_slot_call_iterator(
304 notification.impl->slots_.end(), impl->slots_.end(), f));
309 BOOST_SIGNALS_TEMPLATE_PARMS
310 BOOST_SIGNALS_COMMA_IF_NONZERO_ARGS
313 typename GroupCompare,
314 typename SlotFunction
316 typename BOOST_SIGNALS_SIGNAL<
317 R, BOOST_SIGNALS_TEMPLATE_ARGS
318 BOOST_SIGNALS_COMMA_IF_NONZERO_ARGS
319 Combiner, Group, GroupCompare, SlotFunction>::result_type
320 BOOST_SIGNALS_SIGNAL<
321 R, BOOST_SIGNALS_TEMPLATE_ARGS
322 BOOST_SIGNALS_COMMA_IF_NONZERO_ARGS
323 Combiner, Group, GroupCompare, SlotFunction
324 >::operator()(BOOST_SIGNALS_PARMS) const
326 // Notify the slot handling code that we are making a call
327 BOOST_SIGNALS_NAMESPACE::detail::call_notification notification(this->impl);
329 // Construct a function object that will call the underlying slots
330 // with the given arguments.
331 #if BOOST_SIGNALS_NUM_ARGS == 0
332 BOOST_SIGNALS_ARGS_STRUCT_INST args;
334 BOOST_SIGNALS_ARGS_STRUCT_INST args(BOOST_SIGNALS_ARGS);
335 #endif // BOOST_SIGNALS_NUM_ARGS > 0
337 call_bound_slot f(&args);
339 // Let the combiner call the slots via a pair of input iterators
340 return combiner(BOOST_SIGNALS_NAMESPACE::detail::make_slot_call_iterator(
341 notification.impl->slots_.begin(), impl->slots_.end(), f),
342 BOOST_SIGNALS_NAMESPACE::detail::make_slot_call_iterator(
343 notification.impl->slots_.end(), impl->slots_.end(), f));
347 #undef BOOST_SIGNAL_FUNCTION_N_HEADER
348 #undef BOOST_SIGNALS_ARGS_STRUCT_INST
349 #undef BOOST_SIGNALS_CALL_BOUND
350 #undef BOOST_SIGNALS_ARGS_STRUCT
351 #undef BOOST_SIGNALS_FUNCTION
352 #undef BOOST_SIGNALS_SIGNAL
353 #undef BOOST_SIGNALS_COMMA_IF_NONZERO_ARGS