ossrv_pub/boost_apis/boost/signals/signal_template.hpp
changeset 0 e4d67989cc36
equal deleted inserted replaced
-1:000000000000 0:e4d67989cc36
       
     1 // Boost.Signals library
       
     2 
       
     3 // Copyright Douglas Gregor 2001-2004. Use, modification and
       
     4 // distribution is subject to the Boost Software License, Version
       
     5 // 1.0. (See accompanying file LICENSE_1_0.txt or copy at
       
     6 // http://www.boost.org/LICENSE_1_0.txt)
       
     7 
       
     8 // For more information, see http://www.boost.org
       
     9 
       
    10 // This file intentionally does not have include guards, because it is meant
       
    11 // to be included multiple times (one for each signalN class). The
       
    12 // BOOST_SIGNALS_SIGNAL_TEMPLATE_HEADER_INCLUDED macro merely serves to
       
    13 // suppress reinclusion of the files that this header depends on.
       
    14 
       
    15 #ifndef BOOST_SIGNALS_SIGNAL_TEMPLATE_HEADER_INCLUDED
       
    16 #define BOOST_SIGNALS_SIGNAL_TEMPLATE_HEADER_INCLUDED
       
    17 #  include <boost/config.hpp>
       
    18 #  include <boost/signals/connection.hpp>
       
    19 #  include <boost/utility.hpp>
       
    20 #  include <boost/ref.hpp>
       
    21 #  include <boost/signals/slot.hpp>
       
    22 #  include <boost/last_value.hpp>
       
    23 #  include <boost/signals/detail/signal_base.hpp>
       
    24 #  include <boost/signals/detail/slot_call_iterator.hpp>
       
    25 #  include <boost/mpl/bool.hpp>
       
    26 #  include <boost/type_traits/is_convertible.hpp>
       
    27 #  include <cassert>
       
    28 #  include <functional>
       
    29 #  include <memory>
       
    30 #endif // !BOOST_SIGNALS_SIGNAL_TEMPLATE_HEADER_INCLUDED
       
    31 
       
    32 #ifdef BOOST_HAS_ABI_HEADERS
       
    33 #  include BOOST_ABI_PREFIX
       
    34 #endif
       
    35 
       
    36 // Include the appropriate functionN header
       
    37 #define BOOST_SIGNAL_FUNCTION_N_HEADER BOOST_JOIN(<boost/function/function,BOOST_SIGNALS_NUM_ARGS.hpp>)
       
    38 #include BOOST_SIGNAL_FUNCTION_N_HEADER
       
    39 
       
    40 // Determine if a comma should follow a listing of the arguments/parameters
       
    41 #if BOOST_SIGNALS_NUM_ARGS == 0
       
    42 #  define BOOST_SIGNALS_COMMA_IF_NONZERO_ARGS
       
    43 #else
       
    44 #  define BOOST_SIGNALS_COMMA_IF_NONZERO_ARGS ,
       
    45 #endif // BOOST_SIGNALS_NUM_ARGS > 0
       
    46 
       
    47 // Define class names used
       
    48 #define BOOST_SIGNALS_SIGNAL BOOST_JOIN(signal,BOOST_SIGNALS_NUM_ARGS)
       
    49 #define BOOST_SIGNALS_FUNCTION BOOST_JOIN(function,BOOST_SIGNALS_NUM_ARGS)
       
    50 #define BOOST_SIGNALS_ARGS_STRUCT BOOST_JOIN(args,BOOST_SIGNALS_NUM_ARGS)
       
    51 #define BOOST_SIGNALS_CALL_BOUND BOOST_JOIN(call_bound,BOOST_SIGNALS_NUM_ARGS)
       
    52 
       
    53 // Define commonly-used instantiations
       
    54 #define BOOST_SIGNALS_ARGS_STRUCT_INST \
       
    55   BOOST_SIGNALS_NAMESPACE::detail::BOOST_SIGNALS_ARGS_STRUCT<BOOST_SIGNALS_TEMPLATE_ARGS>
       
    56 
       
    57 namespace boost {
       
    58   namespace BOOST_SIGNALS_NAMESPACE {
       
    59     namespace detail {
       
    60       // Holds the arguments for a bound slot call in a single place
       
    61       template<BOOST_SIGNALS_TEMPLATE_PARMS
       
    62                BOOST_SIGNALS_COMMA_IF_NONZERO_ARGS
       
    63                typename Dummy = int>
       
    64       struct BOOST_SIGNALS_ARGS_STRUCT {
       
    65         BOOST_SIGNALS_ARGS_STRUCT(BOOST_SIGNALS_COPY_PARMS)
       
    66           BOOST_SIGNALS_INIT_ARGS
       
    67         {
       
    68         }
       
    69 
       
    70         BOOST_SIGNALS_ARGS_AS_MEMBERS
       
    71       };
       
    72 
       
    73       // Function object that calls the function object given to it, passing
       
    74       // the bound arguments along to that underlying function object
       
    75       template<typename R>
       
    76       struct BOOST_SIGNALS_CALL_BOUND {
       
    77         template<BOOST_SIGNALS_TEMPLATE_PARMS
       
    78                  BOOST_SIGNALS_COMMA_IF_NONZERO_ARGS
       
    79                  typename F>
       
    80         struct caller {
       
    81           typedef BOOST_SIGNALS_ARGS_STRUCT<BOOST_SIGNALS_TEMPLATE_ARGS>*
       
    82             args_type;
       
    83 
       
    84           args_type args;
       
    85 
       
    86           typedef R result_type;
       
    87 
       
    88           caller() {}
       
    89           caller(args_type a) : args(a) {}
       
    90 
       
    91           template<typename Pair>
       
    92           R operator()(const Pair& slot) const
       
    93           {
       
    94             F* target = const_cast<F*>(unsafe_any_cast<F>(&slot.second));
       
    95             return (*target)(BOOST_SIGNALS_BOUND_ARGS);
       
    96           }
       
    97         };
       
    98       };
       
    99 
       
   100       template<>
       
   101       struct BOOST_SIGNALS_CALL_BOUND<void> {
       
   102         template<BOOST_SIGNALS_TEMPLATE_PARMS
       
   103                  BOOST_SIGNALS_COMMA_IF_NONZERO_ARGS
       
   104                  typename F>
       
   105         struct caller {
       
   106           typedef BOOST_SIGNALS_ARGS_STRUCT<BOOST_SIGNALS_TEMPLATE_ARGS>*
       
   107             args_type;
       
   108 
       
   109           args_type args;
       
   110 
       
   111           typedef unusable result_type;
       
   112 
       
   113           caller(args_type a) : args(a) {}
       
   114 
       
   115           template<typename Pair>
       
   116           unusable operator()(const Pair& slot) const
       
   117           {
       
   118             F* target = const_cast<F*>(unsafe_any_cast<F>(&slot.second));
       
   119             (*target)(BOOST_SIGNALS_BOUND_ARGS);
       
   120             return unusable();
       
   121           }
       
   122         };
       
   123       };
       
   124     } // namespace detail
       
   125   } // namespace BOOST_SIGNALS_NAMESPACE
       
   126 
       
   127   // The actual signalN class
       
   128   template<
       
   129     typename R,
       
   130     BOOST_SIGNALS_TEMPLATE_PARMS
       
   131     BOOST_SIGNALS_COMMA_IF_NONZERO_ARGS
       
   132     typename Combiner = last_value<R>,
       
   133     typename Group = int,
       
   134     typename GroupCompare = std::less<Group>,
       
   135     typename SlotFunction = BOOST_SIGNALS_FUNCTION<
       
   136                               R BOOST_SIGNALS_COMMA_IF_NONZERO_ARGS
       
   137                               BOOST_SIGNALS_TEMPLATE_ARGS>
       
   138   >
       
   139   class BOOST_SIGNALS_SIGNAL :
       
   140     public BOOST_SIGNALS_NAMESPACE::detail::signal_base, // management of slot list
       
   141     public BOOST_SIGNALS_NAMESPACE::trackable // signals are trackable
       
   142   {
       
   143   public:
       
   144     // The slot function type
       
   145     typedef SlotFunction slot_function_type;
       
   146 
       
   147     // Result type of a slot
       
   148     typedef typename BOOST_SIGNALS_NAMESPACE::detail::slot_result_type<R>::type
       
   149       slot_result_type;
       
   150 
       
   151     // Argument types
       
   152     BOOST_SIGNALS_ARG_TYPES
       
   153 
       
   154 #if BOOST_SIGNALS_NUM_ARGS == 1
       
   155     typedef T1 argument_type;
       
   156 #elif BOOST_SIGNALS_NUM_ARGS == 2
       
   157     typedef T1 first_argument_type;
       
   158     typedef T2 second_argument_type;
       
   159 #endif
       
   160 
       
   161   private:
       
   162     // The real slot name comparison object type
       
   163     typedef BOOST_SIGNALS_NAMESPACE::detail::group_bridge_compare<GroupCompare, Group>
       
   164       real_group_compare_type;
       
   165 
       
   166     // The function object passed to the slot call iterator that will call
       
   167     // the underlying slot function with its arguments bound
       
   168     typedef BOOST_SIGNALS_NAMESPACE::detail::BOOST_SIGNALS_CALL_BOUND<R>
       
   169       outer_bound_slot_caller;
       
   170     typedef typename outer_bound_slot_caller::template
       
   171               caller<BOOST_SIGNALS_TEMPLATE_ARGS
       
   172                      BOOST_SIGNALS_COMMA_IF_NONZERO_ARGS
       
   173                      slot_function_type>
       
   174       call_bound_slot;
       
   175 
       
   176   public:
       
   177     // Combiner's result type
       
   178     typedef typename Combiner::result_type result_type;
       
   179 
       
   180     // Combiner type
       
   181     typedef Combiner combiner_type;
       
   182 
       
   183     // Slot type
       
   184     typedef slot<slot_function_type> slot_type;
       
   185 
       
   186     // Slot name type and comparison
       
   187     typedef Group group_type;
       
   188     typedef GroupCompare group_compare_type;
       
   189 
       
   190     typedef BOOST_SIGNALS_NAMESPACE::detail::slot_call_iterator<
       
   191               call_bound_slot, iterator> slot_call_iterator;
       
   192 
       
   193     explicit
       
   194     BOOST_SIGNALS_SIGNAL(const Combiner& c = Combiner(),
       
   195                          const GroupCompare& comp = GroupCompare()) :
       
   196       BOOST_SIGNALS_NAMESPACE::detail::signal_base(real_group_compare_type(comp),
       
   197                                                    c)
       
   198     {
       
   199     }
       
   200 
       
   201     // Connect a slot to this signal
       
   202     BOOST_SIGNALS_NAMESPACE::connection
       
   203     connect(const slot_type&,
       
   204             BOOST_SIGNALS_NAMESPACE::connect_position at
       
   205               = BOOST_SIGNALS_NAMESPACE::at_back);
       
   206 
       
   207 
       
   208     BOOST_SIGNALS_NAMESPACE::connection
       
   209     connect(const group_type&, const slot_type&,
       
   210             BOOST_SIGNALS_NAMESPACE::connect_position at
       
   211               = BOOST_SIGNALS_NAMESPACE::at_back);
       
   212 
       
   213 #if BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
       
   214     // MSVC 6.0 and 7.0 don't handle the is_convertible test well
       
   215     void disconnect(const group_type& group)
       
   216     {
       
   217       impl->disconnect(group);
       
   218     }
       
   219 #else
       
   220     template<typename T>
       
   221     void disconnect(const T& t)
       
   222     {
       
   223       typedef mpl::bool_<(is_convertible<T, group_type>::value)> is_group;
       
   224       this->do_disconnect(t, is_group());
       
   225     }
       
   226 
       
   227   private:
       
   228     // Disconnect a named slot
       
   229     void do_disconnect(const group_type& group, mpl::bool_<true>)
       
   230     {
       
   231       impl->disconnect(group);
       
   232     }
       
   233 
       
   234     template<typename Function>
       
   235     void do_disconnect(const Function& f, mpl::bool_<false>)
       
   236     {
       
   237       // Notify the slot handling code that we are iterating through the slots
       
   238       BOOST_SIGNALS_NAMESPACE::detail::call_notification notification(this->impl);
       
   239 
       
   240       for (iterator i = impl->slots_.begin(); i != impl->slots_.end(); ++i) {
       
   241         slot_function_type& s = *unsafe_any_cast<slot_function_type>(&i->second);
       
   242         if (s == f) i->first.disconnect();
       
   243       }
       
   244     }
       
   245 #endif
       
   246 
       
   247   public:
       
   248 
       
   249     // Emit the signal
       
   250     result_type operator()(BOOST_SIGNALS_PARMS);
       
   251     result_type operator()(BOOST_SIGNALS_PARMS) const;
       
   252 
       
   253     Combiner& combiner()
       
   254     { return *unsafe_any_cast<Combiner>(&impl->combiner_); }
       
   255 
       
   256     const Combiner& combiner() const
       
   257     { return *unsafe_any_cast<const Combiner>(&impl->combiner_); }
       
   258   };
       
   259 
       
   260   template<
       
   261     typename R,
       
   262     BOOST_SIGNALS_TEMPLATE_PARMS
       
   263     BOOST_SIGNALS_COMMA_IF_NONZERO_ARGS
       
   264     typename Combiner,
       
   265     typename Group,
       
   266     typename GroupCompare,
       
   267     typename SlotFunction
       
   268   >
       
   269   BOOST_SIGNALS_NAMESPACE::connection
       
   270   BOOST_SIGNALS_SIGNAL<
       
   271     R, BOOST_SIGNALS_TEMPLATE_ARGS
       
   272     BOOST_SIGNALS_COMMA_IF_NONZERO_ARGS
       
   273     Combiner, Group, GroupCompare, SlotFunction
       
   274   >::connect(const slot_type& in_slot,
       
   275              BOOST_SIGNALS_NAMESPACE::connect_position at)
       
   276   {
       
   277     using boost::BOOST_SIGNALS_NAMESPACE::detail::stored_group;
       
   278 
       
   279     // If the slot has been disconnected, just return a disconnected
       
   280     // connection
       
   281     if (!in_slot.is_active()) {
       
   282       return BOOST_SIGNALS_NAMESPACE::connection();
       
   283     }
       
   284 
       
   285     return impl->connect_slot(in_slot.get_slot_function(), stored_group(),
       
   286                               in_slot.get_data(), at);
       
   287   }
       
   288 
       
   289   template<
       
   290     typename R,
       
   291     BOOST_SIGNALS_TEMPLATE_PARMS
       
   292     BOOST_SIGNALS_COMMA_IF_NONZERO_ARGS
       
   293     typename Combiner,
       
   294     typename Group,
       
   295     typename GroupCompare,
       
   296     typename SlotFunction
       
   297   >
       
   298   BOOST_SIGNALS_NAMESPACE::connection
       
   299   BOOST_SIGNALS_SIGNAL<
       
   300     R, BOOST_SIGNALS_TEMPLATE_ARGS
       
   301     BOOST_SIGNALS_COMMA_IF_NONZERO_ARGS
       
   302     Combiner, Group, GroupCompare, SlotFunction
       
   303   >::connect(const group_type& group,
       
   304              const slot_type& in_slot,
       
   305              BOOST_SIGNALS_NAMESPACE::connect_position at)
       
   306   {
       
   307     // If the slot has been disconnected, just return a disconnected
       
   308     // connection
       
   309     if (!in_slot.is_active()) {
       
   310       return BOOST_SIGNALS_NAMESPACE::connection();
       
   311     }
       
   312 
       
   313     return impl->connect_slot(in_slot.get_slot_function(), group,
       
   314                               in_slot.get_data(), at);
       
   315   }
       
   316 
       
   317   template<
       
   318     typename R,
       
   319     BOOST_SIGNALS_TEMPLATE_PARMS
       
   320     BOOST_SIGNALS_COMMA_IF_NONZERO_ARGS
       
   321     typename Combiner,
       
   322     typename Group,
       
   323     typename GroupCompare,
       
   324     typename SlotFunction
       
   325   >
       
   326   typename BOOST_SIGNALS_SIGNAL<
       
   327              R, BOOST_SIGNALS_TEMPLATE_ARGS
       
   328              BOOST_SIGNALS_COMMA_IF_NONZERO_ARGS
       
   329              Combiner, Group, GroupCompare, SlotFunction>::result_type
       
   330   BOOST_SIGNALS_SIGNAL<
       
   331     R, BOOST_SIGNALS_TEMPLATE_ARGS
       
   332     BOOST_SIGNALS_COMMA_IF_NONZERO_ARGS
       
   333     Combiner, Group, GroupCompare, SlotFunction
       
   334   >::operator()(BOOST_SIGNALS_PARMS)
       
   335   {
       
   336     // Notify the slot handling code that we are making a call
       
   337     BOOST_SIGNALS_NAMESPACE::detail::call_notification notification(this->impl);
       
   338 
       
   339     // Construct a function object that will call the underlying slots
       
   340     // with the given arguments.
       
   341 #if BOOST_SIGNALS_NUM_ARGS == 0
       
   342     BOOST_SIGNALS_ARGS_STRUCT_INST args;
       
   343 #else
       
   344     BOOST_SIGNALS_ARGS_STRUCT_INST args(BOOST_SIGNALS_ARGS);
       
   345 #endif // BOOST_SIGNALS_NUM_ARGS > 0
       
   346     call_bound_slot f(&args);
       
   347 
       
   348     typedef typename call_bound_slot::result_type result_type;
       
   349     optional<result_type> cache;
       
   350     // Let the combiner call the slots via a pair of input iterators
       
   351     return combiner()(slot_call_iterator(notification.impl->slots_.begin(),
       
   352                                          impl->slots_.end(), f, cache),
       
   353                       slot_call_iterator(notification.impl->slots_.end(),
       
   354                                          impl->slots_.end(), f, cache));
       
   355   }
       
   356 
       
   357   template<
       
   358     typename R,
       
   359     BOOST_SIGNALS_TEMPLATE_PARMS
       
   360     BOOST_SIGNALS_COMMA_IF_NONZERO_ARGS
       
   361     typename Combiner,
       
   362     typename Group,
       
   363     typename GroupCompare,
       
   364     typename SlotFunction
       
   365   >
       
   366   typename BOOST_SIGNALS_SIGNAL<
       
   367              R, BOOST_SIGNALS_TEMPLATE_ARGS
       
   368              BOOST_SIGNALS_COMMA_IF_NONZERO_ARGS
       
   369              Combiner, Group, GroupCompare, SlotFunction>::result_type
       
   370   BOOST_SIGNALS_SIGNAL<
       
   371     R, BOOST_SIGNALS_TEMPLATE_ARGS
       
   372     BOOST_SIGNALS_COMMA_IF_NONZERO_ARGS
       
   373     Combiner, Group, GroupCompare, SlotFunction
       
   374   >::operator()(BOOST_SIGNALS_PARMS) const
       
   375   {
       
   376     // Notify the slot handling code that we are making a call
       
   377     BOOST_SIGNALS_NAMESPACE::detail::call_notification notification(this->impl);
       
   378 
       
   379     // Construct a function object that will call the underlying slots
       
   380     // with the given arguments.
       
   381 #if BOOST_SIGNALS_NUM_ARGS == 0
       
   382     BOOST_SIGNALS_ARGS_STRUCT_INST args;
       
   383 #else
       
   384     BOOST_SIGNALS_ARGS_STRUCT_INST args(BOOST_SIGNALS_ARGS);
       
   385 #endif // BOOST_SIGNALS_NUM_ARGS > 0
       
   386 
       
   387     call_bound_slot f(&args);
       
   388 
       
   389     typedef typename call_bound_slot::result_type result_type;
       
   390     optional<result_type> cache;
       
   391 
       
   392     // Let the combiner call the slots via a pair of input iterators
       
   393     return combiner()(slot_call_iterator(notification.impl->slots_.begin(),
       
   394                                          impl->slots_.end(), f, cache),
       
   395                       slot_call_iterator(notification.impl->slots_.end(),
       
   396                                          impl->slots_.end(), f, cache));
       
   397   }
       
   398 } // namespace boost
       
   399 
       
   400 #undef BOOST_SIGNAL_FUNCTION_N_HEADER
       
   401 #undef BOOST_SIGNALS_ARGS_STRUCT_INST
       
   402 #undef BOOST_SIGNALS_CALL_BOUND
       
   403 #undef BOOST_SIGNALS_ARGS_STRUCT
       
   404 #undef BOOST_SIGNALS_FUNCTION
       
   405 #undef BOOST_SIGNALS_SIGNAL
       
   406 #undef BOOST_SIGNALS_COMMA_IF_NONZERO_ARGS
       
   407 
       
   408 #ifdef BOOST_HAS_ABI_HEADERS
       
   409 #  include BOOST_ABI_SUFFIX
       
   410 #endif