os/ossrv/ossrv_pub/boost_apis/boost/lambda/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.
     1 /*=============================================================================
     2     Adaptable closures
     3 
     4     Phoenix V0.9
     5     Copyright (c) 2001-2002 Joel de Guzman
     6 
     7     Distributed under the Boost Software License, Version 1.0. (See
     8     accompanying file LICENSE_1_0.txt or copy at
     9     http://www.boost.org/LICENSE_1_0.txt)
    10 
    11     URL: http://spirit.sourceforge.net/
    12 
    13 ==============================================================================*/
    14 #ifndef PHOENIX_CLOSURES_HPP
    15 #define PHOENIX_CLOSURES_HPP
    16 
    17 ///////////////////////////////////////////////////////////////////////////////
    18 #include "boost/lambda/core.hpp"
    19 ///////////////////////////////////////////////////////////////////////////////
    20 namespace boost {
    21 namespace lambda {
    22 
    23 ///////////////////////////////////////////////////////////////////////////////
    24 //
    25 //  Adaptable closures
    26 //
    27 //      The framework will not be complete without some form of closures
    28 //      support. Closures encapsulate a stack frame where local
    29 //      variables are created upon entering a function and destructed
    30 //      upon exiting. Closures provide an environment for local
    31 //      variables to reside. Closures can hold heterogeneous types.
    32 //
    33 //      Phoenix closures are true hardware stack based closures. At the
    34 //      very least, closures enable true reentrancy in lambda functions.
    35 //      A closure provides access to a function stack frame where local
    36 //      variables reside. Modeled after Pascal nested stack frames,
    37 //      closures can be nested just like nested functions where code in
    38 //      inner closures may access local variables from in-scope outer
    39 //      closures (accessing inner scopes from outer scopes is an error
    40 //      and will cause a run-time assertion failure).
    41 //
    42 //      There are three (3) interacting classes:
    43 //
    44 //      1) closure:
    45 //
    46 //      At the point of declaration, a closure does not yet create a
    47 //      stack frame nor instantiate any variables. A closure declaration
    48 //      declares the types and names[note] of the local variables. The
    49 //      closure class is meant to be subclassed. It is the
    50 //      responsibility of a closure subclass to supply the names for
    51 //      each of the local variable in the closure. Example:
    52 //
    53 //          struct my_closure : closure<int, string, double> {
    54 //
    55 //              member1 num;        // names the 1st (int) local variable
    56 //              member2 message;    // names the 2nd (string) local variable
    57 //              member3 real;       // names the 3rd (double) local variable
    58 //          };
    59 //
    60 //          my_closure clos;
    61 //
    62 //      Now that we have a closure 'clos', its local variables can be
    63 //      accessed lazily using the dot notation. Each qualified local
    64 //      variable can be used just like any primitive actor (see
    65 //      primitives.hpp). Examples:
    66 //
    67 //          clos.num = 30
    68 //          clos.message = arg1
    69 //          clos.real = clos.num * 1e6
    70 //
    71 //      The examples above are lazily evaluated. As usual, these
    72 //      expressions return composite actors that will be evaluated
    73 //      through a second function call invocation (see operators.hpp).
    74 //      Each of the members (clos.xxx) is an actor. As such, applying
    75 //      the operator() will reveal its identity:
    76 //
    77 //          clos.num() // will return the current value of clos.num
    78 //
    79 //      *** [note] Acknowledgement: Juan Carlos Arevalo-Baeza (JCAB)
    80 //      introduced and initilally implemented the closure member names
    81 //      that uses the dot notation.
    82 //
    83 //      2) closure_member
    84 //
    85 //      The named local variables of closure 'clos' above are actually
    86 //      closure members. The closure_member class is an actor and
    87 //      conforms to its conceptual interface. member1..memberN are
    88 //      predefined typedefs that correspond to each of the listed types
    89 //      in the closure template parameters.
    90 //
    91 //      3) closure_frame
    92 //
    93 //      When a closure member is finally evaluated, it should refer to
    94 //      an actual instance of the variable in the hardware stack.
    95 //      Without doing so, the process is not complete and the evaluated
    96 //      member will result to an assertion failure. Remember that the
    97 //      closure is just a declaration. The local variables that a
    98 //      closure refers to must still be instantiated.
    99 //
   100 //      The closure_frame class does the actual instantiation of the
   101 //      local variables and links these variables with the closure and
   102 //      all its members. There can be multiple instances of
   103 //      closure_frames typically situated in the stack inside a
   104 //      function. Each closure_frame instance initiates a stack frame
   105 //      with a new set of closure local variables. Example:
   106 //
   107 //          void foo()
   108 //          {
   109 //              closure_frame<my_closure> frame(clos);
   110 //              /* do something */
   111 //          }
   112 //
   113 //      where 'clos' is an instance of our closure 'my_closure' above.
   114 //      Take note that the usage above precludes locally declared
   115 //      classes. If my_closure is a locally declared type, we can still
   116 //      use its self_type as a paramater to closure_frame:
   117 //
   118 //          closure_frame<my_closure::self_type> frame(clos);
   119 //
   120 //      Upon instantiation, the closure_frame links the local variables
   121 //      to the closure. The previous link to another closure_frame
   122 //      instance created before is saved. Upon destruction, the
   123 //      closure_frame unlinks itself from the closure and relinks the
   124 //      preceding closure_frame prior to this instance.
   125 //
   126 //      The local variables in the closure 'clos' above is default
   127 //      constructed in the stack inside function 'foo'. Once 'foo' is
   128 //      exited, all of these local variables are destructed. In some
   129 //      cases, default construction is not desirable and we need to
   130 //      initialize the local closure variables with some values. This
   131 //      can be done by passing in the initializers in a compatible
   132 //      tuple. A compatible tuple is one with the same number of
   133 //      elements as the destination and where each element from the
   134 //      destination can be constructed from each corresponding element
   135 //      in the source. Example:
   136 //
   137 //          tuple<int, char const*, int> init(123, "Hello", 1000);
   138 //          closure_frame<my_closure> frame(clos, init);
   139 //
   140 //      Here now, our closure_frame's variables are initialized with
   141 //      int: 123, char const*: "Hello" and int: 1000.
   142 //
   143 ///////////////////////////////////////////////////////////////////////////////
   144 
   145 
   146 
   147 ///////////////////////////////////////////////////////////////////////////////
   148 //
   149 //  closure_frame class
   150 //
   151 ///////////////////////////////////////////////////////////////////////////////
   152 template <typename ClosureT>
   153 class closure_frame : public ClosureT::tuple_t {
   154 
   155 public:
   156 
   157     closure_frame(ClosureT& clos)
   158     : ClosureT::tuple_t(), save(clos.frame), frame(clos.frame)
   159     { clos.frame = this; }
   160 
   161     template <typename TupleT>
   162     closure_frame(ClosureT& clos, TupleT const& init)
   163     : ClosureT::tuple_t(init), save(clos.frame), frame(clos.frame)
   164     { clos.frame = this; }
   165 
   166     ~closure_frame()
   167     { frame = save; }
   168 
   169 private:
   170 
   171     closure_frame(closure_frame const&);            // no copy
   172     closure_frame& operator=(closure_frame const&); // no assign
   173 
   174     closure_frame* save;
   175     closure_frame*& frame;
   176 };
   177 
   178 ///////////////////////////////////////////////////////////////////////////////
   179 //
   180 //  closure_member class
   181 //
   182 ///////////////////////////////////////////////////////////////////////////////
   183 template <int N, typename ClosureT>
   184 class closure_member {
   185 
   186 public:
   187 
   188     typedef typename ClosureT::tuple_t tuple_t;
   189 
   190     closure_member()
   191     : frame(ClosureT::closure_frame_ref()) {}
   192 
   193     template <typename TupleT>
   194     struct sig {
   195 
   196         typedef typename detail::tuple_element_as_reference<
   197             N, typename ClosureT::tuple_t
   198         >::type type;
   199     };
   200 
   201     template <class Ret, class A, class B, class C>
   202     //    typename detail::tuple_element_as_reference
   203     //        <N, typename ClosureT::tuple_t>::type
   204     Ret
   205     call(A&, B&, C&) const
   206     {
   207         assert(frame);
   208         return boost::tuples::get<N>(*frame);
   209     }
   210 
   211 
   212 private:
   213 
   214     typename ClosureT::closure_frame_t*& frame;
   215 };
   216 
   217 ///////////////////////////////////////////////////////////////////////////////
   218 //
   219 //  closure class
   220 //
   221 ///////////////////////////////////////////////////////////////////////////////
   222 template <
   223     typename T0 = null_type,
   224     typename T1 = null_type,
   225     typename T2 = null_type,
   226     typename T3 = null_type,
   227     typename T4 = null_type
   228 >
   229 class closure {
   230 
   231 public:
   232 
   233     typedef tuple<T0, T1, T2, T3, T4> tuple_t;
   234     typedef closure<T0, T1, T2, T3, T4> self_t;
   235     typedef closure_frame<self_t> closure_frame_t;
   236 
   237                             closure()
   238                             : frame(0)      { closure_frame_ref(&frame); }
   239     closure_frame_t&        context()       { assert(frame); return frame; }
   240     closure_frame_t const&  context() const { assert(frame); return frame; }
   241 
   242     typedef lambda_functor<closure_member<0, self_t> > member1;
   243     typedef lambda_functor<closure_member<1, self_t> > member2;
   244     typedef lambda_functor<closure_member<2, self_t> > member3;
   245     typedef lambda_functor<closure_member<3, self_t> > member4;
   246     typedef lambda_functor<closure_member<4, self_t> > member5;
   247 
   248 private:
   249 
   250     closure(closure const&);            // no copy
   251     closure& operator=(closure const&); // no assign
   252 
   253     template <int N, typename ClosureT>
   254     friend struct closure_member;
   255 
   256     template <typename ClosureT>
   257     friend class closure_frame;
   258 
   259     static closure_frame_t*&
   260     closure_frame_ref(closure_frame_t** frame_ = 0)
   261     {
   262         static closure_frame_t** frame = 0;
   263         if (frame_ != 0)
   264             frame = frame_;
   265         return *frame;
   266     }
   267 
   268     closure_frame_t* frame;
   269 };
   270 
   271 }}
   272    //  namespace 
   273 
   274 #endif