os/ossrv/ossrv_pub/boost_apis/boost/spirit/phoenix/closures.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
/*=============================================================================
sl@0
     2
    Phoenix V1.2.1
sl@0
     3
    Copyright (c) 2001-2002 Joel de Guzman
sl@0
     4
    MT code Copyright (c) 2002-2003 Martin Wille
sl@0
     5
sl@0
     6
    Use, modification and distribution is subject to the Boost Software
sl@0
     7
    License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
sl@0
     8
    http://www.boost.org/LICENSE_1_0.txt)
sl@0
     9
==============================================================================*/
sl@0
    10
#ifndef PHOENIX_CLOSURES_HPP
sl@0
    11
#define PHOENIX_CLOSURES_HPP
sl@0
    12
sl@0
    13
///////////////////////////////////////////////////////////////////////////////
sl@0
    14
#include <boost/spirit/phoenix/actor.hpp>
sl@0
    15
#include <cassert>
sl@0
    16
sl@0
    17
#ifdef PHOENIX_THREADSAFE
sl@0
    18
#include <boost/thread/tss.hpp>
sl@0
    19
#include <boost/thread/once.hpp>
sl@0
    20
#endif
sl@0
    21
sl@0
    22
///////////////////////////////////////////////////////////////////////////////
sl@0
    23
