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