LCOV - code coverage report
Current view: top level - opt/homebrew/include/boost/signals2/detail - signal_template.hpp (source / functions) Hit Total Coverage
Test: total_coverage.info Lines: 114 136 83.8 %
Date: 2026-06-25 07:23:43 Functions: 324 469 69.1 %

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

Generated by: LCOV version 1.16