annotate DEPENDENCIES/generic/include/boost/signals2/detail/signal_template.hpp @ 133:4acb5d8d80b6 tip

Don't fail environmental check if README.md exists (but .txt and no-suffix don't)
author Chris Cannam
date Tue, 30 Jul 2019 12:25:44 +0100
parents c530137014c0
children
rev   line source
Chris@16 1 /*
Chris@16 2 Template for Signa1, Signal2, ... classes that support signals
Chris@16 3 with 1, 2, ... parameters
Chris@16 4
Chris@16 5 Begin: 2007-01-23
Chris@16 6 */
Chris@16 7 // Copyright Frank Mori Hess 2007-2008
Chris@16 8 //
Chris@16 9 // Use, modification and
Chris@16 10 // distribution is subject to the Boost Software License, Version
Chris@16 11 // 1.0. (See accompanying file LICENSE_1_0.txt or copy at
Chris@16 12 // http://www.boost.org/LICENSE_1_0.txt)
Chris@16 13
Chris@16 14 // This file is included iteratively, and should not be protected from multiple inclusion
Chris@16 15
Chris@16 16 #ifdef BOOST_NO_CXX11_VARIADIC_TEMPLATES
Chris@16 17 #define BOOST_SIGNALS2_NUM_ARGS BOOST_PP_ITERATION()
Chris@16 18 #else
Chris@16 19 #define BOOST_SIGNALS2_NUM_ARGS 1
Chris@16 20 #endif
Chris@16 21
Chris@16 22 // R, T1, T2, ..., TN, Combiner, Group, GroupCompare, SlotFunction, ExtendedSlotFunction, Mutex
Chris@16 23 #define BOOST_SIGNALS2_SIGNAL_TEMPLATE_INSTANTIATION \
Chris@16 24 BOOST_SIGNALS2_SIGNATURE_TEMPLATE_INSTANTIATION(BOOST_SIGNALS2_NUM_ARGS), \
Chris@16 25 Combiner, Group, GroupCompare, SlotFunction, ExtendedSlotFunction, Mutex
Chris@16 26
Chris@16 27 namespace boost
Chris@16 28 {
Chris@16 29 namespace signals2
Chris@16 30 {
Chris@16 31 namespace detail
Chris@16 32 {
Chris@16 33 // helper for bound_extended_slot_function that handles specialization for void return
Chris@16 34 template<typename R>
Chris@16 35 class BOOST_SIGNALS2_BOUND_EXTENDED_SLOT_FUNCTION_INVOKER_N(BOOST_SIGNALS2_NUM_ARGS)
Chris@16 36 {
Chris@16 37 public:
Chris@16 38 typedef R result_type;
Chris@16 39 template<typename ExtendedSlotFunction BOOST_SIGNALS2_PP_COMMA_IF(BOOST_SIGNALS2_NUM_ARGS)
Chris@16 40 BOOST_SIGNALS2_ARGS_TEMPLATE_DECL(BOOST_SIGNALS2_NUM_ARGS)>
Chris@16 41 result_type operator()(ExtendedSlotFunction &func, const connection &conn
Chris@16 42 BOOST_SIGNALS2_PP_COMMA_IF(BOOST_SIGNALS2_NUM_ARGS)
Chris@101 43 BOOST_SIGNALS2_FULL_FORWARD_ARGS(BOOST_SIGNALS2_NUM_ARGS)) const
Chris@16 44 {
Chris@16 45 return func(conn BOOST_SIGNALS2_PP_COMMA_IF(BOOST_SIGNALS2_NUM_ARGS)
Chris@101 46 BOOST_SIGNALS2_FORWARDED_ARGS(BOOST_SIGNALS2_NUM_ARGS));
Chris@16 47 }
Chris@16 48 };
Chris@16 49 #ifdef BOOST_NO_VOID_RETURNS
Chris@16 50 template<>
Chris@16 51 class BOOST_SIGNALS2_BOUND_EXTENDED_SLOT_FUNCTION_INVOKER_N(BOOST_SIGNALS2_NUM_ARGS)<void>
Chris@16 52 {
Chris@16 53 public:
Chris@16 54 typedef result_type_wrapper<void>::type result_type;
Chris@16 55 template<typename ExtendedSlotFunction BOOST_SIGNALS2_PP_COMMA_IF(BOOST_SIGNALS2_NUM_ARGS)
Chris@16 56 BOOST_SIGNALS2_ARGS_TEMPLATE_DECL(BOOST_SIGNALS2_NUM_ARGS)>
Chris@16 57 result_type operator()(ExtendedSlotFunction &func, const connection &conn
Chris@16 58 BOOST_SIGNALS2_PP_COMMA_IF(BOOST_SIGNALS2_NUM_ARGS)
Chris@101 59 BOOST_SIGNALS2_FULL_FORWARD_ARGS(BOOST_SIGNALS2_NUM_ARGS)) const
Chris@16 60 {
Chris@16 61 func(conn BOOST_SIGNALS2_PP_COMMA_IF(BOOST_SIGNALS2_NUM_ARGS)
Chris@101 62 BOOST_SIGNALS2_FORWARDED_ARGS(BOOST_SIGNALS2_NUM_ARGS));
Chris@16 63 return result_type();
Chris@16 64 }
Chris@16 65 };
Chris@16 66 #endif
Chris@16 67 // wrapper around an signalN::extended_slot_function which binds the
Chris@16 68 // connection argument so it looks like a normal
Chris@16 69 // signalN::slot_function
Chris@16 70
Chris@16 71 template<typename ExtendedSlotFunction>
Chris@16 72 class BOOST_SIGNALS2_BOUND_EXTENDED_SLOT_FUNCTION_N(BOOST_SIGNALS2_NUM_ARGS)
Chris@16 73 {
Chris@16 74 public:
Chris@16 75 typedef typename result_type_wrapper<typename ExtendedSlotFunction::result_type>::type result_type;
Chris@16 76 BOOST_SIGNALS2_BOUND_EXTENDED_SLOT_FUNCTION_N(BOOST_SIGNALS2_NUM_ARGS)(const ExtendedSlotFunction &fun):
Chris@16 77 _fun(fun), _connection(new connection)
Chris@16 78 {}
Chris@16 79 void set_connection(const connection &conn)
Chris@16 80 {
Chris@16 81 *_connection = conn;
Chris@16 82 }
Chris@16 83
Chris@16 84 #if BOOST_SIGNALS2_NUM_ARGS > 0
Chris@16 85 template<BOOST_SIGNALS2_ARGS_TEMPLATE_DECL(BOOST_SIGNALS2_NUM_ARGS)>
Chris@16 86 #endif // BOOST_SIGNALS2_NUM_ARGS > 0
Chris@101 87 result_type operator()(BOOST_SIGNALS2_FULL_FORWARD_ARGS(BOOST_SIGNALS2_NUM_ARGS))
Chris@16 88 {
Chris@16 89 return BOOST_SIGNALS2_BOUND_EXTENDED_SLOT_FUNCTION_INVOKER_N(BOOST_SIGNALS2_NUM_ARGS)
Chris@16 90 <typename ExtendedSlotFunction::result_type>()
Chris@16 91 (_fun, *_connection BOOST_SIGNALS2_PP_COMMA_IF(BOOST_SIGNALS2_NUM_ARGS)
Chris@101 92 BOOST_SIGNALS2_FORWARDED_ARGS(BOOST_SIGNALS2_NUM_ARGS));
Chris@16 93 }
Chris@16 94 // const overload
Chris@16 95 #if BOOST_SIGNALS2_NUM_ARGS > 0
Chris@16 96 template<BOOST_SIGNALS2_ARGS_TEMPLATE_DECL(BOOST_SIGNALS2_NUM_ARGS)>
Chris@16 97 #endif // BOOST_SIGNALS2_NUM_ARGS > 0
Chris@101 98 result_type operator()(BOOST_SIGNALS2_FULL_FORWARD_ARGS(BOOST_SIGNALS2_NUM_ARGS)) const
Chris@16 99 {
Chris@16 100 return BOOST_SIGNALS2_BOUND_EXTENDED_SLOT_FUNCTION_INVOKER_N(BOOST_SIGNALS2_NUM_ARGS)
Chris@16 101 <typename ExtendedSlotFunction::result_type>()
Chris@16 102 (_fun, *_connection BOOST_SIGNALS2_PP_COMMA_IF(BOOST_SIGNALS2_NUM_ARGS)
Chris@101 103 BOOST_SIGNALS2_FORWARDED_ARGS(BOOST_SIGNALS2_NUM_ARGS));
Chris@16 104 }
Chris@16 105 template<typename T>
Chris@16 106 bool operator==(const T &other) const
Chris@16 107 {
Chris@16 108 return _fun == other;
Chris@16 109 }
Chris@16 110 private:
Chris@16 111 BOOST_SIGNALS2_BOUND_EXTENDED_SLOT_FUNCTION_N(BOOST_SIGNALS2_NUM_ARGS)()
Chris@16 112 {}
Chris@16 113
Chris@16 114 ExtendedSlotFunction _fun;
Chris@16 115 boost::shared_ptr<connection> _connection;
Chris@16 116 };
Chris@16 117
Chris@16 118 template<BOOST_SIGNALS2_SIGNAL_TEMPLATE_DECL(BOOST_SIGNALS2_NUM_ARGS)>
Chris@16 119 class BOOST_SIGNALS2_SIGNAL_IMPL_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS);
Chris@16 120
Chris@16 121 template<BOOST_SIGNALS2_SIGNAL_TEMPLATE_SPECIALIZATION_DECL(BOOST_SIGNALS2_NUM_ARGS)>
Chris@16 122 class BOOST_SIGNALS2_SIGNAL_IMPL_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS) BOOST_SIGNALS2_SIGNAL_TEMPLATE_SPECIALIZATION
Chris@16 123 {
Chris@16 124 public:
Chris@16 125 typedef SlotFunction slot_function_type;
Chris@16 126 // typedef slotN<Signature, SlotFunction> slot_type;
Chris@16 127 typedef BOOST_SIGNALS2_SLOT_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS)
Chris@16 128 <BOOST_SIGNALS2_SIGNATURE_TEMPLATE_INSTANTIATION(BOOST_SIGNALS2_NUM_ARGS),
Chris@16 129 slot_function_type> slot_type;
Chris@16 130 typedef ExtendedSlotFunction extended_slot_function_type;
Chris@16 131 // typedef slotN+1<R, const connection &, T1, T2, ..., TN, extended_slot_function_type> extended_slot_type;
Chris@16 132 typedef BOOST_SIGNALS2_EXTENDED_SLOT_TYPE(BOOST_SIGNALS2_NUM_ARGS) extended_slot_type;
Chris@16 133 typedef typename nonvoid<typename slot_function_type::result_type>::type nonvoid_slot_result_type;
Chris@16 134 private:
Chris@16 135 #ifdef BOOST_NO_CXX11_VARIADIC_TEMPLATES
Chris@16 136 class slot_invoker;
Chris@16 137 #else // BOOST_NO_CXX11_VARIADIC_TEMPLATES
Chris@16 138 typedef variadic_slot_invoker<nonvoid_slot_result_type, Args...> slot_invoker;
Chris@16 139 #endif // BOOST_NO_CXX11_VARIADIC_TEMPLATES
Chris@16 140 typedef slot_call_iterator_cache<nonvoid_slot_result_type, slot_invoker> slot_call_iterator_cache_type;
Chris@16 141 typedef typename group_key<Group>::type group_key_type;
Chris@16 142 typedef shared_ptr<connection_body<group_key_type, slot_type, Mutex> > connection_body_type;
Chris@16 143 typedef grouped_list<Group, GroupCompare, connection_body_type> connection_list_type;
Chris@16 144 typedef BOOST_SIGNALS2_BOUND_EXTENDED_SLOT_FUNCTION_N(BOOST_SIGNALS2_NUM_ARGS)<extended_slot_function_type>
Chris@16 145 bound_extended_slot_function_type;
Chris@16 146 public:
Chris@16 147 typedef Combiner combiner_type;
Chris@16 148 typedef typename result_type_wrapper<typename combiner_type::result_type>::type result_type;
Chris@16 149 typedef Group group_type;
Chris@16 150 typedef GroupCompare group_compare_type;
Chris@16 151 typedef typename detail::slot_call_iterator_t<slot_invoker,
Chris@16 152 typename connection_list_type::iterator, connection_body<group_key_type, slot_type, Mutex> > slot_call_iterator;
Chris@16 153
Chris@16 154 BOOST_SIGNALS2_SIGNAL_IMPL_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS)(const combiner_type &combiner_arg,
Chris@16 155 const group_compare_type &group_compare):
Chris@16 156 _shared_state(new invocation_state(connection_list_type(group_compare), combiner_arg)),
Chris@16 157 _garbage_collector_it(_shared_state->connection_bodies().end())
Chris@16 158 {}
Chris@16 159 // connect slot
Chris@16 160 connection connect(const slot_type &slot, connect_position position = at_back)
Chris@16 161 {
Chris@16 162 unique_lock<mutex_type> lock(_mutex);
Chris@16 163 return nolock_connect(slot, position);
Chris@16 164 }
Chris@16 165 connection connect(const group_type &group,
Chris@16 166 const slot_type &slot, connect_position position = at_back)
Chris@16 167 {
Chris@16 168 unique_lock<Mutex> lock(_mutex);
Chris@16 169 return nolock_connect(group, slot, position);
Chris@16 170 }
Chris@16 171 // connect extended slot
Chris@16 172 connection connect_extended(const extended_slot_type &ext_slot, connect_position position = at_back)
Chris@16 173 {
Chris@16 174 unique_lock<mutex_type> lock(_mutex);
Chris@16 175 bound_extended_slot_function_type bound_slot(ext_slot.slot_function());
Chris@16 176 slot_type slot = replace_slot_function<slot_type>(ext_slot, bound_slot);
Chris@16 177 connection conn = nolock_connect(slot, position);
Chris@16 178 bound_slot.set_connection(conn);
Chris@16 179 return conn;
Chris@16 180 }
Chris@16 181 connection connect_extended(const group_type &group,
Chris@16 182 const extended_slot_type &ext_slot, connect_position position = at_back)
Chris@16 183 {
Chris@16 184 unique_lock<Mutex> lock(_mutex);
Chris@16 185 bound_extended_slot_function_type bound_slot(ext_slot.slot_function());
Chris@16 186 slot_type slot = replace_slot_function<slot_type>(ext_slot, bound_slot);
Chris@16 187 connection conn = nolock_connect(group, slot, position);
Chris@16 188 bound_slot.set_connection(conn);
Chris@16 189 return conn;
Chris@16 190 }
Chris@16 191 // disconnect slot(s)
Chris@16 192 void disconnect_all_slots()
Chris@16 193 {
Chris@16 194 shared_ptr<invocation_state> local_state =
Chris@16 195 get_readable_state();
Chris@16 196 typename connection_list_type::iterator it;
Chris@16 197 for(it = local_state->connection_bodies().begin();
Chris@16 198 it != local_state->connection_bodies().end(); ++it)
Chris@16 199 {
Chris@16 200 (*it)->disconnect();
Chris@16 201 }
Chris@16 202 }
Chris@16 203 void disconnect(const group_type &group)
Chris@16 204 {
Chris@16 205 shared_ptr<invocation_state> local_state =
Chris@16 206 get_readable_state();
Chris@16 207 group_key_type group_key(grouped_slots, group);
Chris@16 208 typename connection_list_type::iterator it;
Chris@16 209 typename connection_list_type::iterator end_it =
Chris@16 210 local_state->connection_bodies().upper_bound(group_key);
Chris@16 211 for(it = local_state->connection_bodies().lower_bound(group_key);
Chris@16 212 it != end_it; ++it)
Chris@16 213 {
Chris@16 214 (*it)->disconnect();
Chris@16 215 }
Chris@16 216 }
Chris@16 217 template <typename T>
Chris@16 218 void disconnect(const T &slot)
Chris@16 219 {
Chris@16 220 typedef mpl::bool_<(is_convertible<T, group_type>::value)> is_group;
Chris@16 221 do_disconnect(slot, is_group());
Chris@16 222 }
Chris@16 223 // emit signal
Chris@16 224 result_type operator ()(BOOST_SIGNALS2_SIGNATURE_FULL_ARGS(BOOST_SIGNALS2_NUM_ARGS))
Chris@16 225 {
Chris@16 226 shared_ptr<invocation_state> local_state;
Chris@16 227 typename connection_list_type::iterator it;
Chris@16 228 {
Chris@16 229 unique_lock<mutex_type> list_lock(_mutex);
Chris@16 230 // only clean up if it is safe to do so
Chris@16 231 if(_shared_state.unique())
Chris@16 232 nolock_cleanup_connections(false, 1);
Chris@16 233 /* Make a local copy of _shared_state while holding mutex, so we are
Chris@16 234 thread safe against the combiner or connection list getting modified
Chris@16 235 during invocation. */
Chris@16 236 local_state = _shared_state;
Chris@16 237 }
Chris@16 238 slot_invoker invoker = slot_invoker(BOOST_SIGNALS2_SIGNATURE_ARG_NAMES(BOOST_SIGNALS2_NUM_ARGS));
Chris@16 239 slot_call_iterator_cache_type cache(invoker);
Chris@16 240 invocation_janitor janitor(cache, *this, &local_state->connection_bodies());
Chris@16 241 return detail::combiner_invoker<typename combiner_type::result_type>()
Chris@16 242 (
Chris@16 243 local_state->combiner(),
Chris@16 244 slot_call_iterator(local_state->connection_bodies().begin(), local_state->connection_bodies().end(), cache),
Chris@16 245 slot_call_iterator(local_state->connection_bodies().end(), local_state->connection_bodies().end(), cache)
Chris@16 246 );
Chris@16 247 }
Chris@16 248 result_type operator ()(BOOST_SIGNALS2_SIGNATURE_FULL_ARGS(BOOST_SIGNALS2_NUM_ARGS)) const
Chris@16 249 {
Chris@16 250 shared_ptr<invocation_state> local_state;
Chris@16 251 typename connection_list_type::iterator it;
Chris@16 252 {
Chris@16 253 unique_lock<mutex_type> list_lock(_mutex);
Chris@16 254 // only clean up if it is safe to do so
Chris@16 255 if(_shared_state.unique())
Chris@16 256 nolock_cleanup_connections(false, 1);
Chris@16 257 /* Make a local copy of _shared_state while holding mutex, so we are
Chris@16 258 thread safe against the combiner or connection list getting modified
Chris@16 259 during invocation. */
Chris@16 260 local_state = _shared_state;
Chris@16 261 }
Chris@16 262 slot_invoker invoker = slot_invoker(BOOST_SIGNALS2_SIGNATURE_ARG_NAMES(BOOST_SIGNALS2_NUM_ARGS));
Chris@16 263 slot_call_iterator_cache_type cache(invoker);
Chris@16 264 invocation_janitor janitor(cache, *this, &local_state->connection_bodies());
Chris@16 265 return detail::combiner_invoker<typename combiner_type::result_type>()
Chris@16 266 (
Chris@16 267 local_state->combiner(),
Chris@16 268 slot_call_iterator(local_state->connection_bodies().begin(), local_state->connection_bodies().end(), cache),
Chris@16 269 slot_call_iterator(local_state->connection_bodies().end(), local_state->connection_bodies().end(), cache)
Chris@16 270 );
Chris@16 271 }
Chris@16 272 std::size_t num_slots() const
Chris@16 273 {
Chris@16 274 shared_ptr<invocation_state> local_state =
Chris@16 275 get_readable_state();
Chris@16 276 typename connection_list_type::iterator it;
Chris@16 277 std::size_t count = 0;
Chris@16 278 for(it = local_state->connection_bodies().begin();
Chris@16 279 it != local_state->connection_bodies().end(); ++it)
Chris@16 280 {
Chris@16 281 if((*it)->connected()) ++count;
Chris@16 282 }
Chris@16 283 return count;
Chris@16 284 }
Chris@16 285 bool empty() const
Chris@16 286 {
Chris@16 287 shared_ptr<invocation_state> local_state =
Chris@16 288 get_readable_state();
Chris@16 289 typename connection_list_type::iterator it;
Chris@16 290 for(it = local_state->connection_bodies().begin();
Chris@16 291 it != local_state->connection_bodies().end(); ++it)
Chris@16 292 {
Chris@16 293 if((*it)->connected()) return false;
Chris@16 294 }
Chris@16 295 return true;
Chris@16 296 }
Chris@16 297 combiner_type combiner() const
Chris@16 298 {
Chris@16 299 unique_lock<mutex_type> lock(_mutex);
Chris@16 300 return _shared_state->combiner();
Chris@16 301 }
Chris@16 302 void set_combiner(const combiner_type &combiner_arg)
Chris@16 303 {
Chris@16 304 unique_lock<mutex_type> lock(_mutex);
Chris@16 305 if(_shared_state.unique())
Chris@16 306 _shared_state->combiner() = combiner_arg;
Chris@16 307 else
Chris@16 308 _shared_state.reset(new invocation_state(*_shared_state, combiner_arg));
Chris@16 309 }
Chris@16 310 private:
Chris@16 311 typedef Mutex mutex_type;
Chris@16 312
Chris@16 313 // slot_invoker is passed to slot_call_iterator_t to run slots
Chris@16 314 #ifdef BOOST_NO_CXX11_VARIADIC_TEMPLATES
Chris@16 315 class slot_invoker
Chris@16 316 {
Chris@16 317 public:
Chris@16 318 typedef nonvoid_slot_result_type result_type;
Chris@16 319 // typename add_reference<Tn>::type
Chris@16 320 #define BOOST_SIGNALS2_ADD_REF_TYPE(z, n, data) \
Chris@16 321 typename add_reference<BOOST_PP_CAT(T, BOOST_PP_INC(n))>::type
Chris@16 322 // typename add_reference<Tn>::type argn
Chris@16 323 #define BOOST_SIGNALS2_ADD_REF_ARG(z, n, data) \
Chris@16 324 BOOST_SIGNALS2_ADD_REF_TYPE(~, n, ~) \
Chris@16 325 BOOST_SIGNALS2_SIGNATURE_ARG_NAME(~, n, ~)
Chris@16 326 // typename add_reference<T1>::type arg1, typename add_reference<T2>::type arg2, ..., typename add_reference<Tn>::type argn
Chris@16 327 #define BOOST_SIGNALS2_ADD_REF_ARGS(arity) \
Chris@16 328 BOOST_PP_ENUM(arity, BOOST_SIGNALS2_ADD_REF_ARG, ~)
Chris@16 329 slot_invoker(BOOST_SIGNALS2_ADD_REF_ARGS(BOOST_SIGNALS2_NUM_ARGS)) BOOST_PP_EXPR_IF(BOOST_SIGNALS2_NUM_ARGS, :)
Chris@16 330 #undef BOOST_SIGNALS2_ADD_REF_ARGS
Chris@16 331
Chris@16 332 // m_argn
Chris@16 333 #define BOOST_SIGNALS2_M_ARG_NAME(z, n, data) BOOST_PP_CAT(m_arg, BOOST_PP_INC(n))
Chris@16 334 // m_argn ( argn )
Chris@16 335 #define BOOST_SIGNALS2_MISC_STATEMENT(z, n, data) \
Chris@16 336 BOOST_SIGNALS2_M_ARG_NAME(~, n, ~) ( BOOST_SIGNALS2_SIGNATURE_ARG_NAME(~, n, ~) )
Chris@16 337 // m_arg1(arg1), m_arg2(arg2), ..., m_argn(argn)
Chris@16 338 BOOST_PP_ENUM(BOOST_SIGNALS2_NUM_ARGS, BOOST_SIGNALS2_MISC_STATEMENT, ~)
Chris@16 339 #undef BOOST_SIGNALS2_MISC_STATEMENT
Chris@16 340 {}
Chris@16 341 result_type operator ()(const connection_body_type &connectionBody) const
Chris@16 342 {
Chris@16 343 result_type *resolver = 0;
Chris@16 344 return m_invoke(connectionBody,
Chris@16 345 resolver);
Chris@16 346 }
Chris@16 347 private:
Chris@16 348 // declare assignment operator private since this class might have reference or const members
Chris@16 349 slot_invoker & operator=(const slot_invoker &);
Chris@16 350
Chris@16 351 #define BOOST_SIGNALS2_ADD_REF_M_ARG_STATEMENT(z, n, data) \
Chris@16 352 BOOST_SIGNALS2_ADD_REF_TYPE(~, n, ~) BOOST_SIGNALS2_M_ARG_NAME(~, n, ~) ;
Chris@16 353 BOOST_PP_REPEAT(BOOST_SIGNALS2_NUM_ARGS, BOOST_SIGNALS2_ADD_REF_M_ARG_STATEMENT, ~)
Chris@16 354 #undef BOOST_SIGNALS2_ADD_REF_M_ARG_STATEMENT
Chris@16 355 #undef BOOST_SIGNALS2_ADD_REF_ARG
Chris@16 356 #undef BOOST_SIGNALS2_ADD_REF_TYPE
Chris@16 357
Chris@16 358 // m_arg1, m_arg2, ..., m_argn
Chris@16 359 #define BOOST_SIGNALS2_M_ARG_NAMES(arity) BOOST_PP_ENUM(arity, BOOST_SIGNALS2_M_ARG_NAME, ~)
Chris@16 360 result_type m_invoke(const connection_body_type &connectionBody,
Chris@16 361 const void_type *) const
Chris@16 362 {
Chris@16 363 connectionBody->slot.slot_function()(BOOST_SIGNALS2_M_ARG_NAMES(BOOST_SIGNALS2_NUM_ARGS));
Chris@16 364 return void_type();
Chris@16 365 }
Chris@16 366 result_type m_invoke(const connection_body_type &connectionBody, ...) const
Chris@16 367 {
Chris@16 368 return connectionBody->slot.slot_function()(BOOST_SIGNALS2_M_ARG_NAMES(BOOST_SIGNALS2_NUM_ARGS));
Chris@16 369 }
Chris@16 370 };
Chris@16 371 #undef BOOST_SIGNALS2_M_ARG_NAMES
Chris@16 372 #undef BOOST_SIGNALS2_M_ARG_NAME
Chris@16 373
Chris@16 374 #endif // BOOST_NO_CXX11_VARIADIC_TEMPLATES
Chris@16 375 // a struct used to optimize (minimize) the number of shared_ptrs that need to be created
Chris@16 376 // inside operator()
Chris@16 377 class invocation_state
Chris@16 378 {
Chris@16 379 public:
Chris@16 380 invocation_state(const connection_list_type &connections_in,
Chris@16 381 const combiner_type &combiner_in): _connection_bodies(new connection_list_type(connections_in)),
Chris@16 382 _combiner(new combiner_type(combiner_in))
Chris@16 383 {}
Chris@16 384 invocation_state(const invocation_state &other, const connection_list_type &connections_in):
Chris@16 385 _connection_bodies(new connection_list_type(connections_in)),
Chris@16 386 _combiner(other._combiner)
Chris@16 387 {}
Chris@16 388 invocation_state(const invocation_state &other, const combiner_type &combiner_in):
Chris@16 389 _connection_bodies(other._connection_bodies),
Chris@16 390 _combiner(new combiner_type(combiner_in))
Chris@16 391 {}
Chris@16 392 connection_list_type & connection_bodies() { return *_connection_bodies; }
Chris@16 393 const connection_list_type & connection_bodies() const { return *_connection_bodies; }
Chris@16 394 combiner_type & combiner() { return *_combiner; }
Chris@16 395 const combiner_type & combiner() const { return *_combiner; }
Chris@16 396 private:
Chris@16 397 invocation_state(const invocation_state &);
Chris@16 398
Chris@16 399 shared_ptr<connection_list_type> _connection_bodies;
Chris@16 400 shared_ptr<combiner_type> _combiner;
Chris@16 401 };
Chris@16 402 // Destructor of invocation_janitor does some cleanup when a signal invocation completes.
Chris@16 403 // Code can't be put directly in signal's operator() due to complications from void return types.
Chris@101 404 class invocation_janitor: noncopyable
Chris@16 405 {
Chris@16 406 public:
Chris@16 407 typedef BOOST_SIGNALS2_SIGNAL_IMPL_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS) signal_type;
Chris@16 408 invocation_janitor
Chris@16 409 (
Chris@16 410 const slot_call_iterator_cache_type &cache,
Chris@16 411 const signal_type &sig,
Chris@16 412 const connection_list_type *connection_bodies
Chris@16 413 ):_cache(cache), _sig(sig), _connection_bodies(connection_bodies)
Chris@16 414 {}
Chris@16 415 ~invocation_janitor()
Chris@16 416 {
Chris@16 417 // force a full cleanup of disconnected slots if there are too many
Chris@16 418 if(_cache.disconnected_slot_count > _cache.connected_slot_count)
Chris@16 419 {
Chris@16 420 _sig.force_cleanup_connections(_connection_bodies);
Chris@16 421 }
Chris@16 422 }
Chris@16 423 private:
Chris@16 424 const slot_call_iterator_cache_type &_cache;
Chris@16 425 const signal_type &_sig;
Chris@16 426 const connection_list_type *_connection_bodies;
Chris@16 427 };
Chris@16 428
Chris@16 429 // clean up disconnected connections
Chris@16 430 void nolock_cleanup_connections_from(bool grab_tracked,
Chris@16 431 const typename connection_list_type::iterator &begin, unsigned count = 0) const
Chris@16 432 {
Chris@16 433 BOOST_ASSERT(_shared_state.unique());
Chris@16 434 typename connection_list_type::iterator it;
Chris@16 435 unsigned i;
Chris@16 436 for(it = begin, i = 0;
Chris@16 437 it != _shared_state->connection_bodies().end() && (count == 0 || i < count);
Chris@16 438 ++i)
Chris@16 439 {
Chris@16 440 bool connected;
Chris@16 441 {
Chris@16 442 unique_lock<connection_body_base> lock(**it);
Chris@16 443 if(grab_tracked)
Chris@16 444 (*it)->nolock_slot_expired();
Chris@16 445 connected = (*it)->nolock_nograb_connected();
Chris@16 446 }// scoped lock destructs here, safe to erase now
Chris@16 447 if(connected == false)
Chris@16 448 {
Chris@16 449 it = _shared_state->connection_bodies().erase((*it)->group_key(), it);
Chris@16 450 }else
Chris@16 451 {
Chris@16 452 ++it;
Chris@16 453 }
Chris@16 454 }
Chris@16 455 _garbage_collector_it = it;
Chris@16 456 }
Chris@16 457 // clean up a few connections in constant time
Chris@16 458 void nolock_cleanup_connections(bool grab_tracked, unsigned count) const
Chris@16 459 {
Chris@16 460 BOOST_ASSERT(_shared_state.unique());
Chris@16 461 typename connection_list_type::iterator begin;
Chris@16 462 if(_garbage_collector_it == _shared_state->connection_bodies().end())
Chris@16 463 {
Chris@16 464 begin = _shared_state->connection_bodies().begin();
Chris@16 465 }else
Chris@16 466 {
Chris@16 467 begin = _garbage_collector_it;
Chris@16 468 }
Chris@16 469 nolock_cleanup_connections_from(grab_tracked, begin, count);
Chris@16 470 }
Chris@16 471 /* Make a new copy of the slot list if it is currently being read somewhere else
Chris@16 472 */
Chris@16 473 void nolock_force_unique_connection_list()
Chris@16 474 {
Chris@16 475 if(_shared_state.unique() == false)
Chris@16 476 {
Chris@16 477 _shared_state.reset(new invocation_state(*_shared_state, _shared_state->connection_bodies()));
Chris@16 478 nolock_cleanup_connections_from(true, _shared_state->connection_bodies().begin());
Chris@16 479 }else
Chris@16 480 {
Chris@16 481 /* We need to try and check more than just 1 connection here to avoid corner
Chris@16 482 cases where certain repeated connect/disconnect patterns cause the slot
Chris@16 483 list to grow without limit. */
Chris@16 484 nolock_cleanup_connections(true, 2);
Chris@16 485 }
Chris@16 486 }
Chris@16 487 // force a full cleanup of the connection list
Chris@16 488 void force_cleanup_connections(const connection_list_type *connection_bodies) const
Chris@16 489 {
Chris@16 490 unique_lock<mutex_type> list_lock(_mutex);
Chris@16 491 // if the connection list passed in as a parameter is no longer in use,
Chris@16 492 // we don't need to do any cleanup.
Chris@16 493 if(&_shared_state->connection_bodies() != connection_bodies)
Chris@16 494 {
Chris@16 495 return;
Chris@16 496 }
Chris@16 497 if(_shared_state.unique() == false)
Chris@16 498 {
Chris@16 499 _shared_state.reset(new invocation_state(*_shared_state, _shared_state->connection_bodies()));
Chris@16 500 }
Chris@16 501 nolock_cleanup_connections_from(false, _shared_state->connection_bodies().begin());
Chris@16 502 }
Chris@16 503 shared_ptr<invocation_state> get_readable_state() const
Chris@16 504 {
Chris@16 505 unique_lock<mutex_type> list_lock(_mutex);
Chris@16 506 return _shared_state;
Chris@16 507 }
Chris@16 508 connection_body_type create_new_connection(const slot_type &slot)
Chris@16 509 {
Chris@16 510 nolock_force_unique_connection_list();
Chris@16 511 return connection_body_type(new connection_body<group_key_type, slot_type, Mutex>(slot));
Chris@16 512 }
Chris@16 513 void do_disconnect(const group_type &group, mpl::bool_<true> /* is_group */)
Chris@16 514 {
Chris@16 515 disconnect(group);
Chris@16 516 }
Chris@16 517 template<typename T>
Chris@16 518 void do_disconnect(const T &slot, mpl::bool_<false> /* is_group */)
Chris@16 519 {
Chris@16 520 shared_ptr<invocation_state> local_state =
Chris@16 521 get_readable_state();
Chris@16 522 typename connection_list_type::iterator it;
Chris@16 523 for(it = local_state->connection_bodies().begin();
Chris@16 524 it != local_state->connection_bodies().end(); ++it)
Chris@16 525 {
Chris@16 526 unique_lock<connection_body_base> lock(**it);
Chris@16 527 if((*it)->slot.slot_function() == slot)
Chris@16 528 {
Chris@16 529 (*it)->nolock_disconnect();
Chris@16 530 }else
Chris@16 531 {
Chris@16 532 // check for wrapped extended slot
Chris@16 533 bound_extended_slot_function_type *fp;
Chris@16 534 fp = (*it)->slot.slot_function().template target<bound_extended_slot_function_type>();
Chris@16 535 if(fp && *fp == slot)
Chris@16 536 {
Chris@16 537 (*it)->nolock_disconnect();
Chris@16 538 }
Chris@16 539 }
Chris@16 540 }
Chris@16 541 }
Chris@16 542 // connect slot
Chris@16 543 connection nolock_connect(const slot_type &slot, connect_position position)
Chris@16 544 {
Chris@16 545 connection_body_type newConnectionBody =
Chris@16 546 create_new_connection(slot);
Chris@16 547 group_key_type group_key;
Chris@16 548 if(position == at_back)
Chris@16 549 {
Chris@16 550 group_key.first = back_ungrouped_slots;
Chris@16 551 _shared_state->connection_bodies().push_back(group_key, newConnectionBody);
Chris@16 552 }else
Chris@16 553 {
Chris@16 554 group_key.first = front_ungrouped_slots;
Chris@16 555 _shared_state->connection_bodies().push_front(group_key, newConnectionBody);
Chris@16 556 }
Chris@16 557 newConnectionBody->set_group_key(group_key);
Chris@16 558 return connection(newConnectionBody);
Chris@16 559 }
Chris@16 560 connection nolock_connect(const group_type &group,
Chris@16 561 const slot_type &slot, connect_position position)
Chris@16 562 {
Chris@16 563 connection_body_type newConnectionBody =
Chris@16 564 create_new_connection(slot);
Chris@16 565 // update map to first connection body in group if needed
Chris@16 566 group_key_type group_key(grouped_slots, group);
Chris@16 567 newConnectionBody->set_group_key(group_key);
Chris@16 568 if(position == at_back)
Chris@16 569 {
Chris@16 570 _shared_state->connection_bodies().push_back(group_key, newConnectionBody);
Chris@16 571 }else // at_front
Chris@16 572 {
Chris@16 573 _shared_state->connection_bodies().push_front(group_key, newConnectionBody);
Chris@16 574 }
Chris@16 575 return connection(newConnectionBody);
Chris@16 576 }
Chris@16 577
Chris@16 578 // _shared_state is mutable so we can do force_cleanup_connections during a const invocation
Chris@16 579 mutable shared_ptr<invocation_state> _shared_state;
Chris@16 580 mutable typename connection_list_type::iterator _garbage_collector_it;
Chris@16 581 // connection list mutex must never be locked when attempting a blocking lock on a slot,
Chris@16 582 // or you could deadlock.
Chris@16 583 mutable mutex_type _mutex;
Chris@16 584 };
Chris@16 585
Chris@16 586 template<BOOST_SIGNALS2_SIGNAL_TEMPLATE_DECL(BOOST_SIGNALS2_NUM_ARGS)>
Chris@16 587 class BOOST_SIGNALS2_WEAK_SIGNAL_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS);
Chris@16 588 }
Chris@16 589
Chris@16 590 template<BOOST_SIGNALS2_SIGNAL_TEMPLATE_DEFAULTED_DECL(BOOST_SIGNALS2_NUM_ARGS)>
Chris@16 591 class BOOST_SIGNALS2_SIGNAL_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS);
Chris@16 592
Chris@16 593 template<BOOST_SIGNALS2_SIGNAL_TEMPLATE_SPECIALIZATION_DECL(BOOST_SIGNALS2_NUM_ARGS)>
Chris@16 594 class BOOST_SIGNALS2_SIGNAL_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS)
Chris@16 595 BOOST_SIGNALS2_SIGNAL_TEMPLATE_SPECIALIZATION: public signal_base,
Chris@16 596 public detail::BOOST_SIGNALS2_STD_FUNCTIONAL_BASE
Chris@16 597 (typename detail::result_type_wrapper<typename Combiner::result_type>::type)
Chris@16 598 {
Chris@16 599 typedef detail::BOOST_SIGNALS2_SIGNAL_IMPL_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS)
Chris@16 600 <BOOST_SIGNALS2_SIGNAL_TEMPLATE_INSTANTIATION> impl_class;
Chris@16 601 public:
Chris@16 602 typedef detail::BOOST_SIGNALS2_WEAK_SIGNAL_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS)
Chris@16 603 <BOOST_SIGNALS2_SIGNAL_TEMPLATE_INSTANTIATION> weak_signal_type;
Chris@16 604 friend class detail::BOOST_SIGNALS2_WEAK_SIGNAL_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS)
Chris@16 605 <BOOST_SIGNALS2_SIGNAL_TEMPLATE_INSTANTIATION>;
Chris@16 606
Chris@16 607 typedef SlotFunction slot_function_type;
Chris@16 608 // typedef slotN<Signature, SlotFunction> slot_type;
Chris@16 609 typedef typename impl_class::slot_type slot_type;
Chris@16 610 typedef typename impl_class::extended_slot_function_type extended_slot_function_type;
Chris@16 611 typedef typename impl_class::extended_slot_type extended_slot_type;
Chris@16 612 typedef typename slot_function_type::result_type slot_result_type;
Chris@16 613 typedef Combiner combiner_type;
Chris@16 614 typedef typename impl_class::result_type result_type;
Chris@16 615 typedef Group group_type;
Chris@16 616 typedef GroupCompare group_compare_type;
Chris@16 617 typedef typename impl_class::slot_call_iterator
Chris@16 618 slot_call_iterator;
Chris@16 619 typedef typename mpl::identity<BOOST_SIGNALS2_SIGNATURE_FUNCTION_TYPE(BOOST_SIGNALS2_NUM_ARGS)>::type signature_type;
Chris@16 620
Chris@16 621 #ifdef BOOST_NO_CXX11_VARIADIC_TEMPLATES
Chris@16 622
Chris@16 623 // typedef Tn argn_type;
Chris@16 624 #define BOOST_SIGNALS2_MISC_STATEMENT(z, n, data) \
Chris@16 625 typedef BOOST_PP_CAT(T, BOOST_PP_INC(n)) BOOST_PP_CAT(BOOST_PP_CAT(arg, BOOST_PP_INC(n)), _type);
Chris@16 626 BOOST_PP_REPEAT(BOOST_SIGNALS2_NUM_ARGS, BOOST_SIGNALS2_MISC_STATEMENT, ~)
Chris@16 627 #undef BOOST_SIGNALS2_MISC_STATEMENT
Chris@16 628 #if BOOST_SIGNALS2_NUM_ARGS == 1
Chris@16 629 typedef arg1_type argument_type;
Chris@16 630 #elif BOOST_SIGNALS2_NUM_ARGS == 2
Chris@16 631 typedef arg1_type first_argument_type;
Chris@16 632 typedef arg2_type second_argument_type;
Chris@16 633 #endif
Chris@16 634
Chris@16 635 template<unsigned n> class arg : public
Chris@16 636 detail::BOOST_SIGNALS2_PREPROCESSED_ARG_N_TYPE_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS)
Chris@16 637 <n BOOST_SIGNALS2_PP_COMMA_IF(BOOST_SIGNALS2_NUM_ARGS)
Chris@16 638 BOOST_SIGNALS2_ARGS_TEMPLATE_INSTANTIATION(BOOST_SIGNALS2_NUM_ARGS)>
Chris@16 639 {};
Chris@16 640
Chris@16 641 BOOST_STATIC_CONSTANT(int, arity = BOOST_SIGNALS2_NUM_ARGS);
Chris@16 642
Chris@16 643 #else // BOOST_NO_CXX11_VARIADIC_TEMPLATES
Chris@16 644
Chris@16 645 template<unsigned n> class arg
Chris@16 646 {
Chris@16 647 public:
Chris@16 648 typedef typename detail::variadic_arg_type<n, Args...>::type type;
Chris@16 649 };
Chris@16 650 BOOST_STATIC_CONSTANT(int, arity = sizeof...(Args));
Chris@16 651
Chris@16 652 #endif // BOOST_NO_CXX11_VARIADIC_TEMPLATES
Chris@16 653
Chris@16 654 BOOST_SIGNALS2_SIGNAL_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS)(const combiner_type &combiner_arg = combiner_type(),
Chris@16 655 const group_compare_type &group_compare = group_compare_type()):
Chris@16 656 _pimpl(new impl_class(combiner_arg, group_compare))
Chris@16 657 {};
Chris@16 658 virtual ~BOOST_SIGNALS2_SIGNAL_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS)()
Chris@16 659 {
Chris@16 660 }
Chris@101 661
Chris@101 662 //move support
Chris@101 663 #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
Chris@101 664 BOOST_SIGNALS2_SIGNAL_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS)(
Chris@101 665 BOOST_SIGNALS2_SIGNAL_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS) && other)
Chris@101 666 {
Chris@101 667 using std::swap;
Chris@101 668 swap(_pimpl, other._pimpl);
Chris@101 669 };
Chris@101 670
Chris@101 671 BOOST_SIGNALS2_SIGNAL_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS) &
Chris@101 672 operator=(BOOST_SIGNALS2_SIGNAL_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS) && rhs)
Chris@101 673 {
Chris@101 674 if(this == &rhs)
Chris@101 675 {
Chris@101 676 return *this;
Chris@101 677 }
Chris@101 678 _pimpl.reset();
Chris@101 679 using std::swap;
Chris@101 680 swap(_pimpl, rhs._pimpl);
Chris@101 681 return *this;
Chris@101 682 }
Chris@101 683 #endif // !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
Chris@101 684
Chris@16 685 connection connect(const slot_type &slot, connect_position position = at_back)
Chris@16 686 {
Chris@16 687 return (*_pimpl).connect(slot, position);
Chris@16 688 }
Chris@16 689 connection connect(const group_type &group,
Chris@16 690 const slot_type &slot, connect_position position = at_back)
Chris@16 691 {
Chris@16 692 return (*_pimpl).connect(group, slot, position);
Chris@16 693 }
Chris@16 694 connection connect_extended(const extended_slot_type &slot, connect_position position = at_back)
Chris@16 695 {
Chris@16 696 return (*_pimpl).connect_extended(slot, position);
Chris@16 697 }
Chris@16 698 connection connect_extended(const group_type &group,
Chris@16 699 const extended_slot_type &slot, connect_position position = at_back)
Chris@16 700 {
Chris@16 701 return (*_pimpl).connect_extended(group, slot, position);
Chris@16 702 }
Chris@16 703 void disconnect_all_slots()
Chris@16 704 {
Chris@16 705 (*_pimpl).disconnect_all_slots();
Chris@16 706 }
Chris@16 707 void disconnect(const group_type &group)
Chris@16 708 {
Chris@16 709 (*_pimpl).disconnect(group);
Chris@16 710 }
Chris@16 711 template <typename T>
Chris@16 712 void disconnect(const T &slot)
Chris@16 713 {
Chris@16 714 (*_pimpl).disconnect(slot);
Chris@16 715 }
Chris@16 716 result_type operator ()(BOOST_SIGNALS2_SIGNATURE_FULL_ARGS(BOOST_SIGNALS2_NUM_ARGS))
Chris@16 717 {
Chris@16 718 return (*_pimpl)(BOOST_SIGNALS2_SIGNATURE_ARG_NAMES(BOOST_SIGNALS2_NUM_ARGS));
Chris@16 719 }
Chris@16 720 result_type operator ()(BOOST_SIGNALS2_SIGNATURE_FULL_ARGS(BOOST_SIGNALS2_NUM_ARGS)) const
Chris@16 721 {
Chris@16 722 return (*_pimpl)(BOOST_SIGNALS2_SIGNATURE_ARG_NAMES(BOOST_SIGNALS2_NUM_ARGS));
Chris@16 723 }
Chris@16 724 std::size_t num_slots() const
Chris@16 725 {
Chris@16 726 return (*_pimpl).num_slots();
Chris@16 727 }
Chris@16 728 bool empty() const
Chris@16 729 {
Chris@16 730 return (*_pimpl).empty();
Chris@16 731 }
Chris@16 732 combiner_type combiner() const
Chris@16 733 {
Chris@16 734 return (*_pimpl).combiner();
Chris@16 735 }
Chris@16 736 void set_combiner(const combiner_type &combiner_arg)
Chris@16 737 {
Chris@16 738 return (*_pimpl).set_combiner(combiner_arg);
Chris@16 739 }
Chris@16 740 void swap(BOOST_SIGNALS2_SIGNAL_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS) & other)
Chris@16 741 {
Chris@16 742 using std::swap;
Chris@16 743 swap(_pimpl, other._pimpl);
Chris@16 744 }
Chris@16 745 protected:
Chris@16 746 virtual shared_ptr<void> lock_pimpl() const
Chris@16 747 {
Chris@16 748 return _pimpl;
Chris@16 749 }
Chris@16 750 private:
Chris@16 751 shared_ptr<impl_class>
Chris@16 752 _pimpl;
Chris@16 753 };
Chris@16 754
Chris@16 755 #ifdef BOOST_NO_CXX11_VARIADIC_TEMPLATES
Chris@16 756 // free swap function for signalN classes, findable by ADL
Chris@16 757 template<BOOST_SIGNALS2_SIGNAL_TEMPLATE_DECL(BOOST_SIGNALS2_NUM_ARGS)>
Chris@16 758 void swap(
Chris@16 759 BOOST_SIGNALS2_SIGNAL_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS) <BOOST_SIGNALS2_SIGNAL_TEMPLATE_INSTANTIATION> &sig1,
Chris@16 760 BOOST_SIGNALS2_SIGNAL_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS) <BOOST_SIGNALS2_SIGNAL_TEMPLATE_INSTANTIATION> &sig2 )
Chris@16 761 {
Chris@16 762 sig1.swap(sig2);
Chris@16 763 }
Chris@16 764 #endif
Chris@16 765
Chris@16 766 namespace detail
Chris@16 767 {
Chris@16 768 // wrapper class for storing other signals as slots with automatic lifetime tracking
Chris@16 769 template<BOOST_SIGNALS2_SIGNAL_TEMPLATE_DECL(BOOST_SIGNALS2_NUM_ARGS)>
Chris@16 770 class BOOST_SIGNALS2_WEAK_SIGNAL_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS);
Chris@16 771
Chris@16 772 template<BOOST_SIGNALS2_SIGNAL_TEMPLATE_SPECIALIZATION_DECL(BOOST_SIGNALS2_NUM_ARGS)>
Chris@16 773 class BOOST_SIGNALS2_WEAK_SIGNAL_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS)
Chris@16 774 BOOST_SIGNALS2_SIGNAL_TEMPLATE_SPECIALIZATION
Chris@16 775 {
Chris@16 776 public:
Chris@16 777 typedef typename BOOST_SIGNALS2_SIGNAL_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS)
Chris@16 778 <BOOST_SIGNALS2_SIGNAL_TEMPLATE_INSTANTIATION>::result_type
Chris@16 779 result_type;
Chris@16 780
Chris@16 781 BOOST_SIGNALS2_WEAK_SIGNAL_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS)
Chris@16 782 (const BOOST_SIGNALS2_SIGNAL_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS)
Chris@16 783 <BOOST_SIGNALS2_SIGNAL_TEMPLATE_INSTANTIATION>
Chris@16 784 &signal):
Chris@16 785 _weak_pimpl(signal._pimpl)
Chris@16 786 {}
Chris@16 787 result_type operator ()(BOOST_SIGNALS2_SIGNATURE_FULL_ARGS(BOOST_SIGNALS2_NUM_ARGS))
Chris@16 788 {
Chris@16 789 shared_ptr<detail::BOOST_SIGNALS2_SIGNAL_IMPL_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS)
Chris@16 790 <BOOST_SIGNALS2_SIGNAL_TEMPLATE_INSTANTIATION> >
Chris@16 791 shared_pimpl(_weak_pimpl.lock());
Chris@16 792 if(shared_pimpl == 0) boost::throw_exception(expired_slot());
Chris@16 793 return (*shared_pimpl)(BOOST_SIGNALS2_SIGNATURE_ARG_NAMES(BOOST_SIGNALS2_NUM_ARGS));
Chris@16 794 }
Chris@16 795 result_type operator ()(BOOST_SIGNALS2_SIGNATURE_FULL_ARGS(BOOST_SIGNALS2_NUM_ARGS)) const
Chris@16 796 {
Chris@16 797 shared_ptr<detail::BOOST_SIGNALS2_SIGNAL_IMPL_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS)
Chris@16 798 <BOOST_SIGNALS2_SIGNAL_TEMPLATE_INSTANTIATION> >
Chris@16 799 shared_pimpl(_weak_pimpl.lock());
Chris@16 800 if(shared_pimpl == 0) boost::throw_exception(expired_slot());
Chris@16 801 return (*shared_pimpl)(BOOST_SIGNALS2_SIGNATURE_ARG_NAMES(BOOST_SIGNALS2_NUM_ARGS));
Chris@16 802 }
Chris@16 803 private:
Chris@16 804 boost::weak_ptr<detail::BOOST_SIGNALS2_SIGNAL_IMPL_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS)
Chris@16 805 <BOOST_SIGNALS2_SIGNAL_TEMPLATE_INSTANTIATION> > _weak_pimpl;
Chris@16 806 };
Chris@16 807
Chris@16 808 #ifndef BOOST_NO_CXX11_VARIADIC_TEMPLATES
Chris@16 809 template<int arity, typename Signature>
Chris@16 810 class extended_signature: public variadic_extended_signature<Signature>
Chris@16 811 {};
Chris@16 812 #else // BOOST_NO_CXX11_VARIADIC_TEMPLATES
Chris@16 813 template<int arity, typename Signature>
Chris@16 814 class extended_signature;
Chris@16 815 // partial template specialization
Chris@16 816 template<typename Signature>
Chris@16 817 class extended_signature<BOOST_SIGNALS2_NUM_ARGS, Signature>
Chris@16 818 {
Chris@16 819 public:
Chris@16 820 // typename function_traits<Signature>::result_type (
Chris@16 821 // const boost::signals2::connection &,
Chris@16 822 // typename function_traits<Signature>::arg1_type,
Chris@16 823 // typename function_traits<Signature>::arg2_type,
Chris@16 824 // ...,
Chris@16 825 // typename function_traits<Signature>::argn_type)
Chris@16 826 #define BOOST_SIGNALS2_EXT_SIGNATURE(arity, Signature) \
Chris@16 827 typename function_traits<Signature>::result_type ( \
Chris@16 828 const boost::signals2::connection & BOOST_SIGNALS2_PP_COMMA_IF(BOOST_SIGNALS2_NUM_ARGS) \
Chris@16 829 BOOST_PP_ENUM(arity, BOOST_SIGNALS2_SIGNATURE_TO_ARGN_TYPE, Signature) )
Chris@16 830 typedef function<BOOST_SIGNALS2_EXT_SIGNATURE(BOOST_SIGNALS2_NUM_ARGS, Signature)> function_type;
Chris@16 831 #undef BOOST_SIGNALS2_EXT_SIGNATURE
Chris@16 832 };
Chris@16 833
Chris@16 834 template<unsigned arity, typename Signature, typename Combiner,
Chris@16 835 typename Group, typename GroupCompare, typename SlotFunction,
Chris@16 836 typename ExtendedSlotFunction, typename Mutex>
Chris@16 837 class signalN;
Chris@16 838 // partial template specialization
Chris@16 839 template<typename Signature, typename Combiner, typename Group,
Chris@16 840 typename GroupCompare, typename SlotFunction,
Chris@16 841 typename ExtendedSlotFunction, typename Mutex>
Chris@16 842 class signalN<BOOST_SIGNALS2_NUM_ARGS, Signature, Combiner, Group,
Chris@16 843 GroupCompare, SlotFunction, ExtendedSlotFunction, Mutex>
Chris@16 844 {
Chris@16 845 public:
Chris@16 846 typedef BOOST_SIGNALS2_SIGNAL_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS)<
Chris@16 847 BOOST_SIGNALS2_PORTABLE_SIGNATURE(BOOST_SIGNALS2_NUM_ARGS, Signature),
Chris@16 848 Combiner, Group,
Chris@16 849 GroupCompare, SlotFunction, ExtendedSlotFunction, Mutex> type;
Chris@16 850 };
Chris@16 851
Chris@16 852 #endif // BOOST_NO_CXX11_VARIADIC_TEMPLATES
Chris@16 853
Chris@16 854 } // namespace detail
Chris@16 855 } // namespace signals2
Chris@16 856 } // namespace boost
Chris@16 857
Chris@16 858 #undef BOOST_SIGNALS2_NUM_ARGS
Chris@16 859 #undef BOOST_SIGNALS2_SIGNAL_TEMPLATE_INSTANTIATION