os/ossrv/ossrv_pub/boost_apis/boost/spirit/phoenix/closures.hpp
changeset 0 bde4ae8d615e
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/os/ossrv/ossrv_pub/boost_apis/boost/spirit/phoenix/closures.hpp	Fri Jun 15 03:10:57 2012 +0200
     1.3 @@ -0,0 +1,440 @@
     1.4 +/*=============================================================================
     1.5 +    Phoenix V1.2.1
     1.6 +    Copyright (c) 2001-2002 Joel de Guzman
     1.7 +    MT code Copyright (c) 2002-2003 Martin Wille
     1.8 +
     1.9 +    Use, modification and distribution is subject to the Boost Software
    1.10 +    License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
    1.11 +    http://www.boost.org/LICENSE_1_0.txt)
    1.12 +==============================================================================*/
    1.13 +#ifndef PHOENIX_CLOSURES_HPP
    1.14 +#define PHOENIX_CLOSURES_HPP
    1.15 +
    1.16 +///////////////////////////////////////////////////////////////////////////////
    1.17 +#include <boost/spirit/phoenix/actor.hpp>
    1.18 +#include <cassert>
    1.19 +
    1.20 +#ifdef PHOENIX_THREADSAFE
    1.21 +#include <boost/thread/tss.hpp>
    1.22 +#include <boost/thread/once.hpp>
    1.23 +#endif
    1.24 +
    1.25 +///////////////////////////////////////////////////////////////////////////////
    1.26 +namespace phoenix {
    1.27 +
    1.28 +///////////////////////////////////////////////////////////////////////////////
    1.29 +//
    1.30 +//  Adaptable closures
    1.31 +//
    1.32 +//      The framework will not be complete without some form of closures
    1.33 +//      support. Closures encapsulate a stack frame where local
    1.34 +//      variables are created upon entering a function and destructed
    1.35 +//      upon exiting. Closures provide an environment for local
    1.36 +//      variables to reside. Closures can hold heterogeneous types.
    1.37 +//
    1.38 +//      Phoenix closures are true hardware stack based closures. At the
    1.39 +//      very least, closures enable true reentrancy in lambda functions.
    1.40 +//      A closure provides access to a function stack frame where local
    1.41 +//      variables reside. Modeled after Pascal nested stack frames,
    1.42 +//      closures can be nested just like nested functions where code in
    1.43 +//      inner closures may access local variables from in-scope outer
    1.44 +//      closures (accessing inner scopes from outer scopes is an error
    1.45 +//      and will cause a run-time assertion failure).
    1.46 +//
    1.47 +//      There are three (3) interacting classes:
    1.48 +//
    1.49 +//      1) closure:
    1.50 +//
    1.51 +//      At the point of declaration, a closure does not yet create a
    1.52 +//      stack frame nor instantiate any variables. A closure declaration
    1.53 +//      declares the types and names[note] of the local variables. The
    1.54 +//      closure class is meant to be subclassed. It is the
    1.55 +//      responsibility of a closure subclass to supply the names for
    1.56 +//      each of the local variable in the closure. Example:
    1.57 +//
    1.58 +//          struct my_closure : closure<int, string, double> {
    1.59 +//
    1.60 +//              member1 num;        // names the 1st (int) local variable
    1.61 +//              member2 message;    // names the 2nd (string) local variable
    1.62 +//              member3 real;       // names the 3rd (double) local variable
    1.63 +//          };
    1.64 +//
    1.65 +//          my_closure clos;
    1.66 +//
    1.67 +//      Now that we have a closure 'clos', its local variables can be
    1.68 +//      accessed lazily using the dot notation. Each qualified local
    1.69 +//      variable can be used just like any primitive actor (see
    1.70 +//      primitives.hpp). Examples:
    1.71 +//
    1.72 +//          clos.num = 30
    1.73 +//          clos.message = arg1
    1.74 +//          clos.real = clos.num * 1e6
    1.75 +//
    1.76 +//      The examples above are lazily evaluated. As usual, these
    1.77 +//      expressions return composite actors that will be evaluated
    1.78 +//      through a second function call invocation (see operators.hpp).
    1.79 +//      Each of the members (clos.xxx) is an actor. As such, applying
    1.80 +//      the operator() will reveal its identity:
    1.81 +//
    1.82 +//          clos.num() // will return the current value of clos.num
    1.83 +//
    1.84 +//      *** [note] Acknowledgement: Juan Carlos Arevalo-Baeza (JCAB)
    1.85 +//      introduced and initilally implemented the closure member names
    1.86 +//      that uses the dot notation.
    1.87 +//
    1.88 +//      2) closure_member
    1.89 +//
    1.90 +//      The named local variables of closure 'clos' above are actually
    1.91 +//      closure members. The closure_member class is an actor and
    1.92 +//      conforms to its conceptual interface. member1..memberN are
    1.93 +//      predefined typedefs that correspond to each of the listed types
    1.94 +//      in the closure template parameters.
    1.95 +//
    1.96 +//      3) closure_frame
    1.97 +//
    1.98 +//      When a closure member is finally evaluated, it should refer to
    1.99 +//      an actual instance of the variable in the hardware stack.
   1.100 +//      Without doing so, the process is not complete and the evaluated
   1.101 +//      member will result to an assertion failure. Remember that the
   1.102 +//      closure is just a declaration. The local variables that a
   1.103 +//      closure refers to must still be instantiated.
   1.104 +//
   1.105 +//      The closure_frame class does the actual instantiation of the
   1.106 +//      local variables and links these variables with the closure and
   1.107 +//      all its members. There can be multiple instances of
   1.108 +//      closure_frames typically situated in the stack inside a
   1.109 +//      function. Each closure_frame instance initiates a stack frame
   1.110 +//      with a new set of closure local variables. Example:
   1.111 +//
   1.112 +//          void foo()
   1.113 +//          {
   1.114 +//              closure_frame<my_closure> frame(clos);
   1.115 +//              /* do something */
   1.116 +//          }
   1.117 +//
   1.118 +//      where 'clos' is an instance of our closure 'my_closure' above.
   1.119 +//      Take note that the usage above precludes locally declared
   1.120 +//      classes. If my_closure is a locally declared type, we can still
   1.121 +//      use its self_type as a paramater to closure_frame:
   1.122 +//
   1.123 +//          closure_frame<my_closure::self_type> frame(clos);
   1.124 +//
   1.125 +//      Upon instantiation, the closure_frame links the local variables
   1.126 +//      to the closure. The previous link to another closure_frame
   1.127 +//      instance created before is saved. Upon destruction, the
   1.128 +//      closure_frame unlinks itself from the closure and relinks the
   1.129 +//      preceding closure_frame prior to this instance.
   1.130 +//
   1.131 +//      The local variables in the closure 'clos' above is default
   1.132 +//      constructed in the stack inside function 'foo'. Once 'foo' is
   1.133 +//      exited, all of these local variables are destructed. In some
   1.134 +//      cases, default construction is not desirable and we need to
   1.135 +//      initialize the local closure variables with some values. This
   1.136 +//      can be done by passing in the initializers in a compatible
   1.137 +//      tuple. A compatible tuple is one with the same number of
   1.138 +//      elements as the destination and where each element from the
   1.139 +//      destination can be constructed from each corresponding element
   1.140 +//      in the source. Example:
   1.141 +//
   1.142 +//          tuple<int, char const*, int> init(123, "Hello", 1000);
   1.143 +//          closure_frame<my_closure> frame(clos, init);
   1.144 +//
   1.145 +//      Here now, our closure_frame's variables are initialized with
   1.146 +//      int: 123, char const*: "Hello" and int: 1000.
   1.147 +//
   1.148 +///////////////////////////////////////////////////////////////////////////////
   1.149 +
   1.150 +namespace impl
   1.151 +{
   1.152 +    ///////////////////////////////////////////////////////////////////////
   1.153 +    // closure_frame_holder is a simple class that encapsulates the
   1.154 +    // storage for a frame pointer. It uses thread specific data in
   1.155 +    // case when multithreading is enabled, an ordinary pointer otherwise
   1.156 +    //
   1.157 +    // it has get() and set() member functions. set() has to be used
   1.158 +    // _after_ get(). get() contains intialisation code in the multi
   1.159 +    // threading case
   1.160 +    //
   1.161 +    // closure_frame_holder is used by the closure<> class to store
   1.162 +    // the pointer to the current frame.
   1.163 +    //
   1.164 +#ifndef PHOENIX_THREADSAFE
   1.165 +    template <typename FrameT>
   1.166 +    struct closure_frame_holder
   1.167 +    {
   1.168 +        typedef FrameT frame_t;
   1.169 +        typedef frame_t *frame_ptr;
   1.170 +
   1.171 +        closure_frame_holder() : frame(0) {}
   1.172 +
   1.173 +        frame_ptr &get() { return frame; }
   1.174 +        void set(frame_t *f) { frame = f; }
   1.175 +
   1.176 +    private:
   1.177 +        frame_ptr frame;
   1.178 +
   1.179 +        // no copies, no assignments
   1.180 +        closure_frame_holder(closure_frame_holder const &);
   1.181 +        closure_frame_holder &operator=(closure_frame_holder const &);
   1.182 +    };
   1.183 +#else
   1.184 +    template <typename FrameT>
   1.185 +    struct closure_frame_holder
   1.186 +    {
   1.187 +        typedef FrameT   frame_t;
   1.188 +        typedef frame_t *frame_ptr;
   1.189 +
   1.190 +        closure_frame_holder() : tsp_frame() {}
   1.191 +
   1.192 +        frame_ptr &get()
   1.193 +        {
   1.194 +            if (!tsp_frame.get())
   1.195 +                tsp_frame.reset(new frame_ptr(0));
   1.196 +            return *tsp_frame;
   1.197 +        }
   1.198 +        void set(frame_ptr f)
   1.199 +        {
   1.200 +            *tsp_frame = f;
   1.201 +        }
   1.202 +
   1.203 +    private:
   1.204 +        boost::thread_specific_ptr<frame_ptr> tsp_frame;
   1.205 +
   1.206 +        // no copies, no assignments
   1.207 +        closure_frame_holder(closure_frame_holder const &);
   1.208 +        closure_frame_holder &operator=(closure_frame_holder const &);
   1.209 +    };
   1.210 +#endif
   1.211 +} // namespace phoenix::impl
   1.212 +
   1.213 +///////////////////////////////////////////////////////////////////////////////
   1.214 +//
   1.215 +//  closure_frame class
   1.216 +//
   1.217 +///////////////////////////////////////////////////////////////////////////////
   1.218 +template <typename ClosureT>
   1.219 +class closure_frame : public ClosureT::tuple_t {
   1.220 +
   1.221 +public:
   1.222 +
   1.223 +    closure_frame(ClosureT const& clos)
   1.224 +    : ClosureT::tuple_t(), save(clos.frame.get()), frame(clos.frame)
   1.225 +    { clos.frame.set(this); }
   1.226 +
   1.227 +    template <typename TupleT>
   1.228 +    closure_frame(ClosureT const& clos, TupleT const& init)
   1.229 +    : ClosureT::tuple_t(init), save(clos.frame.get()), frame(clos.frame)
   1.230 +    { clos.frame.set(this); }
   1.231 +
   1.232 +    ~closure_frame()
   1.233 +    { frame.set(save); }
   1.234 +
   1.235 +private:
   1.236 +
   1.237 +    closure_frame(closure_frame const&);            // no copy
   1.238 +    closure_frame& operator=(closure_frame const&); // no assign
   1.239 +
   1.240 +    closure_frame* save;
   1.241 +    impl::closure_frame_holder<closure_frame>& frame;
   1.242 +};
   1.243 +
   1.244 +///////////////////////////////////////////////////////////////////////////////
   1.245 +//
   1.246 +//  closure_member class
   1.247 +//
   1.248 +///////////////////////////////////////////////////////////////////////////////
   1.249 +template <int N, typename ClosureT>
   1.250 +class closure_member {
   1.251 +
   1.252 +public:
   1.253 +
   1.254 +    typedef typename ClosureT::tuple_t tuple_t;
   1.255 +
   1.256 +    closure_member()
   1.257 +    : frame(ClosureT::closure_frame_holder_ref()) {}
   1.258 +
   1.259 +    template <typename TupleT>
   1.260 +    struct result {
   1.261 +
   1.262 +        typedef typename tuple_element<
   1.263 +            N, typename ClosureT::tuple_t
   1.264 +        >::rtype type;
   1.265 +    };
   1.266 +
   1.267 +    template <typename TupleT>
   1.268 +    typename tuple_element<N, typename ClosureT::tuple_t>::rtype
   1.269 +    eval(TupleT const& /*args*/) const
   1.270 +    {
   1.271 +        using namespace std;
   1.272 +        assert(frame.get() != 0);
   1.273 +        return (*frame.get())[tuple_index<N>()];
   1.274 +    }
   1.275 +
   1.276 +private:
   1.277 +    impl::closure_frame_holder<typename ClosureT::closure_frame_t> &frame;
   1.278 +};
   1.279 +
   1.280 +///////////////////////////////////////////////////////////////////////////////
   1.281 +//
   1.282 +//  closure class
   1.283 +//
   1.284 +///////////////////////////////////////////////////////////////////////////////
   1.285 +template <
   1.286 +        typename T0 = nil_t
   1.287 +    ,   typename T1 = nil_t
   1.288 +    ,   typename T2 = nil_t
   1.289 +
   1.290 +#if PHOENIX_LIMIT > 3
   1.291 +    ,   typename T3 = nil_t
   1.292 +    ,   typename T4 = nil_t
   1.293 +    ,   typename T5 = nil_t
   1.294 +
   1.295 +#if PHOENIX_LIMIT > 6
   1.296 +    ,   typename T6 = nil_t
   1.297 +    ,   typename T7 = nil_t
   1.298 +    ,   typename T8 = nil_t
   1.299 +
   1.300 +#if PHOENIX_LIMIT > 9
   1.301 +    ,   typename T9 = nil_t
   1.302 +    ,   typename T10 = nil_t
   1.303 +    ,   typename T11 = nil_t
   1.304 +
   1.305 +#if PHOENIX_LIMIT > 12
   1.306 +    ,   typename T12 = nil_t
   1.307 +    ,   typename T13 = nil_t
   1.308 +    ,   typename T14 = nil_t
   1.309 +
   1.310 +#endif
   1.311 +#endif
   1.312 +#endif
   1.313 +#endif
   1.314 +>
   1.315 +class closure {
   1.316 +
   1.317 +public:
   1.318 +
   1.319 +    typedef tuple<
   1.320 +            T0, T1, T2
   1.321 +#if PHOENIX_LIMIT > 3
   1.322 +        ,   T3, T4, T5
   1.323 +#if PHOENIX_LIMIT > 6
   1.324 +        ,   T6, T7, T8
   1.325 +#if PHOENIX_LIMIT > 9
   1.326 +        ,   T9, T10, T11
   1.327 +#if PHOENIX_LIMIT > 12
   1.328 +        ,   T12, T13, T14
   1.329 +#endif
   1.330 +#endif
   1.331 +#endif
   1.332 +#endif
   1.333 +        > tuple_t;
   1.334 +
   1.335 +    typedef closure<
   1.336 +            T0, T1, T2
   1.337 +#if PHOENIX_LIMIT > 3
   1.338 +        ,   T3, T4, T5
   1.339 +#if PHOENIX_LIMIT > 6
   1.340 +        ,   T6, T7, T8
   1.341 +#if PHOENIX_LIMIT > 9
   1.342 +        ,   T9, T10, T11
   1.343 +#if PHOENIX_LIMIT > 12
   1.344 +        ,   T12, T13, T14
   1.345 +#endif
   1.346 +#endif
   1.347 +#endif
   1.348 +#endif
   1.349 +        > self_t;
   1.350 +
   1.351 +    typedef closure_frame<self_t> closure_frame_t;
   1.352 +
   1.353 +                            closure()
   1.354 +                            : frame()       { closure_frame_holder_ref(&frame); }
   1.355 +    closure_frame_t&        context()       { assert(frame!=0); return frame.get(); }
   1.356 +    closure_frame_t const&  context() const { assert(frame!=0); return frame.get(); }
   1.357 +
   1.358 +    typedef actor<closure_member<0, self_t> > member1;
   1.359 +    typedef actor<closure_member<1, self_t> > member2;
   1.360 +    typedef actor<closure_member<2, self_t> > member3;
   1.361 +
   1.362 +#if PHOENIX_LIMIT > 3
   1.363 +    typedef actor<closure_member<3, self_t> > member4;
   1.364 +    typedef actor<closure_member<4, self_t> > member5;
   1.365 +    typedef actor<closure_member<5, self_t> > member6;
   1.366 +
   1.367 +#if PHOENIX_LIMIT > 6
   1.368 +    typedef actor<closure_member<6, self_t> > member7;
   1.369 +    typedef actor<closure_member<7, self_t> > member8;
   1.370 +    typedef actor<closure_member<8, self_t> > member9;
   1.371 +
   1.372 +#if PHOENIX_LIMIT > 9
   1.373 +    typedef actor<closure_member<9, self_t> > member10;
   1.374 +    typedef actor<closure_member<10, self_t> > member11;
   1.375 +    typedef actor<closure_member<11, self_t> > member12;
   1.376 +
   1.377 +#if PHOENIX_LIMIT > 12
   1.378 +    typedef actor<closure_member<12, self_t> > member13;
   1.379 +    typedef actor<closure_member<13, self_t> > member14;
   1.380 +    typedef actor<closure_member<14, self_t> > member15;
   1.381 +
   1.382 +#endif
   1.383 +#endif
   1.384 +#endif
   1.385 +#endif
   1.386 +
   1.387 +#if !defined(__MWERKS__) || (__MWERKS__ > 0x3002)
   1.388 +private:
   1.389 +#endif
   1.390 +
   1.391 +    closure(closure const&);            // no copy
   1.392 +    closure& operator=(closure const&); // no assign
   1.393 +
   1.394 +#if !defined(__MWERKS__) || (__MWERKS__ > 0x3002)
   1.395 +    template <int N, typename ClosureT>
   1.396 +    friend class closure_member;
   1.397 +
   1.398 +    template <typename ClosureT>
   1.399 +    friend class closure_frame;
   1.400 +#endif
   1.401 +
   1.402 +    typedef impl::closure_frame_holder<closure_frame_t> holder_t;
   1.403 +
   1.404 +#ifdef PHOENIX_THREADSAFE
   1.405 +    static boost::thread_specific_ptr<holder_t*> &
   1.406 +    tsp_frame_instance()
   1.407 +    {
   1.408 +        static boost::thread_specific_ptr<holder_t*> the_instance;
   1.409 +        return the_instance;
   1.410 +    }
   1.411 +
   1.412 +    static void
   1.413 +    tsp_frame_instance_init()
   1.414 +    {
   1.415 +        tsp_frame_instance();
   1.416 +    }
   1.417 +#endif
   1.418 +
   1.419 +    static holder_t &
   1.420 +    closure_frame_holder_ref(holder_t* holder_ = 0)
   1.421 +    {
   1.422 +#ifdef PHOENIX_THREADSAFE
   1.423 +        static boost::once_flag been_here = BOOST_ONCE_INIT;
   1.424 +        boost::call_once(tsp_frame_instance_init, been_here);
   1.425 +        boost::thread_specific_ptr<holder_t*> &tsp_frame = tsp_frame_instance();
   1.426 +        if (!tsp_frame.get())
   1.427 +            tsp_frame.reset(new holder_t *(0));
   1.428 +        holder_t *& holder = *tsp_frame;
   1.429 +#else
   1.430 +        static holder_t* holder = 0;
   1.431 +#endif
   1.432 +        if (holder_ != 0)
   1.433 +            holder = holder_;
   1.434 +        return *holder;
   1.435 +    }
   1.436 +
   1.437 +    mutable holder_t frame;
   1.438 +};
   1.439 +
   1.440 +}
   1.441 +   //  namespace phoenix
   1.442 +
   1.443 +#endif