moved the token invalidation from ~trackable to signal_base::do_disconnect where...
[beacon-ss.git] / beacon / fast_signal.hpp
blob34e8826292d862c80fcca5fa93eeacf8790e4ec3
1 /**
2 * beacon
3 * Author: Lukas Krejci <krejci.l@centrum.cz>, (C) 2008
4 * Copyright: See COPYING file that comes with this distribution
5 */
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
31 namespace beacon {
33 namespace detail {
35 template<int Arity, typename Signature>
36 struct get_fast_signal_impl;
38 #include BOOST_PP_ITERATE()
40 } //namespace detail
42 /**
43 * Fast signal is a signal that can execute the slots
44 * within an event queue of the trackables their connected
45 * with.
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>
50 class fast_signal :
51 public detail::get_fast_signal_impl<
52 (boost::function_traits<Signature>::arity),
53 Signature>::type {
56 } //namespace beacon
58 #endif //BEACON_fast_signal_H
60 #else //BOOST_PP_IS_ITERATING
62 #define n BOOST_PP_ITERATION()
64 #define FAST_SIGNAL_IMPL_N BOOST_PP_CAT(fast_signal_impl, n)
66 template<typename Signature
67 BOOST_PP_COMMA_IF(n)
68 BOOST_PP_ENUM_PARAMS(n, typename T)>
69 class FAST_SIGNAL_IMPL_N : public detail::signal_impl<typename boost::add_pointer<Signature>::type> {
70 public:
71 typedef slot_impl_base<typename boost::add_pointer<Signature>::type> slot_type;
73 /**
74 * Emits the signal.
75 * All the connected slots are invoked with given parameters.
76 * The invocation of the slot is relayed to the event queue if
77 * the slot was connected using a trackable with non-null event queue
78 * or executed directly if the trackable was null or its event queue
79 * was null.
81 void emit(BOOST_PP_ENUM_BINARY_PARAMS(n, T, arg)) {
82 signal_base::slot_list_type slots = signal_base::get_slots_copy();
84 for(signal_base::slot_list_type::iterator it = slots.begin();
85 it != slots.end(); ++it) {
87 intrusive_ptr<connection_impl_base> con = it->connection;
89 if (con->connected()
90 #ifdef ENABLE_CONNECTION_BLOCKING
91 && !con->blocked()
92 #endif
93 ) {
95 invokable::token_ptr token = con->token();
97 token->lock();
99 if (token->valid()) {
100 slot_type * slot = reinterpret_cast<slot_type *>(it->slot);
102 if (it->queue != 0) {
103 enqueue<Signature>::call(*(it->queue), *slot, token)
104 (BOOST_PP_ENUM_PARAMS(n, arg));
105 } else {
106 (*slot)(BOOST_PP_ENUM_PARAMS(n, arg));
110 token->unlock();
116 * Calls emit with the provided arguments.
118 void operator()(BOOST_PP_ENUM_BINARY_PARAMS(n, T, arg)) {
119 emit(BOOST_PP_ENUM_PARAMS(n, arg));
123 #define ARG_TYPE(z, x, unused) \
124 BOOST_PP_CAT(BOOST_PP_CAT( \
125 typename boost::function_traits<Signature>::arg, \
126 BOOST_PP_INC(x)), _type)
128 template<typename Signature>
129 struct get_fast_signal_impl<n, Signature> {
131 typedef FAST_SIGNAL_IMPL_N<
132 Signature
133 BOOST_PP_COMMA_IF(n)
134 BOOST_PP_ENUM(n, ARG_TYPE, ~)> type;
137 #undef n
138 #undef FAST_SIGNAL_IMPL_N
139 #undef ARG_TYPE
141 #endif //BOOST_PP_IS_ITERATING