namespace phoenix {
sl@0
    24
sl@0
    25
///////////////////////////////////////////////////////////////////////////////
sl@0
    26
//
sl@0
    27
//  Adaptable closures
sl@0
    28
//
sl@0
    29
//      The framework will not be complete without some form of closures
sl@0
    30
//      support. Closures encapsulate a stack frame where local
sl@0
    31
//      variables are created upon entering a function and destructed
sl@0
    32
//      upon exiting. Closures provide an environment for local
sl@0
    33
//      variables to reside. Closures can hold heterogeneous types.
sl@0
    34
//
sl@0
    35
//      Phoenix closures are true hardware stack based closures. At the
sl@0
    36
//      very least, closures enable true reentrancy in lambda functions.
sl@0
    37
//      A closure provides access to a function stack frame where local
sl@0
    38
//      variables reside. Modeled after Pascal nested stack frames,
sl@0
    39
//      closures can be nested just like nested functions where code in
sl@0
    40
//      inner closures may access local variables from in-scope outer
sl@0
    41
//      closures (accessing inner scopes from outer scopes is an error
sl@0
    42
//      and will cause a run-time assertion failure).
sl@0
    43
//
sl@0
    44
//      There are three (3) interacting classes:
sl@0
    45
//
sl@0
    46
//      1) closure:
sl@0
    47
//
sl@0
    48
//      At the point of declaration, a closure does not yet create a
sl@0
    49
//      stack frame nor instantiate any variables. A closure declaration
sl@0
    50
//      declares the types and names[note] of the local variables. The
sl@0
    51
//      closure class is meant to be subclassed. It is the
sl@0
    52
//      responsibility of a closure subclass to supply the names for
sl@0
    53
//      each of the local variable in the closure. Example:
sl@0
    54
//
sl@0
    55
//          struct my_closure : closure<int, string, double> {
sl@0
    56
//
sl@0
    57
//              member1 num;        // names the 1st (int) local variable
sl@0
    58
//              member2 message;    // names the 2nd (string) local variable
sl@0
    59
//              member3 real;       // names the 3rd (double) local variable
sl@0
    60
//          };
sl@0
    61
//
sl@0
    62
//          my_closure clos;
sl@0
    63
//
sl@0
    64
//      Now that we have a closure 'clos', its local variables can be
sl@0
    65
//      accessed lazily using the dot notation. Each qualified local
sl@0
    66
//      variable can be used just like any primitive actor (see
sl@0
    67
//      primitives.hpp). Examples:
sl@0
    68
//
sl@0
    69
//          clos.num = 30
sl@0
    70
//          clos.message = arg1
sl@0
    71
//          clos.real = clos.num * 1e6
sl@0
    72
//
sl@0
    73
//      The examples above are lazily evaluated. As usual, these
sl@0
    74
//      expressions return composite actors that will be evaluated
sl@0
    75
//      through a second function call invocation (see operators.hpp).
sl@0
    76
//      Each of the members (clos.xxx) is an actor. As such, applying
sl@0
    77
//      the operator() will reveal its identity:
sl@0
    78
//
sl@0
    79
//          clos.num() // will return the current value of clos.num
sl@0
    80
//
sl@0
    81
//      *** [note] Acknowledgement: Juan Carlos Arevalo-Baeza (JCAB)
sl@0
    82
//      introduced and initilally implemented the closure member names
sl@0
    83
//      that uses the dot notation.
sl@0
    84
//
sl@0
    85
//      2) closure_member
sl@0
    86
//
sl@0
    87
//      The named local variables of closure 'clos' above are actually
sl@0
    88
//      closure members. The closure_member class is an actor and
sl@0
    89
//      conforms to its conceptual interface. member1..memberN are
sl@0
    90
//      predefined typedefs that correspond to each of the listed types
sl@0
    91
//      in the closure template parameters.
sl@0
    92
//
sl@0
    93
//      3) closure_frame
sl@0
    94
//
sl@0
    95
//      When a closure member is finally evaluated, it should refer to
sl@0
    96
//      an actual instance of the variable in the hardware stack.
sl@0
    97
//      Without doing so, the process is not complete and the evaluated
sl@0
    98
//      member will result to an assertion failure. Remember that the
sl@0
    99
//      closure is just a declaration. The local variables that a
sl@0
   100
//      closure refers to must still be instantiated.
sl@0
   101
//
sl@0
   102
//      The closure_frame class does the actual instantiation of the
sl@0
   103
//      local variables and links these variables with the closure and
sl@0
   104
//      all its members. There can be multiple instances of
sl@0
   105
//      closure_frames typically situated in the stack inside a
sl@0
   106
//      function. Each closure_frame instance initiates a stack frame
sl@0
   107
//      with a new set of closure local variables. Example:
sl@0
   108
//
sl@0
   109
//          void foo()
sl@0
   110
//          {
sl@0
   111
//              closure_frame<my_closure> frame(clos);
sl@0
   112
//              /* do something */
sl@0
   113
//          }
sl@0
   114
//
sl@0
   115
//      where 'clos' is an instance of our closure 'my_closure' above.
sl@0
   116
//      Take note that the usage above precludes locally declared
sl@0
   117
//      classes. If my_closure is a locally declared type, we can still
sl@0
   118
//      use its self_type as a paramater to closure_frame:
sl@0
   119
//
sl@0
   120
//          closure_frame<my_closure::self_type> frame(clos);
sl@0
   121
//
sl@0
   122
//      Upon instantiation, the closure_frame links the local variables
sl@0
   123
//      to the closure. The previous link to another closure_frame
sl@0
   124
//      instance created before is saved. Upon destruction, the
sl@0
   125
//      closure_frame unlinks itself from the closure and relinks the
sl@0
   126
//      preceding closure_frame prior to this instance.
sl@0
   127
//
sl@0
   128
//      The local variables in the closure 'clos' above is default
sl@0
   129
//      constructed in the stack inside function 'foo'. Once 'foo' is
sl@0
   130
//      exited, all of these local variables are destructed. In some
sl@0
   131
//      cases, default construction is not desirable and we need to
sl@0
   132
//      initialize the local closure variables with some values. This
sl@0
   133
//      can be done by passing in the initializers in a compatible
sl@0
   134
//      tuple. A compatible tuple is one with the same number of
sl@0
   135
//      elements as the destination and where each element from the
sl@0
   136
//      destination can be constructed from each corresponding element
sl@0
   137
//      in the source. Example:
sl@0
   138
//
sl@0
   139
//          tuple<int, char const*, int> init(123, "Hello", 1000);
sl@0
   140
//          closure_frame<my_closure> frame(clos, init);
sl@0
   141
//
sl@0
   142
//      Here now, our closure_frame's variables are initialized with
sl@0
   143
//      int: 123, char const*: "Hello" and int: 1000.
sl@0
   144
//
sl@0
   145
///////////////////////////////////////////////////////////////////////////////
sl@0
   146
sl@0
   147
namespace impl
sl@0
   148
{
sl@0
   149
    ///////////////////////////////////////////////////////////////////////
sl@0
   150
    // closure_frame_holder is a simple class that encapsulates the
sl@0
   151
    // storage for a frame pointer. It uses thread specific data in
sl@0
   152
    // case when multithreading is enabled, an ordinary pointer otherwise
sl@0
   153
    //
sl@0
   154
    // it has get() and set() member functions. set() has to be used
sl@0
   155
    // _after_ get(). get() contains intialisation code in the multi
sl@0
   156
    // threading case
sl@0
   157
    //
sl@0
   158
    // closure_frame_holder is used by the closure<> class to store
sl@0
   159
    // the pointer to the current frame.
sl@0
   160
    //
sl@0
   161
#ifndef PHOENIX_THREADSAFE
sl@0
   162
    template <typename FrameT>
sl@0
   163
    struct closure_frame_holder
sl@0
   164
    {
sl@0
   165
        typedef FrameT frame_t;
sl@0
   166
        typedef frame_t *frame_ptr;
sl@0
   167
sl@0
   168
        closure_frame_holder() : frame(0) {}
sl@0
   169
sl@0
   170
        frame_ptr &get() { return frame; }
sl@0
   171
        void set(frame_t *f) { frame = f; }
sl@0
   172
sl@0
   173
    private:
sl@0
   174
        frame_ptr frame;
sl@0
   175
sl@0
   176
        // no copies, no assignments
sl@0
   177
        closure_frame_holder(closure_frame_holder const &);
sl@0
   178
        closure_frame_holder &operator=(closure_frame_holder const &);
sl@0
   179
    };
sl@0
   180
#else
sl@0
   181
    template <typename FrameT>
sl@0
   182
    struct closure_frame_holder
sl@0
   183
    {
sl@0
   184
        typedef FrameT   frame_t;
sl@0
   185
        typedef frame_t *frame_ptr;
sl@0
   186
sl@0
   187
        closure_frame_holder() : tsp_frame() {}
sl@0
   188
sl@0
   189
        frame_ptr &get()
sl@0
   190
        {
sl@0
   191
            if (!tsp_frame.get())
sl@0
   192
                tsp_frame.reset(new frame_ptr(0));
sl@0
   193
            return *tsp_frame;
sl@0
   194
        }
sl@0
   195
        void set(frame_ptr f)
sl@0
   196
        {
sl@0
   197
            *tsp_frame = f;
sl@0
   198
        }
sl@0
   199
sl@0
   200
    private:
sl@0
   201
        boost::thread_specific_ptr<frame_ptr> tsp_frame;
sl@0
   202
sl@0
   203
        // no copies, no assignments
sl@0
   204
        closure_frame_holder(closure_frame_holder const &);
sl@0
   205
        closure_frame_holder &operator=(closure_frame_holder const &);
sl@0
   206
    };
sl@0
   207
#endif
sl@0
   208
} // namespace phoenix::impl
sl@0
   209
sl@0
   210
///////////////////////////////////////////////////////////////////////////////
sl@0
   211
//
sl@0
   212
//  closure_frame class
sl@0
   213
//
sl@0
   214
///////////////////////////////////////////////////////////////////////////////
sl@0
   215
template <typename ClosureT>
sl@0
   216
class closure_frame : public ClosureT::tuple_t {
sl@0
   217
sl@0
   218
public:
sl@0
   219
sl@0
   220
    closure_frame(ClosureT const& clos)
sl@0
   221
    : ClosureT::tuple_t(), save(clos.frame.get()), frame(clos.frame)
sl@0
   222
    { clos.frame.set(this); }
sl@0
   223
sl@0
   224
    template <typename TupleT>
sl@0
   225
    closure_frame(ClosureT const& clos, TupleT const& init)
sl@0
   226
    : ClosureT::tuple_t(init), save(clos.frame.get()), frame(clos.frame)
sl@0
   227
    { clos.frame.set(this); }
sl@0
   228
sl@0
   229
    ~closure_frame()
sl@0
   230
    { frame.set(save); }
sl@0
   231
sl@0
   232
private:
sl@0
   233
sl@0
   234
    closure_frame(closure_frame const&);            // no copy
sl@0
   235
    closure_frame& operator=(closure_frame const&); // no assign
sl@0
   236
sl@0
   237
    closure_frame* save;
sl@0
   238
    impl::closure_frame_holder<closure_frame>& frame;
sl@0
   239
};
sl@0
   240
sl@0
   241
///////////////////////////////////////////////////////////////////////////////
sl@0
   242
//
sl@0
   243
//  closure_member class
sl@0
   244
//
sl@0
   245
///////////////////////////////////////////////////////////////////////////////
sl@0
   246
template <int N, typename ClosureT>
sl@0
   247
class closure_member {
sl@0
   248
sl@0
   249
public:
sl@0
   250
sl@0
   251
    typedef typename ClosureT::tuple_t tuple_t;
sl@0
   252
sl@0
   253
    closure_member()
sl@0
   254
    : frame(ClosureT::closure_frame_holder_ref()) {}
sl@0
   255
sl@0
   256
    template <typename TupleT>
sl@0
   257
    struct result {
sl@0
   258
sl@0
   259
        typedef typename tuple_element<
sl@0
   260
            N, typename ClosureT::tuple_t
sl@0
   261
        >::rtype type;
sl@0
   262
    };
sl@0
   263
sl@0
   264
    template <typename TupleT>
sl@0
   265
    typename tuple_element<N, typename ClosureT::tuple_t>::rtype
sl@0
   266
    eval(TupleT const& /*args*/) const
sl@0
   267
    {
sl@0
   268
        using namespace std;
sl@0
   269
        assert(frame.get() != 0);
sl@0
   270
        return (*frame.get())[tuple_index<N>()];
sl@0
   271
    }
sl@0
   272
sl@0
   273
private:
sl@0
   274
    impl::closure_frame_holder<typename ClosureT::closure_frame_t> &frame;
sl@0
   275
};
sl@0
   276
sl@0
   277
///////////////////////////////////////////////////////////////////////////////
sl@0
   278
//
sl@0
   279
//  closure class
sl@0
   280
//
sl@0
   281
///////////////////////////////////////////////////////////////////////////////
sl@0
   282
template <
sl@0
   283
        typename T0 = nil_t
sl@0
   284
    ,   typename T1 = nil_t
sl@0
   285
    ,   typename T2 = nil_t
sl@0
   286
sl@0
   287
#if PHOENIX_LIMIT > 3
sl@0
   288
    ,   typename T3 = nil_t
sl@0
   289
    ,   typename T4 = nil_t
sl@0
   290
    ,   typename T5 = nil_t
sl@0
   291
sl@0
   292
#if PHOENIX_LIMIT > 6
sl@0
   293
    ,   typename T6 = nil_t
sl@0
   294
    ,   typename T7 = nil_t
sl@0
   295
    ,   typename T8 = nil_t
sl@0
   296
sl@0
   297
#if PHOENIX_LIMIT > 9
sl@0
   298
    ,   typename T9 = nil_t
sl@0
   299
    ,   typename T10 = nil_t
sl@0
   300
    ,   typename T11 = nil_t
sl@0
   301
sl@0
   302
#if PHOENIX_LIMIT > 12
sl@0
   303
    ,   typename T12 = nil_t
sl@0
   304
    ,   typename T13 = nil_t
sl@0
   305
    ,   typename T14 = nil_t
sl@0
   306
sl@0
   307
#endif
sl@0
   308
#endif
sl@0
   309
#endif
sl@0
   310
#endif
sl@0
   311
>
sl@0
   312
class closure {
sl@0
   313
sl@0
   314
public:
sl@0
   315
sl@0
   316
    typedef tuple<
sl@0
   317
            T0, T1, T2
sl@0
   318
#if PHOENIX_LIMIT > 3
sl@0
   319
        ,   T3, T4, T5
sl@0
   320
#if PHOENIX_LIMIT > 6
sl@0
   321
        ,   T6, T7, T8
sl@0
   322
#if PHOENIX_LIMIT > 9
sl@0
   323
        ,   T9, T10, T11
sl@0
   324
#if PHOENIX_LIMIT > 12
sl@0
   325
        ,   T12, T13, T14
sl@0
   326
#endif
sl@0
   327
#endif
sl@0
   328
#endif
sl@0
   329
#endif
sl@0
   330
        > tuple_t;
sl@0
   331
sl@0
   332
    typedef closure<
sl@0
   333
            T0, T1, T2
sl@0
   334
#if PHOENIX_LIMIT > 3
sl@0
   335
        ,   T3, T4, T5
sl@0
   336
#if PHOENIX_LIMIT > 6
sl@0
   337
        ,   T6, T7, T8
sl@0
   338
#if PHOENIX_LIMIT > 9
sl@0
   339
        ,   T9, T10, T11
sl@0
   340
#if PHOENIX_LIMIT > 12
sl@0
   341
        ,   T12, T13, T14
sl@0
   342
#endif
sl@0
   343
#endif
sl@0
   344
#endif
sl@0
   345
#endif
sl@0
   346
        > self_t;
sl@0
   347
sl@0
   348
    typedef closure_frame<self_t> closure_frame_t;
sl@0
   349
sl@0
   350
                            closure()
sl@0
   351
                            : frame()       { closure_frame_holder_ref(&frame); }
sl@0
   352
    closure_frame_t&        context()       { assert(frame!=0); return frame.get(); }
sl@0
   353
    closure_frame_t const&  context() const { assert(frame!=0); return frame.get(); }
sl@0
   354
sl@0
   355
    typedef actor<closure_member<0, self_t> > member1;
sl@0
   356
    typedef actor<closure_member<1, self_t> > member2;
sl@0
   357
    typedef actor<closure_member<2, self_t> > member3;
sl@0
   358
sl@0
   359
#if PHOENIX_LIMIT > 3
sl@0
   360
    typedef actor<closure_member<3, self_t> > member4;
sl@0
   361
    typedef actor<closure_member<4, self_t> > member5;
sl@0
   362
    typedef actor<closure_member<5, self_t> > member6;
sl@0
   363
sl@0
   364
#if PHOENIX_LIMIT > 6
sl@0
   365
    typedef actor<closure_member<6, self_t> > member7;
sl@0
   366
    typedef actor<closure_member<7, self_t> > member8;
sl@0
   367
    typedef actor<closure_member<8, self_t> > member9;
sl@0
   368
sl@0
   369
#if PHOENIX_LIMIT > 9
sl@0
   370
    typedef actor<closure_member<9, self_t> > member10;
sl@0
   371
    typedef actor<closure_member<10, self_t> > member11;
sl@0
   372
    typedef actor<closure_member<11, self_t> > member12;
sl@0
   373
sl@0
   374
#if PHOENIX_LIMIT > 12
sl@0
   375
    typedef actor<closure_member<12, self_t> > member13;
sl@0
   376
    typedef actor<closure_member<13, self_t> > member14;
sl@0
   377
    typedef actor<closure_member<14, self_t> > member15;
sl@0
   378
sl@0
   379
#endif
sl@0
   380
#endif
sl@0
   381
#endif
sl@0
   382
#endif
sl@0
   383
sl@0
   384
#if !defined(__MWERKS__) || (__MWERKS__ > 0x3002)
sl@0
   385
private:
sl@0
   386
#endif
sl@0
   387
sl@0
   388
    closure(closure const&);            // no copy
sl@0
   389
    closure& operator=(closure const&); // no assign
sl@0
   390
sl@0
   391
#if !defined(__MWERKS__) || (__MWERKS__ > 0x3002)
sl@0
   392
    template <int N, typename ClosureT>
sl@0
   393
    friend class closure_member;
sl@0
   394
sl@0
   395
    template <typename ClosureT>
sl@0
   396
    friend class closure_frame;
sl@0
   397
#endif
sl@0
   398
sl@0
   399
    typedef impl::closure_frame_holder<closure_frame_t> holder_t;
sl@0
   400
sl@0
   401
#ifdef PHOENIX_THREADSAFE
sl@0
   402
    static boost::thread_specific_ptr<holder_t*> &
sl@0
   403
    tsp_frame_instance()
sl@0
   404
    {
sl@0
   405
        static boost::thread_specific_ptr<holder_t*> the_instance;
sl@0
   406
        return the_instance;
sl@0
   407
    }
sl@0
   408
sl@0
   409
    static void
sl@0
   410
    tsp_frame_instance_init()
sl@0
   411
    {
sl@0
   412
        tsp_frame_instance();
sl@0
   413
    }
sl@0
   414
#endif
sl@0
   415
sl@0
   416
    static holder_t &
sl@0
   417
    closure_frame_holder_ref(holder_t* holder_ = 0)
sl@0
   418
    {
sl@0
   419
#ifdef PHOENIX_THREADSAFE
sl@0
   420
        static boost::once_flag been_here = BOOST_ONCE_INIT;
sl@0
   421
        boost::call_once(tsp_frame_instance_init, been_here);
sl@0
   422
        boost::thread_specific_ptr<holder_t*> &tsp_frame = tsp_frame_instance();
sl@0
   423
        if (!tsp_frame.get())
sl@0
   424
            tsp_frame.reset(new holder_t *(0));
sl@0
   425
        holder_t *& holder = *tsp_frame;
sl@0
   426
#else
sl@0
   427
        static holder_t* holder = 0;
sl@0
   428
#endif
sl@0
   429
        if (holder_ != 0)
sl@0
   430
            holder = holder_;
sl@0
   431
        return *holder;
sl@0
   432
    }
sl@0
   433
sl@0
   434
    mutable holder_t frame;
sl@0
   435
};
sl@0
   436
sl@0
   437
}
sl@0
   438
   //  namespace phoenix
sl@0
   439
sl@0
   440
#endif