Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2024-11-15 09:31:26

0001 /*=============================================================================
0002     Phoenix V1.2.1
0003     Copyright (c) 2001-2002 Joel de Guzman
0004     MT code Copyright (c) 2002-2003 Martin Wille
0005 
0006   Distributed under the Boost Software License, Version 1.0. (See accompanying
0007   file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0008 ==============================================================================*/
0009 #ifndef BOOST_SPIRIT_CLASSIC_PHOENIX_CLOSURES_HPP
0010 #define BOOST_SPIRIT_CLASSIC_PHOENIX_CLOSURES_HPP
0011 
0012 ///////////////////////////////////////////////////////////////////////////////
0013 #include <boost/spirit/home/classic/phoenix/actor.hpp>
0014 #include <boost/assert.hpp>
0015 
0016 #ifdef PHOENIX_THREADSAFE
0017 #include <boost/thread/tss.hpp>
0018 #include <boost/thread/once.hpp>
0019 #endif
0020 
0021 ///////////////////////////////////////////////////////////////////////////////
0022 namespace phoenix {
0023 
0024 #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
0025 #pragma warning(push)
0026 #pragma warning(disable:4512) //assignment operator could not be generated
0027 #endif
0028 
0029 ///////////////////////////////////////////////////////////////////////////////
0030 //
0031 //  Adaptable closures
0032 //
0033 //      The framework will not be complete without some form of closures
0034 //      support. Closures encapsulate a stack frame where local
0035 //      variables are created upon entering a function and destructed
0036 //      upon exiting. Closures provide an environment for local
0037 //      variables to reside. Closures can hold heterogeneous types.
0038 //
0039 //      Phoenix closures are true hardware stack based closures. At the
0040 //      very least, closures enable true reentrancy in lambda functions.
0041 //      A closure provides access to a function stack frame where local
0042 //      variables reside. Modeled after Pascal nested stack frames,
0043 //      closures can be nested just like nested functions where code in
0044 //      inner closures may access local variables from in-scope outer
0045 //      closures (accessing inner scopes from outer scopes is an error
0046 //      and will cause a run-time assertion failure).
0047 //
0048 //      There are three (3) interacting classes:
0049 //
0050 //      1) closure:
0051 //
0052 //      At the point of declaration, a closure does not yet create a
0053 //      stack frame nor instantiate any variables. A closure declaration
0054 //      declares the types and names[note] of the local variables. The
0055 //      closure class is meant to be subclassed. It is the
0056 //      responsibility of a closure subclass to supply the names for
0057 //      each of the local variable in the closure. Example:
0058 //
0059 //          struct my_closure : closure<int, string, double> {
0060 //
0061 //              member1 num;        // names the 1st (int) local variable
0062 //              member2 message;    // names the 2nd (string) local variable
0063 //              member3 real;       // names the 3rd (double) local variable
0064 //          };
0065 //
0066 //          my_closure clos;
0067 //
0068 //      Now that we have a closure 'clos', its local variables can be
0069 //      accessed lazily using the dot notation. Each qualified local
0070 //      variable can be used just like any primitive actor (see
0071 //      primitives.hpp). Examples:
0072 //
0073 //          clos.num = 30
0074 //          clos.message = arg1
0075 //          clos.real = clos.num * 1e6
0076 //
0077 //      The examples above are lazily evaluated. As usual, these
0078 //      expressions return composite actors that will be evaluated
0079 //      through a second function call invocation (see operators.hpp).
0080 //      Each of the members (clos.xxx) is an actor. As such, applying
0081 //      the operator() will reveal its identity:
0082 //
0083 //          clos.num() // will return the current value of clos.num
0084 //
0085 //      *** [note] Acknowledgement: Juan Carlos Arevalo-Baeza (JCAB)
0086 //      introduced and initilally implemented the closure member names
0087 //      that uses the dot notation.
0088 //
0089 //      2) closure_member
0090 //
0091 //      The named local variables of closure 'clos' above are actually
0092 //      closure members. The closure_member class is an actor and
0093 //      conforms to its conceptual interface. member1..memberN are
0094 //      predefined typedefs that correspond to each of the listed types
0095 //      in the closure template parameters.
0096 //
0097 //      3) closure_frame
0098 //
0099 //      When a closure member is finally evaluated, it should refer to
0100 //      an actual instance of the variable in the hardware stack.
0101 //      Without doing so, the process is not complete and the evaluated
0102 //      member will result to an assertion failure. Remember that the
0103 //      closure is just a declaration. The local variables that a
0104 //      closure refers to must still be instantiated.
0105 //
0106 //      The closure_frame class does the actual instantiation of the
0107 //      local variables and links these variables with the closure and
0108 //      all its members. There can be multiple instances of
0109 //      closure_frames typically situated in the stack inside a
0110 //      function. Each closure_frame instance initiates a stack frame
0111 //      with a new set of closure local variables. Example:
0112 //
0113 //          void foo()
0114 //          {
0115 //              closure_frame<my_closure> frame(clos);
0116 //              /* do something */
0117 //          }
0118 //
0119 //      where 'clos' is an instance of our closure 'my_closure' above.
0120 //      Take note that the usage above precludes locally declared
0121 //      classes. If my_closure is a locally declared type, we can still
0122 //      use its self_type as a parameter to closure_frame:
0123 //
0124 //          closure_frame<my_closure::self_type> frame(clos);
0125 //
0126 //      Upon instantiation, the closure_frame links the local variables
0127 //      to the closure. The previous link to another closure_frame
0128 //      instance created before is saved. Upon destruction, the
0129 //      closure_frame unlinks itself from the closure and relinks the
0130 //      preceding closure_frame prior to this instance.
0131 //
0132 //      The local variables in the closure 'clos' above is default
0133 //      constructed in the stack inside function 'foo'. Once 'foo' is
0134 //      exited, all of these local variables are destructed. In some
0135 //      cases, default construction is not desirable and we need to
0136 //      initialize the local closure variables with some values. This
0137 //      can be done by passing in the initializers in a compatible
0138 //      tuple. A compatible tuple is one with the same number of
0139 //      elements as the destination and where each element from the
0140 //      destination can be constructed from each corresponding element
0141 //      in the source. Example:
0142 //
0143 //          tuple<int, char const*, int> init(123, "Hello", 1000);
0144 //          closure_frame<my_closure> frame(clos, init);
0145 //
0146 //      Here now, our closure_frame's variables are initialized with
0147 //      int: 123, char const*: "Hello" and int: 1000.
0148 //
0149 ///////////////////////////////////////////////////////////////////////////////
0150 
0151 namespace impl
0152 {
0153     ///////////////////////////////////////////////////////////////////////
0154     // closure_frame_holder is a simple class that encapsulates the
0155     // storage for a frame pointer. It uses thread specific data in
0156     // case when multithreading is enabled, an ordinary pointer otherwise
0157     //
0158     // it has get() and set() member functions. set() has to be used
0159     // _after_ get(). get() contains intialisation code in the multi
0160     // threading case
0161     //
0162     // closure_frame_holder is used by the closure<> class to store
0163     // the pointer to the current frame.
0164     //
0165 #ifndef PHOENIX_THREADSAFE
0166     template <typename FrameT>
0167     struct closure_frame_holder
0168     {
0169         typedef FrameT frame_t;
0170         typedef frame_t *frame_ptr;
0171 
0172         closure_frame_holder() : frame(0) {}
0173 
0174         frame_ptr &get() { return frame; }
0175         void set(frame_t *f) { frame = f; }
0176 
0177     private:
0178         frame_ptr frame;
0179 
0180         // no copies, no assignments
0181         closure_frame_holder(closure_frame_holder const &);
0182         closure_frame_holder &operator=(closure_frame_holder const &);
0183     };
0184 #else
0185     template <typename FrameT>
0186     struct closure_frame_holder
0187     {
0188         typedef FrameT   frame_t;
0189         typedef frame_t *frame_ptr;
0190 
0191         closure_frame_holder() : tsp_frame() {}
0192 
0193         frame_ptr &get()
0194         {
0195             if (!tsp_frame.get())
0196                 tsp_frame.reset(new frame_ptr(0));
0197             return *tsp_frame;
0198         }
0199         void set(frame_ptr f)
0200         {
0201             *tsp_frame = f;
0202         }
0203 
0204     private:
0205         boost::thread_specific_ptr<frame_ptr> tsp_frame;
0206 
0207         // no copies, no assignments
0208         closure_frame_holder(closure_frame_holder const &);
0209         closure_frame_holder &operator=(closure_frame_holder const &);
0210     };
0211 #endif
0212 } // namespace phoenix::impl
0213 
0214 ///////////////////////////////////////////////////////////////////////////////
0215 //
0216 //  closure_frame class
0217 //
0218 ///////////////////////////////////////////////////////////////////////////////
0219 template <typename ClosureT>
0220 class closure_frame : public ClosureT::tuple_t {
0221 
0222 public:
0223 
0224     closure_frame(ClosureT const& clos)
0225     : ClosureT::tuple_t(), save(clos.frame.get()), frame(clos.frame)
0226     { clos.frame.set(this); }
0227 
0228     template <typename TupleT>
0229     closure_frame(ClosureT const& clos, TupleT const& init)
0230     : ClosureT::tuple_t(init), save(clos.frame.get()), frame(clos.frame)
0231     { clos.frame.set(this); }
0232 
0233     ~closure_frame()
0234     { frame.set(save); }
0235 
0236 private:
0237 
0238     closure_frame(closure_frame const&);            // no copy
0239     closure_frame& operator=(closure_frame const&); // no assign
0240 
0241     closure_frame* save;
0242     impl::closure_frame_holder<closure_frame>& frame;
0243 };
0244 
0245 ///////////////////////////////////////////////////////////////////////////////
0246 //
0247 //  closure_member class
0248 //
0249 ///////////////////////////////////////////////////////////////////////////////
0250 template <int N, typename ClosureT>
0251 class closure_member {
0252 
0253 public:
0254 
0255     typedef typename ClosureT::tuple_t tuple_t;
0256 
0257     closure_member()
0258     : frame(ClosureT::closure_frame_holder_ref()) {}
0259 
0260     template <typename TupleT>
0261     struct result {
0262 
0263         typedef typename tuple_element<
0264             N, typename ClosureT::tuple_t
0265         >::rtype type;
0266     };
0267 
0268     template <typename TupleT>
0269     typename tuple_element<N, typename ClosureT::tuple_t>::rtype
0270     eval(TupleT const& /*args*/) const
0271     {
0272         using namespace std;
0273         BOOST_ASSERT(frame.get() != 0);
0274         tuple_index<N> const idx;
0275         return (*frame.get())[idx];
0276     }
0277 
0278 private:
0279     impl::closure_frame_holder<typename ClosureT::closure_frame_t> &frame;
0280 };
0281 
0282 ///////////////////////////////////////////////////////////////////////////////
0283 //
0284 //  closure class
0285 //
0286 ///////////////////////////////////////////////////////////////////////////////
0287 template <
0288         typename T0 = nil_t
0289     ,   typename T1 = nil_t
0290     ,   typename T2 = nil_t
0291 
0292 #if PHOENIX_LIMIT > 3
0293     ,   typename T3 = nil_t
0294     ,   typename T4 = nil_t
0295     ,   typename T5 = nil_t
0296 
0297 #if PHOENIX_LIMIT > 6
0298     ,   typename T6 = nil_t
0299     ,   typename T7 = nil_t
0300     ,   typename T8 = nil_t
0301 
0302 #if PHOENIX_LIMIT > 9
0303     ,   typename T9 = nil_t
0304     ,   typename T10 = nil_t
0305     ,   typename T11 = nil_t
0306 
0307 #if PHOENIX_LIMIT > 12
0308     ,   typename T12 = nil_t
0309     ,   typename T13 = nil_t
0310     ,   typename T14 = nil_t
0311 
0312 #endif
0313 #endif
0314 #endif
0315 #endif
0316 >
0317 class closure {
0318 
0319 public:
0320 
0321     typedef tuple<
0322             T0, T1, T2
0323 #if PHOENIX_LIMIT > 3
0324         ,   T3, T4, T5
0325 #if PHOENIX_LIMIT > 6
0326         ,   T6, T7, T8
0327 #if PHOENIX_LIMIT > 9
0328         ,   T9, T10, T11
0329 #if PHOENIX_LIMIT > 12
0330         ,   T12, T13, T14
0331 #endif
0332 #endif
0333 #endif
0334 #endif
0335         > tuple_t;
0336 
0337     typedef closure<
0338             T0, T1, T2
0339 #if PHOENIX_LIMIT > 3
0340         ,   T3, T4, T5
0341 #if PHOENIX_LIMIT > 6
0342         ,   T6, T7, T8
0343 #if PHOENIX_LIMIT > 9
0344         ,   T9, T10, T11
0345 #if PHOENIX_LIMIT > 12
0346         ,   T12, T13, T14
0347 #endif
0348 #endif
0349 #endif
0350 #endif
0351         > self_t;
0352 
0353     typedef closure_frame<self_t> closure_frame_t;
0354 
0355                             closure()
0356                             : frame()       { closure_frame_holder_ref(&frame); }
0357 
0358     typedef actor<closure_member<0, self_t> > member1;
0359     typedef actor<closure_member<1, self_t> > member2;
0360     typedef actor<closure_member<2, self_t> > member3;
0361 
0362 #if PHOENIX_LIMIT > 3
0363     typedef actor<closure_member<3, self_t> > member4;
0364     typedef actor<closure_member<4, self_t> > member5;
0365     typedef actor<closure_member<5, self_t> > member6;
0366 
0367 #if PHOENIX_LIMIT > 6
0368     typedef actor<closure_member<6, self_t> > member7;
0369     typedef actor<closure_member<7, self_t> > member8;
0370     typedef actor<closure_member<8, self_t> > member9;
0371 
0372 #if PHOENIX_LIMIT > 9
0373     typedef actor<closure_member<9, self_t> > member10;
0374     typedef actor<closure_member<10, self_t> > member11;
0375     typedef actor<closure_member<11, self_t> > member12;
0376 
0377 #if PHOENIX_LIMIT > 12
0378     typedef actor<closure_member<12, self_t> > member13;
0379     typedef actor<closure_member<13, self_t> > member14;
0380     typedef actor<closure_member<14, self_t> > member15;
0381 
0382 #endif
0383 #endif
0384 #endif
0385 #endif
0386 
0387 #if !defined(__MWERKS__) || (__MWERKS__ > 0x3002)
0388 private:
0389 #endif
0390 
0391     closure(closure const&);            // no copy
0392     closure& operator=(closure const&); // no assign
0393 
0394 #if !defined(__MWERKS__) || (__MWERKS__ > 0x3002)
0395     template <int N, typename ClosureT>
0396     friend class closure_member;
0397 
0398     template <typename ClosureT>
0399     friend class closure_frame;
0400 #endif
0401 
0402     typedef impl::closure_frame_holder<closure_frame_t> holder_t;
0403 
0404 #ifdef PHOENIX_THREADSAFE
0405     static boost::thread_specific_ptr<holder_t*> &
0406     tsp_frame_instance()
0407     {
0408         static boost::thread_specific_ptr<holder_t*> the_instance;
0409         return the_instance;
0410     }
0411 
0412     static void
0413     tsp_frame_instance_init()
0414     {
0415         tsp_frame_instance();
0416     }
0417 #endif
0418 
0419     static holder_t &
0420     closure_frame_holder_ref(holder_t* holder_ = 0)
0421     {
0422 #ifdef PHOENIX_THREADSAFE
0423 #ifndef BOOST_THREAD_PROVIDES_ONCE_CXX11
0424         static boost::once_flag been_here = BOOST_ONCE_INIT;
0425 #else
0426         static boost::once_flag been_here;
0427 #endif
0428         boost::call_once(been_here, tsp_frame_instance_init);
0429         boost::thread_specific_ptr<holder_t*> &tsp_frame = tsp_frame_instance();
0430         if (!tsp_frame.get())
0431             tsp_frame.reset(new holder_t *(0));
0432         holder_t *& holder = *tsp_frame;
0433 #else
0434         static holder_t* holder = 0;
0435 #endif
0436         if (holder_ != 0)
0437             holder = holder_;
0438         return *holder;
0439     }
0440 
0441     mutable holder_t frame;
0442 };
0443 
0444 #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
0445 #pragma warning(pop)
0446 #endif
0447 
0448 }
0449    //  namespace phoenix
0450 
0451 #endif