3 * Author: Lukas Krejci <krejci.l@centrum.cz>, (C) 2008
4 * Copyright: See COPYING file that comes with this distribution
7 #ifndef BOOST_PP_IS_ITERATING
9 #ifndef BEACON_fast_signal_H
10 #define BEACON_fast_signal_H
12 #include <beacon/config.hpp> //for BEACON_MAX_ARGS
13 #include <beacon/connection.hpp>
14 #include <beacon/event_queue.hpp>
15 #include <beacon/detail/slot.hpp>
16 #include <beacon/trackable.hpp>
17 #include <beacon/detail/connection_impl_base.hpp>
18 #include <beacon/detail/signal_impl.hpp>
19 #include <boost/type_traits/function_traits.hpp>
20 #include <boost/type_traits/add_pointer.hpp>
22 //include preprocessor magic
23 #include <boost/preprocessor/iteration/iterate.hpp>
24 #include <boost/preprocessor/repetition.hpp>
25 #include <boost/preprocessor/punctuation/comma_if.hpp>
26 #include <boost/preprocessor/cat.hpp>
28 #define BOOST_PP_ITERATION_LIMITS (0, BEACON_MAX_ARGS)
29 #define BOOST_PP_FILENAME_1 "beacon/fast_signal.hpp" // this file
35 template<int Arity
, typename Signature
>
36 struct get_fast_signal_impl
;
38 #include BOOST_PP_ITERATE()
43 * Fast signal is a signal that can execute the slots
44 * within an event queue of the trackables their connected
46 * There is no support to retrieve or track the results
47 * of those invocations (which makes the signal execution "fast").
49 template<typename Signature
>
51 public detail::get_fast_signal_impl
<
52 (boost::function_traits
<Signature
>::arity
),
58 * Creates a new signal with the same connections as this instance.
59 * !!! Use with caution as there is no way of controlling the
60 * individual connections of the new signal.
62 fast_signal
<Signature
> & copy() {
63 fast_signal
<Signature
> * ret
= new fast_signal
<Signature
>;
64 detail::signal_base::slot_list_type slts
= detail::signal_base::get_slots_copy();
66 for(detail::signal_base::slot_list_type::iterator it
= slts
.begin();
67 it
!= slts
.end(); ++it
) {
69 ret
->do_connect(it
->slot
, *(it
->queue
));
78 #endif //BEACON_fast_signal_H
80 #else //BOOST_PP_IS_ITERATING
82 #define n BOOST_PP_ITERATION()
84 #define FAST_SIGNAL_IMPL_N BOOST_PP_CAT(fast_signal_impl, n)
86 template<typename Signature
88 BOOST_PP_ENUM_PARAMS(n
, typename T
)>
89 class FAST_SIGNAL_IMPL_N
: public detail::signal_impl
<typename
boost::add_pointer
<Signature
>::type
> {
91 typedef slot_impl_base
<typename
boost::add_pointer
<Signature
>::type
> slot_type
;
95 * All the connected slots are invoked with given parameters.
96 * The invocation of the slot is relayed to the event queue if
97 * the slot was connected using a trackable with non-null event queue
98 * or executed directly if the trackable was null or its event queue
101 void raise(BOOST_PP_ENUM_BINARY_PARAMS(n
, T
, arg
)) {
102 signal_base::slot_list_type slts
= signal_base::get_slots_copy();
104 for(signal_base::slot_list_type::iterator it
= slts
.begin();
105 it
!= slts
.end(); ++it
) {
107 intrusive_ptr
<connection_impl_base
> con
= it
->connection
;
110 #ifdef ENABLE_CONNECTION_BLOCKING
115 slot_type
* slot
= reinterpret_cast<slot_type
*>(it
->slot
.get());
117 if (it
->queue
!= 0) {
118 enqueue
<Signature
>::call(*(it
->queue
), *slot
, con
->token())
119 (BOOST_PP_ENUM_PARAMS(n
, arg
));
121 invokable::token_type::lock_t
lock(con
->token()->guard());
123 (*slot
)(BOOST_PP_ENUM_PARAMS(n
, arg
));
130 * Calls raise() with the provided arguments.
132 inline void operator()(BOOST_PP_ENUM_BINARY_PARAMS(n
, T
, arg
)) {
133 raise(BOOST_PP_ENUM_PARAMS(n
, arg
));
137 #define ARG_TYPE(z, x, unused) \
138 BOOST_PP_CAT(BOOST_PP_CAT( \
139 typename boost::function_traits<Signature>::arg, \
140 BOOST_PP_INC(x)), _type)
142 template<typename Signature
>
143 struct get_fast_signal_impl
<n
, Signature
> {
145 typedef FAST_SIGNAL_IMPL_N
<
148 BOOST_PP_ENUM(n
, ARG_TYPE
, ~)> type
;
152 #undef FAST_SIGNAL_IMPL_N
155 #endif //BOOST_PP_IS_ITERATING