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