Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-12-16 09:45:10

0001 
0002 //          Copyright Oliver Kowalke 2009.
0003 // Distributed under the Boost Software License, Version 1.0.
0004 //    (See accompanying file LICENSE_1_0.txt or copy at
0005 //          http://www.boost.org/LICENSE_1_0.txt)
0006 
0007 #ifndef BOOST_COROUTINES_ASYMMETRIC_COROUTINE_H
0008 #define BOOST_COROUTINES_ASYMMETRIC_COROUTINE_H
0009 
0010 #include <cstddef>
0011 #include <iterator>
0012 #include <memory>
0013 
0014 #include <boost/assert.hpp>
0015 #include <boost/config.hpp>
0016 #include <boost/move/move.hpp>
0017 #include <boost/throw_exception.hpp>
0018 #include <boost/utility/explicit_operator_bool.hpp>
0019 
0020 #include <boost/coroutine/attributes.hpp>
0021 #include <boost/coroutine/detail/config.hpp>
0022 #include <boost/coroutine/detail/coroutine_context.hpp>
0023 #include <boost/coroutine/detail/parameters.hpp>
0024 #include <boost/coroutine/exceptions.hpp>
0025 #include <boost/coroutine/stack_allocator.hpp>
0026 #include <boost/coroutine/detail/pull_coroutine_impl.hpp>
0027 #include <boost/coroutine/detail/pull_coroutine_object.hpp>
0028 #include <boost/coroutine/detail/pull_coroutine_synthesized.hpp>
0029 #include <boost/coroutine/detail/push_coroutine_impl.hpp>
0030 #include <boost/coroutine/detail/push_coroutine_object.hpp>
0031 #include <boost/coroutine/detail/push_coroutine_synthesized.hpp>
0032 #include <boost/coroutine/stack_context.hpp>
0033 
0034 #ifdef BOOST_HAS_ABI_HEADERS
0035 #  include BOOST_ABI_PREFIX
0036 #endif
0037 
0038 namespace boost {
0039 namespace coroutines {
0040 
0041 template< typename R >
0042 class pull_coroutine;
0043 
0044 template< typename Arg >
0045 class push_coroutine
0046 {
0047 private:
0048     template< typename V, typename X, typename Y, typename Z >
0049     friend class detail::pull_coroutine_object;
0050 
0051     typedef detail::push_coroutine_impl< Arg >          impl_type;
0052     typedef detail::push_coroutine_synthesized< Arg >   synth_type;
0053     typedef detail::parameters< Arg >                   param_type;
0054 
0055     struct dummy {};
0056 
0057     impl_type       *   impl_;
0058 
0059     BOOST_MOVABLE_BUT_NOT_COPYABLE( push_coroutine)
0060 
0061     explicit push_coroutine( detail::synthesized_t::flag_t, impl_type & impl) :
0062         impl_( & impl)
0063     { BOOST_ASSERT( impl_); }
0064 
0065 public:
0066     push_coroutine() BOOST_NOEXCEPT :
0067         impl_( 0)
0068     {}
0069 
0070 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
0071 # ifdef BOOST_MSVC
0072     typedef void ( * coroutine_fn)( pull_coroutine< Arg > &);
0073 
0074     explicit push_coroutine( coroutine_fn,
0075                              attributes const& = attributes() );
0076 
0077     template< typename StackAllocator >
0078     explicit push_coroutine( coroutine_fn,
0079                              attributes const&,
0080                              StackAllocator);
0081 # endif
0082     template< typename Fn >
0083     explicit push_coroutine( BOOST_RV_REF( Fn),
0084                              attributes const& = attributes() );
0085 
0086     template< typename Fn, typename StackAllocator >
0087     explicit push_coroutine( BOOST_RV_REF( Fn),
0088                              attributes const&,
0089                              StackAllocator);
0090 #else
0091     template< typename Fn >
0092     explicit push_coroutine( Fn fn,
0093                              attributes const& = attributes() );
0094 
0095     template< typename Fn, typename StackAllocator >
0096     explicit push_coroutine( Fn fn,
0097                              attributes const&,
0098                              StackAllocator);
0099 
0100     template< typename Fn >
0101     explicit push_coroutine( BOOST_RV_REF( Fn),
0102                              attributes const& = attributes() );
0103 
0104     template< typename Fn, typename StackAllocator >
0105     explicit push_coroutine( BOOST_RV_REF( Fn),
0106                              attributes const&,
0107                              StackAllocator);
0108 #endif
0109 
0110     ~push_coroutine()
0111     {
0112         if ( 0 != impl_)
0113         {
0114             impl_->destroy();
0115             impl_ = 0;
0116         }
0117     }
0118 
0119     push_coroutine( BOOST_RV_REF( push_coroutine) other) BOOST_NOEXCEPT :
0120         impl_( 0)
0121     { swap( other); }
0122 
0123     push_coroutine & operator=( BOOST_RV_REF( push_coroutine) other) BOOST_NOEXCEPT
0124     {
0125         push_coroutine tmp( boost::move( other) );
0126         swap( tmp);
0127         return * this;
0128     }
0129 
0130     BOOST_EXPLICIT_OPERATOR_BOOL();
0131 
0132     bool operator!() const BOOST_NOEXCEPT
0133     { return 0 == impl_ || impl_->is_complete(); }
0134 
0135     void swap( push_coroutine & other) BOOST_NOEXCEPT
0136     { std::swap( impl_, other.impl_); }
0137 
0138     push_coroutine & operator()( Arg arg)
0139     {
0140         BOOST_ASSERT( * this);
0141 
0142         impl_->push( arg);
0143         return * this;
0144     }
0145 
0146     class iterator
0147     {
0148     private:
0149        push_coroutine< Arg >    *   c_;
0150 
0151     public:
0152         typedef std::output_iterator_tag iterator_category;
0153         typedef void value_type;
0154         typedef void difference_type;
0155         typedef void pointer;
0156         typedef void reference;
0157 
0158         iterator() :
0159            c_( 0)
0160         {}
0161 
0162         explicit iterator( push_coroutine< Arg > * c) :
0163             c_( c)
0164         {}
0165 
0166         iterator & operator=( Arg a)
0167         {
0168             BOOST_ASSERT( c_);
0169             if ( ! ( * c_)( a) ) c_ = 0;
0170             return * this;
0171         }
0172 
0173         bool operator==( iterator const& other) const
0174         { return other.c_ == c_; }
0175 
0176         bool operator!=( iterator const& other) const
0177         { return other.c_ != c_; }
0178 
0179         iterator & operator*()
0180         { return * this; }
0181 
0182         iterator & operator++()
0183         { return * this; }
0184     };
0185 
0186     struct const_iterator;
0187 };
0188 
0189 template< typename Arg >
0190 class push_coroutine< Arg & >
0191 {
0192 private:
0193     template< typename V, typename X, typename Y, typename Z >
0194     friend class detail::pull_coroutine_object;
0195 
0196     typedef detail::push_coroutine_impl< Arg & >          impl_type;
0197     typedef detail::push_coroutine_synthesized< Arg & >   synth_type;
0198     typedef detail::parameters< Arg & >                   param_type;
0199 
0200     struct dummy {};
0201 
0202     impl_type       *   impl_;
0203 
0204     BOOST_MOVABLE_BUT_NOT_COPYABLE( push_coroutine)
0205 
0206     explicit push_coroutine( detail::synthesized_t::flag_t, impl_type & impl) :
0207         impl_( & impl)
0208     { BOOST_ASSERT( impl_); }
0209 
0210 public:
0211     push_coroutine() BOOST_NOEXCEPT :
0212         impl_( 0)
0213     {}
0214 
0215 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
0216 # ifdef BOOST_MSVC
0217     typedef void ( * coroutine_fn)( pull_coroutine< Arg & > &);
0218 
0219     explicit push_coroutine( coroutine_fn,
0220                              attributes const& = attributes() );
0221 
0222     template< typename StackAllocator >
0223     explicit push_coroutine( coroutine_fn,
0224                              attributes const&,
0225                              StackAllocator);
0226 # endif
0227     template< typename Fn >
0228     explicit push_coroutine( BOOST_RV_REF( Fn),
0229                              attributes const& = attributes() );
0230 
0231     template< typename Fn, typename StackAllocator >
0232     explicit push_coroutine( BOOST_RV_REF( Fn),
0233                              attributes const&,
0234                              StackAllocator);
0235 #else
0236     template< typename Fn >
0237     explicit push_coroutine( Fn,
0238                              attributes const& = attributes() );
0239 
0240     template< typename Fn, typename StackAllocator >
0241     explicit push_coroutine( Fn,
0242                              attributes const&,
0243                              StackAllocator);
0244 
0245     template< typename Fn >
0246     explicit push_coroutine( BOOST_RV_REF( Fn),
0247                              attributes const& = attributes() );
0248 
0249     template< typename Fn, typename StackAllocator >
0250     explicit push_coroutine( BOOST_RV_REF( Fn),
0251                              attributes const&,
0252                              StackAllocator);
0253 #endif
0254 
0255     ~push_coroutine()
0256     {
0257         if ( 0 != impl_)
0258         {
0259             impl_->destroy();
0260             impl_ = 0;
0261         }
0262     }
0263 
0264     push_coroutine( BOOST_RV_REF( push_coroutine) other) BOOST_NOEXCEPT :
0265         impl_( 0)
0266     { swap( other); }
0267 
0268     push_coroutine & operator=( BOOST_RV_REF( push_coroutine) other) BOOST_NOEXCEPT
0269     {
0270         push_coroutine tmp( boost::move( other) );
0271         swap( tmp);
0272         return * this;
0273     }
0274 
0275     BOOST_EXPLICIT_OPERATOR_BOOL();
0276 
0277     bool operator!() const BOOST_NOEXCEPT
0278     { return 0 == impl_ || impl_->is_complete(); }
0279 
0280     void swap( push_coroutine & other) BOOST_NOEXCEPT
0281     { std::swap( impl_, other.impl_); }
0282 
0283     push_coroutine & operator()( Arg & arg)
0284     {
0285         BOOST_ASSERT( * this);
0286 
0287         impl_->push( arg);
0288         return * this;
0289     }
0290 
0291     class iterator
0292     {
0293     private:
0294        push_coroutine< Arg & >  *   c_;
0295 
0296     public:
0297         typedef std::output_iterator_tag iterator_category;
0298         typedef void value_type;
0299         typedef void difference_type;
0300         typedef void pointer;
0301         typedef void reference;
0302 
0303         iterator() :
0304            c_( 0)
0305         {}
0306 
0307         explicit iterator( push_coroutine< Arg & > * c) :
0308             c_( c)
0309         {}
0310 
0311         iterator & operator=( Arg & a)
0312         {
0313             BOOST_ASSERT( c_);
0314             if ( ! ( * c_)( a) ) c_ = 0;
0315             return * this;
0316         }
0317 
0318         bool operator==( iterator const& other) const
0319         { return other.c_ == c_; }
0320 
0321         bool operator!=( iterator const& other) const
0322         { return other.c_ != c_; }
0323 
0324         iterator & operator*()
0325         { return * this; }
0326 
0327         iterator & operator++()
0328         { return * this; }
0329     };
0330 
0331     struct const_iterator;
0332 };
0333 
0334 template<>
0335 class push_coroutine< void >
0336 {
0337 private:
0338     template< typename V, typename X, typename Y, typename Z >
0339     friend class detail::pull_coroutine_object;
0340 
0341     typedef detail::push_coroutine_impl< void >          impl_type;
0342     typedef detail::push_coroutine_synthesized< void >   synth_type;
0343     typedef detail::parameters< void >                   param_type;
0344 
0345     struct dummy {};
0346 
0347     impl_type       *   impl_;
0348 
0349     BOOST_MOVABLE_BUT_NOT_COPYABLE( push_coroutine)
0350 
0351     explicit push_coroutine( detail::synthesized_t::flag_t, impl_type & impl) :
0352         impl_( & impl)
0353     { BOOST_ASSERT( impl_); }
0354 
0355 public:
0356     push_coroutine() BOOST_NOEXCEPT :
0357         impl_( 0)
0358     {}
0359 
0360 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
0361 # ifdef BOOST_MSVC
0362     typedef void ( * coroutine_fn)( pull_coroutine< void > &);
0363 
0364     explicit push_coroutine( coroutine_fn,
0365                              attributes const& = attributes() );
0366 
0367     template< typename StackAllocator >
0368     explicit push_coroutine( coroutine_fn,
0369                              attributes const&,
0370                              StackAllocator);
0371 # endif
0372     template< typename Fn >
0373     explicit push_coroutine( BOOST_RV_REF( Fn),
0374                              attributes const& = attributes() );
0375 
0376     template< typename Fn, typename StackAllocator >
0377     explicit push_coroutine( BOOST_RV_REF( Fn),
0378                              attributes const&,
0379                              StackAllocator);
0380 #else
0381     template< typename Fn >
0382     explicit push_coroutine( Fn,
0383                              attributes const& = attributes() );
0384 
0385     template< typename Fn, typename StackAllocator >
0386     explicit push_coroutine( Fn,
0387                              attributes const&,
0388                              StackAllocator);
0389 
0390     template< typename Fn >
0391     explicit push_coroutine( BOOST_RV_REF( Fn),
0392                              attributes const& = attributes() );
0393 
0394     template< typename Fn, typename StackAllocator >
0395     explicit push_coroutine( BOOST_RV_REF( Fn),
0396                              attributes const&,
0397                              StackAllocator);
0398 #endif
0399 
0400     ~push_coroutine()
0401     {
0402         if ( 0 != impl_)
0403         {
0404             impl_->destroy();
0405             impl_ = 0;
0406         }
0407     }
0408 
0409     inline push_coroutine( BOOST_RV_REF( push_coroutine) other) BOOST_NOEXCEPT :
0410         impl_( 0)
0411     { swap( other); }
0412 
0413     inline push_coroutine & operator=( BOOST_RV_REF( push_coroutine) other) BOOST_NOEXCEPT
0414     {
0415         push_coroutine tmp( boost::move( other) );
0416         swap( tmp);
0417         return * this;
0418     }
0419 
0420     BOOST_EXPLICIT_OPERATOR_BOOL();
0421 
0422     inline bool operator!() const BOOST_NOEXCEPT
0423     { return 0 == impl_ || impl_->is_complete(); }
0424 
0425     inline void swap( push_coroutine & other) BOOST_NOEXCEPT
0426     { std::swap( impl_, other.impl_); }
0427 
0428     inline push_coroutine & operator()()
0429     {
0430         BOOST_ASSERT( * this);
0431 
0432         impl_->push();
0433         return * this;
0434     }
0435 
0436     struct iterator;
0437     struct const_iterator;
0438 };
0439 
0440 
0441 
0442 template< typename R >
0443 class pull_coroutine
0444 {
0445 private:
0446     template< typename V, typename X, typename Y, typename Z >
0447     friend class detail::push_coroutine_object;
0448 
0449     typedef detail::pull_coroutine_impl< R >            impl_type;
0450     typedef detail::pull_coroutine_synthesized< R >     synth_type;
0451     typedef detail::parameters< R >                     param_type;
0452 
0453     struct dummy {};
0454 
0455     impl_type       *   impl_;
0456 
0457     BOOST_MOVABLE_BUT_NOT_COPYABLE( pull_coroutine)
0458 
0459     explicit pull_coroutine( detail::synthesized_t::flag_t, impl_type & impl) :
0460         impl_( & impl)
0461     { BOOST_ASSERT( impl_); }
0462 
0463 public:
0464     pull_coroutine() BOOST_NOEXCEPT :
0465         impl_( 0)
0466     {}
0467 
0468 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
0469 # ifdef BOOST_MSVC
0470     typedef void ( * coroutine_fn)( push_coroutine< R > &);
0471 
0472     explicit pull_coroutine( coroutine_fn fn,
0473                              attributes const& attrs = attributes() ) :
0474         impl_( 0)
0475     {
0476         // create a stack-context
0477         stack_context stack_ctx;
0478         stack_allocator stack_alloc;
0479         // allocate the coroutine-stack
0480         stack_alloc.allocate( stack_ctx, attrs.size);
0481         BOOST_ASSERT( 0 != stack_ctx.sp);
0482         // typedef of internal coroutine-type
0483         typedef detail::pull_coroutine_object<
0484             push_coroutine< R >, R, coroutine_fn, stack_allocator
0485         >                                                        object_t;
0486         // reserve space on top of coroutine-stack for internal coroutine-type
0487         std::size_t size = stack_ctx.size - sizeof( object_t);
0488         BOOST_ASSERT( 0 != size);
0489         void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
0490         BOOST_ASSERT( 0 != sp);
0491         // placement new for internal coroutine
0492         impl_ = new ( sp) object_t(
0493                 boost::forward< coroutine_fn >( fn), attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc); 
0494         BOOST_ASSERT( impl_);
0495         impl_->pull();
0496     }
0497 
0498     template< typename StackAllocator >
0499     explicit pull_coroutine( coroutine_fn fn,
0500                              attributes const& attrs,
0501                              StackAllocator stack_alloc) :
0502         impl_( 0)
0503     {
0504         // create a stack-context
0505         stack_context stack_ctx;
0506         // allocate the coroutine-stack
0507         stack_alloc.allocate( stack_ctx, attrs.size);
0508         BOOST_ASSERT( 0 != stack_ctx.sp);
0509         // typedef of internal coroutine-type
0510         typedef detail::pull_coroutine_object<
0511             push_coroutine< R >, R, coroutine_fn, StackAllocator
0512         >                                                        object_t;
0513         // reserve space on top of coroutine-stack for internal coroutine-type
0514         std::size_t size = stack_ctx.size - sizeof( object_t);
0515         BOOST_ASSERT( 0 != size);
0516         void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
0517         BOOST_ASSERT( 0 != sp);
0518         // placement new for internal coroutine
0519         impl_ = new ( sp) object_t(
0520                 boost::forward< coroutine_fn >( fn), attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc); 
0521         BOOST_ASSERT( impl_);
0522         impl_->pull();
0523     }
0524 # endif
0525     template< typename Fn >
0526     explicit pull_coroutine( BOOST_RV_REF( Fn) fn,
0527                              attributes const& attrs = attributes() ) :
0528         impl_( 0)
0529     {
0530         // create a stack-context
0531         stack_context stack_ctx;
0532         stack_allocator stack_alloc;
0533         // allocate the coroutine-stack
0534         stack_alloc.allocate( stack_ctx, attrs.size);
0535         BOOST_ASSERT( 0 != stack_ctx.sp);
0536         // typedef of internal coroutine-type
0537         typedef detail::pull_coroutine_object<
0538             push_coroutine< R >, R, Fn, stack_allocator
0539         >                                                        object_t;
0540         // reserve space on top of coroutine-stack for internal coroutine-type
0541         std::size_t size = stack_ctx.size - sizeof( object_t);
0542         BOOST_ASSERT( 0 != size);
0543         void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
0544         BOOST_ASSERT( 0 != sp);
0545         // placement new for internal coroutine
0546         impl_ = new ( sp) object_t(
0547                 boost::forward< Fn >( fn), attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc); 
0548         BOOST_ASSERT( impl_);
0549         impl_->pull();
0550     }
0551 
0552     template< typename Fn, typename StackAllocator >
0553     explicit pull_coroutine( BOOST_RV_REF( Fn) fn,
0554                              attributes const& attrs,
0555                              StackAllocator stack_alloc) :
0556         impl_( 0)
0557     {
0558         // create a stack-context
0559         stack_context stack_ctx;
0560         // allocate the coroutine-stack
0561         stack_alloc.allocate( stack_ctx, attrs.size);
0562         BOOST_ASSERT( 0 != stack_ctx.sp);
0563         // typedef of internal coroutine-type
0564         typedef detail::pull_coroutine_object<
0565             push_coroutine< R >, R, Fn, StackAllocator
0566         >                                                        object_t;
0567         // reserve space on top of coroutine-stack for internal coroutine-type
0568         std::size_t size = stack_ctx.size - sizeof( object_t);
0569         BOOST_ASSERT( 0 != size);
0570         void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
0571         BOOST_ASSERT( 0 != sp);
0572         // placement new for internal coroutine
0573         impl_ = new ( sp) object_t(
0574                 boost::forward< Fn >( fn), attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc); 
0575         BOOST_ASSERT( impl_);
0576         impl_->pull();
0577     }
0578 #else
0579     template< typename Fn >
0580     explicit pull_coroutine( Fn fn,
0581                              attributes const& attrs = attributes() ) :
0582         impl_( 0)
0583     {
0584         // create a stack-context
0585         stack_context stack_ctx;
0586         stack_allocator stack_alloc;
0587         // allocate the coroutine-stack
0588         stack_alloc.allocate( stack_ctx, attrs.size);
0589         BOOST_ASSERT( 0 != stack_ctx.sp);
0590         // typedef of internal coroutine-type
0591         typedef detail::pull_coroutine_object<
0592             push_coroutine< R >, R, Fn, stack_allocator
0593         >                                                        object_t;
0594         // reserve space on top of coroutine-stack for internal coroutine-type
0595         std::size_t size = stack_ctx.size - sizeof( object_t);
0596         BOOST_ASSERT( 0 != size);
0597         void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
0598         BOOST_ASSERT( 0 != sp);
0599         // placement new for internal coroutine
0600         impl_ = new ( sp) object_t(
0601                 fn, attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc); 
0602         BOOST_ASSERT( impl_);
0603         impl_->pull();
0604     }
0605 
0606     template< typename Fn, typename StackAllocator >
0607     explicit pull_coroutine( Fn fn,
0608                              attributes const& attrs,
0609                              StackAllocator stack_alloc) :
0610         impl_( 0)
0611     {
0612         // create a stack-context
0613         stack_context stack_ctx;
0614         // allocate the coroutine-stack
0615         stack_alloc.allocate( stack_ctx, attrs.size);
0616         BOOST_ASSERT( 0 != stack_ctx.sp);
0617         // typedef of internal coroutine-type
0618         typedef detail::pull_coroutine_object<
0619             push_coroutine< R >, R, Fn, StackAllocator
0620         >                                                        object_t;
0621         // reserve space on top of coroutine-stack for internal coroutine-type
0622         std::size_t size = stack_ctx.size - sizeof( object_t);
0623         BOOST_ASSERT( 0 != size);
0624         void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
0625         BOOST_ASSERT( 0 != sp);
0626         // placement new for internal coroutine
0627         impl_ = new ( sp) object_t(
0628                 fn, attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc); 
0629         BOOST_ASSERT( impl_);
0630         impl_->pull();
0631     }
0632 
0633     template< typename Fn >
0634     explicit pull_coroutine( BOOST_RV_REF( Fn) fn,
0635                              attributes const& attrs = attributes() ) :
0636         impl_( 0)
0637     {
0638         // create a stack-context
0639         stack_context stack_ctx;
0640         stack_allocator stack_alloc;
0641         // allocate the coroutine-stack
0642         stack_alloc.allocate( stack_ctx, attrs.size);
0643         BOOST_ASSERT( 0 != stack_ctx.sp);
0644         // typedef of internal coroutine-type
0645         typedef detail::pull_coroutine_object<
0646             push_coroutine< R >, R, Fn, stack_allocator
0647         >                                                        object_t;
0648         // reserve space on top of coroutine-stack for internal coroutine-type
0649         std::size_t size = stack_ctx.size - sizeof( object_t);
0650         BOOST_ASSERT( 0 != size);
0651         void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
0652         BOOST_ASSERT( 0 != sp);
0653         // placement new for internal coroutine
0654         impl_ = new ( sp) object_t(
0655                 fn, attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc); 
0656         BOOST_ASSERT( impl_);
0657         impl_->pull();
0658     }
0659 
0660     template< typename Fn, typename StackAllocator >
0661     explicit pull_coroutine( BOOST_RV_REF( Fn) fn,
0662                              attributes const& attrs,
0663                              StackAllocator stack_alloc) :
0664         impl_( 0)
0665     {
0666         // create a stack-context
0667         stack_context stack_ctx;
0668         // allocate the coroutine-stack
0669         stack_alloc.allocate( stack_ctx, attrs.size);
0670         BOOST_ASSERT( 0 != stack_ctx.sp);
0671         // typedef of internal coroutine-type
0672         typedef detail::pull_coroutine_object<
0673             push_coroutine< R >, R, Fn, StackAllocator
0674         >                                                        object_t;
0675         // reserve space on top of coroutine-stack for internal coroutine-type
0676         std::size_t size = stack_ctx.size - sizeof( object_t);
0677         BOOST_ASSERT( 0 != size);
0678         void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
0679         BOOST_ASSERT( 0 != sp);
0680         // placement new for internal coroutine
0681         impl_ = new ( sp) object_t(
0682                 fn, attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc); 
0683         BOOST_ASSERT( impl_);
0684         impl_->pull();
0685     }
0686 #endif
0687 
0688     ~pull_coroutine()
0689     {
0690         if ( 0 != impl_)
0691         {
0692             impl_->destroy();
0693             impl_ = 0;
0694         }
0695     }
0696 
0697     pull_coroutine( BOOST_RV_REF( pull_coroutine) other) BOOST_NOEXCEPT :
0698         impl_( 0)
0699     { swap( other); }
0700 
0701     pull_coroutine & operator=( BOOST_RV_REF( pull_coroutine) other) BOOST_NOEXCEPT
0702     {
0703         pull_coroutine tmp( boost::move( other) );
0704         swap( tmp);
0705         return * this;
0706     }
0707 
0708     BOOST_EXPLICIT_OPERATOR_BOOL();
0709 
0710     bool operator!() const BOOST_NOEXCEPT
0711     { return 0 == impl_ || impl_->is_complete(); }
0712 
0713     void swap( pull_coroutine & other) BOOST_NOEXCEPT
0714     { std::swap( impl_, other.impl_); }
0715 
0716     pull_coroutine & operator()()
0717     {
0718         BOOST_ASSERT( * this);
0719 
0720         impl_->pull();
0721         return * this;
0722     }
0723 
0724     R get() const
0725     {
0726         BOOST_ASSERT( 0 != impl_);
0727 
0728         return impl_->get();
0729     }
0730 
0731     class iterator
0732     {
0733     private:
0734         pull_coroutine< R > *   c_;
0735         R                   *   val_;
0736 
0737         void fetch_()
0738         {
0739             BOOST_ASSERT( c_);
0740 
0741             if ( ! ( * c_) )
0742             {
0743                 c_ = 0;
0744                 val_ = 0;
0745                 return;
0746             }
0747             val_ = c_->impl_->get_pointer();
0748         }
0749 
0750         void increment_()
0751         {
0752             BOOST_ASSERT( c_);
0753             BOOST_ASSERT( * c_);
0754 
0755             ( * c_)();
0756             fetch_();
0757         }
0758 
0759     public:
0760         typedef std::input_iterator_tag iterator_category;
0761         typedef typename remove_reference< R >::type value_type;
0762         typedef std::ptrdiff_t difference_type;
0763         typedef value_type * pointer;
0764         typedef value_type & reference;
0765 
0766         typedef pointer   pointer_t;
0767         typedef reference reference_t;
0768 
0769         iterator() :
0770             c_( 0), val_( 0)
0771         {}
0772 
0773         explicit iterator( pull_coroutine< R > * c) :
0774             c_( c), val_( 0)
0775         { fetch_(); }
0776 
0777         iterator( iterator const& other) :
0778             c_( other.c_), val_( other.val_)
0779         {}
0780 
0781         iterator & operator=( iterator const& other)
0782         {
0783             if ( this == & other) return * this;
0784             c_ = other.c_;
0785             val_ = other.val_;
0786             return * this;
0787         }
0788 
0789         bool operator==( iterator const& other) const
0790         { return other.c_ == c_ && other.val_ == val_; }
0791 
0792         bool operator!=( iterator const& other) const
0793         { return other.c_ != c_ || other.val_ != val_; }
0794 
0795         iterator & operator++()
0796         {
0797             increment_();
0798             return * this;
0799         }
0800 
0801         iterator operator++( int);
0802 
0803         reference_t operator*() const
0804         {
0805             if ( ! val_)
0806                 boost::throw_exception(
0807                     invalid_result() );
0808             return * val_;
0809         }
0810 
0811         pointer_t operator->() const
0812         {
0813             if ( ! val_)
0814                 boost::throw_exception(
0815                     invalid_result() );
0816             return val_;
0817         }
0818     };
0819 
0820     class const_iterator
0821     {
0822     private:
0823         pull_coroutine< R > *   c_;
0824         R                   *   val_;
0825 
0826         void fetch_()
0827         {
0828             BOOST_ASSERT( c_);
0829 
0830             if ( ! ( * c_) )
0831             {
0832                 c_ = 0;
0833                 val_ = 0;
0834                 return;
0835             }
0836             val_ = c_->impl_->get_pointer();
0837         }
0838 
0839         void increment_()
0840         {
0841             BOOST_ASSERT( c_);
0842             BOOST_ASSERT( * c_);
0843 
0844             ( * c_)();
0845             fetch_();
0846         }
0847 
0848     public:
0849         typedef std::input_iterator_tag iterator_category;
0850         typedef const typename remove_reference< R >::type value_type;
0851         typedef std::ptrdiff_t difference_type;
0852         typedef value_type * pointer;
0853         typedef value_type & reference;
0854 
0855         typedef pointer   pointer_t;
0856         typedef reference reference_t;
0857 
0858         const_iterator() :
0859             c_( 0), val_( 0)
0860         {}
0861 
0862         explicit const_iterator( pull_coroutine< R > const* c) :
0863             c_( const_cast< pull_coroutine< R > * >( c) ),
0864             val_( 0)
0865         { fetch_(); }
0866 
0867         const_iterator( const_iterator const& other) :
0868             c_( other.c_), val_( other.val_)
0869         {}
0870 
0871         const_iterator & operator=( const_iterator const& other)
0872         {
0873             if ( this == & other) return * this;
0874             c_ = other.c_;
0875             val_ = other.val_;
0876             return * this;
0877         }
0878 
0879         bool operator==( const_iterator const& other) const
0880         { return other.c_ == c_ && other.val_ == val_; }
0881 
0882         bool operator!=( const_iterator const& other) const
0883         { return other.c_ != c_ || other.val_ != val_; }
0884 
0885         const_iterator & operator++()
0886         {
0887             increment_();
0888             return * this;
0889         }
0890 
0891         const_iterator operator++( int);
0892 
0893         reference_t operator*() const
0894         {
0895             if ( ! val_)
0896                 boost::throw_exception(
0897                     invalid_result() );
0898             return * val_;
0899         }
0900 
0901         pointer_t operator->() const
0902         {
0903             if ( ! val_)
0904                 boost::throw_exception(
0905                     invalid_result() );
0906             return val_;
0907         }
0908     };
0909 
0910     friend class iterator;
0911     friend class const_iterator;
0912 };
0913 
0914 template< typename R >
0915 class pull_coroutine< R & >
0916 {
0917 private:
0918     template< typename V, typename X, typename Y, typename Z >
0919     friend class detail::push_coroutine_object;
0920 
0921     typedef detail::pull_coroutine_impl< R & >            impl_type;
0922     typedef detail::pull_coroutine_synthesized< R & >     synth_type;
0923     typedef detail::parameters< R & >                     param_type;
0924 
0925     struct dummy {};
0926 
0927     impl_type       *   impl_;
0928 
0929     BOOST_MOVABLE_BUT_NOT_COPYABLE( pull_coroutine)
0930 
0931     explicit pull_coroutine( detail::synthesized_t::flag_t, impl_type & impl) :
0932         impl_( & impl)
0933     { BOOST_ASSERT( impl_); }
0934 
0935 public:
0936     pull_coroutine() BOOST_NOEXCEPT :
0937         impl_( 0)
0938     {}
0939 
0940 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
0941 # ifdef BOOST_MSVC
0942     typedef void ( * coroutine_fn)( push_coroutine< R & > &);
0943 
0944     explicit pull_coroutine( coroutine_fn fn,
0945                              attributes const& attrs = attributes() ) :
0946         impl_( 0)
0947     {
0948         // create a stack-context
0949         stack_context stack_ctx;
0950         stack_allocator stack_alloc;
0951         // allocate the coroutine-stack
0952         stack_alloc.allocate( stack_ctx, attrs.size);
0953         BOOST_ASSERT( 0 != stack_ctx.sp);
0954         // typedef of internal coroutine-type
0955         typedef detail::pull_coroutine_object<
0956             push_coroutine< R & >, R &, coroutine_fn, stack_allocator
0957         >                                                        object_t;
0958         // reserve space on top of coroutine-stack for internal coroutine-type
0959         std::size_t size = stack_ctx.size - sizeof( object_t);
0960         BOOST_ASSERT( 0 != size);
0961         void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
0962         BOOST_ASSERT( 0 != sp);
0963         // placement new for internal coroutine
0964         impl_ = new ( sp) object_t(
0965                 boost::forward< coroutine_fn >( fn), attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc); 
0966         BOOST_ASSERT( impl_);
0967         impl_->pull();
0968     }
0969 
0970     template< typename StackAllocator >
0971     explicit pull_coroutine( coroutine_fn fn,
0972                              attributes const& attrs,
0973                              StackAllocator stack_alloc) :
0974         impl_( 0)
0975     {
0976         // create a stack-context
0977         stack_context stack_ctx;
0978         // allocate the coroutine-stack
0979         stack_alloc.allocate( stack_ctx, attrs.size);
0980         BOOST_ASSERT( 0 != stack_ctx.sp);
0981         // typedef of internal coroutine-type
0982         typedef detail::pull_coroutine_object<
0983             push_coroutine< R & >, R &, coroutine_fn, StackAllocator
0984         >                                                        object_t;
0985         // reserve space on top of coroutine-stack for internal coroutine-type
0986         std::size_t size = stack_ctx.size - sizeof( object_t);
0987         BOOST_ASSERT( 0 != size);
0988         void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
0989         BOOST_ASSERT( 0 != sp);
0990         // placement new for internal coroutine
0991         impl_ = new ( sp) object_t(
0992                 boost::forward< coroutine_fn >( fn), attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc); 
0993         BOOST_ASSERT( impl_);
0994         impl_->pull();
0995     }
0996 # endif
0997     template< typename Fn >
0998     explicit pull_coroutine( BOOST_RV_REF( Fn) fn,
0999                              attributes const& attrs = attributes() ) :
1000         impl_( 0)
1001     {
1002         // create a stack-context
1003         stack_context stack_ctx;
1004         stack_allocator stack_alloc;
1005         // allocate the coroutine-stack
1006         stack_alloc.allocate( stack_ctx, attrs.size);
1007         BOOST_ASSERT( 0 != stack_ctx.sp);
1008         // typedef of internal coroutine-type
1009         typedef detail::pull_coroutine_object<
1010             push_coroutine< R & >, R &, Fn, stack_allocator
1011         >                                                        object_t;
1012         // reserve space on top of coroutine-stack for internal coroutine-type
1013         std::size_t size = stack_ctx.size - sizeof( object_t);
1014         BOOST_ASSERT( 0 != size);
1015         void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
1016         BOOST_ASSERT( 0 != sp);
1017         // placement new for internal coroutine
1018         impl_ = new ( sp) object_t(
1019                 boost::forward< Fn >( fn), attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc); 
1020         BOOST_ASSERT( impl_);
1021         impl_->pull();
1022     }
1023 
1024     template< typename Fn, typename StackAllocator >
1025     explicit pull_coroutine( BOOST_RV_REF( Fn) fn,
1026                              attributes const& attrs,
1027                              StackAllocator stack_alloc) :
1028         impl_( 0)
1029     {
1030         // create a stack-context
1031         stack_context stack_ctx;
1032         // allocate the coroutine-stack
1033         stack_alloc.allocate( stack_ctx, attrs.size);
1034         BOOST_ASSERT( 0 != stack_ctx.sp);
1035         // typedef of internal coroutine-type
1036         typedef detail::pull_coroutine_object<
1037             push_coroutine< R & >, R &, Fn, StackAllocator
1038         >                                                        object_t;
1039         // reserve space on top of coroutine-stack for internal coroutine-type
1040         std::size_t size = stack_ctx.size - sizeof( object_t);
1041         BOOST_ASSERT( 0 != size);
1042         void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
1043         BOOST_ASSERT( 0 != sp);
1044         // placement new for internal coroutine
1045         impl_ = new ( sp) object_t(
1046                 boost::forward< Fn >( fn), attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc); 
1047         BOOST_ASSERT( impl_);
1048         impl_->pull();
1049     }
1050 #else
1051     template< typename Fn >
1052     explicit pull_coroutine( Fn fn,
1053                              attributes const& attrs = attributes() ) :
1054         impl_( 0)
1055     {
1056         // create a stack-context
1057         stack_context stack_ctx;
1058         stack_allocator stack_alloc;
1059         // allocate the coroutine-stack
1060         stack_alloc.allocate( stack_ctx, attrs.size);
1061         BOOST_ASSERT( 0 != stack_ctx.sp);
1062         // typedef of internal coroutine-type
1063         typedef detail::pull_coroutine_object<
1064             push_coroutine< R & >, R &, Fn, stack_allocator
1065         >                                                        object_t;
1066         // reserve space on top of coroutine-stack for internal coroutine-type
1067         std::size_t size = stack_ctx.size - sizeof( object_t);
1068         BOOST_ASSERT( 0 != size);
1069         void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
1070         BOOST_ASSERT( 0 != sp);
1071         // placement new for internal coroutine
1072         impl_ = new ( sp) object_t(
1073                 fn, attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc); 
1074         BOOST_ASSERT( impl_);
1075         impl_->pull();
1076     }
1077 
1078     template< typename Fn, typename StackAllocator >
1079     explicit pull_coroutine( Fn fn,
1080                              attributes const& attrs,
1081                              StackAllocator stack_alloc) :
1082         impl_( 0)
1083     {
1084         // create a stack-context
1085         stack_context stack_ctx;
1086         // allocate the coroutine-stack
1087         stack_alloc.allocate( stack_ctx, attrs.size);
1088         BOOST_ASSERT( 0 != stack_ctx.sp);
1089         // typedef of internal coroutine-type
1090         typedef detail::pull_coroutine_object<
1091             push_coroutine< R & >, R &, Fn, StackAllocator
1092         >                                                        object_t;
1093         // reserve space on top of coroutine-stack for internal coroutine-type
1094         std::size_t size = stack_ctx.size - sizeof( object_t);
1095         BOOST_ASSERT( 0 != size);
1096         void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
1097         BOOST_ASSERT( 0 != sp);
1098         // placement new for internal coroutine
1099         impl_ = new ( sp) object_t(
1100                 fn, attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc); 
1101         BOOST_ASSERT( impl_);
1102         impl_->pull();
1103     }
1104 
1105     template< typename Fn >
1106     explicit pull_coroutine( BOOST_RV_REF( Fn) fn,
1107                              attributes const& attrs = attributes() ) :
1108         impl_( 0)
1109     {
1110         // create a stack-context
1111         stack_context stack_ctx;
1112         stack_allocator stack_alloc;
1113         // allocate the coroutine-stack
1114         stack_alloc.allocate( stack_ctx, attrs.size);
1115         BOOST_ASSERT( 0 != stack_ctx.sp);
1116         // typedef of internal coroutine-type
1117         typedef detail::pull_coroutine_object<
1118             push_coroutine< R & >, R &, Fn, stack_allocator
1119         >                                                        object_t;
1120         // reserve space on top of coroutine-stack for internal coroutine-type
1121         std::size_t size = stack_ctx.size - sizeof( object_t);
1122         BOOST_ASSERT( 0 != size);
1123         void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
1124         BOOST_ASSERT( 0 != sp);
1125         // placement new for internal coroutine
1126         impl_ = new ( sp) object_t(
1127                 fn, attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc); 
1128         BOOST_ASSERT( impl_);
1129         impl_->pull();
1130     }
1131 
1132     template< typename Fn, typename StackAllocator >
1133     explicit pull_coroutine( BOOST_RV_REF( Fn) fn,
1134                              attributes const& attrs,
1135                              StackAllocator stack_alloc) :
1136         impl_( 0)
1137     {
1138         // create a stack-context
1139         stack_context stack_ctx;
1140         // allocate the coroutine-stack
1141         stack_alloc.allocate( stack_ctx, attrs.size);
1142         BOOST_ASSERT( 0 != stack_ctx.sp);
1143         // typedef of internal coroutine-type
1144         typedef detail::pull_coroutine_object<
1145             push_coroutine< R & >, R &, Fn, StackAllocator
1146         >                                                        object_t;
1147         // reserve space on top of coroutine-stack for internal coroutine-type
1148         std::size_t size = stack_ctx.size - sizeof( object_t);
1149         BOOST_ASSERT( 0 != size);
1150         void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
1151         BOOST_ASSERT( 0 != sp);
1152         // placement new for internal coroutine
1153         impl_ = new ( sp) object_t(
1154                 fn, attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc); 
1155         BOOST_ASSERT( impl_);
1156         impl_->pull();
1157     }
1158 #endif
1159 
1160     ~pull_coroutine()
1161     {
1162         if ( 0 != impl_)
1163         {
1164             impl_->destroy();
1165             impl_ = 0;
1166         }
1167     }
1168 
1169     pull_coroutine( BOOST_RV_REF( pull_coroutine) other) BOOST_NOEXCEPT :
1170         impl_( 0)
1171     { swap( other); }
1172 
1173     pull_coroutine & operator=( BOOST_RV_REF( pull_coroutine) other) BOOST_NOEXCEPT
1174     {
1175         pull_coroutine tmp( boost::move( other) );
1176         swap( tmp);
1177         return * this;
1178     }
1179 
1180     BOOST_EXPLICIT_OPERATOR_BOOL();
1181 
1182     bool operator!() const BOOST_NOEXCEPT
1183     { return 0 == impl_ || impl_->is_complete(); }
1184 
1185     void swap( pull_coroutine & other) BOOST_NOEXCEPT
1186     { std::swap( impl_, other.impl_); }
1187 
1188     pull_coroutine & operator()()
1189     {
1190         BOOST_ASSERT( * this);
1191 
1192         impl_->pull();
1193         return * this;
1194     }
1195 
1196     R & get() const
1197     { return impl_->get(); }
1198 
1199     class iterator
1200     {
1201     private:
1202         pull_coroutine< R & >   *   c_;
1203         R                       *   val_;
1204 
1205         void fetch_()
1206         {
1207             BOOST_ASSERT( c_);
1208 
1209             if ( ! ( * c_) )
1210             {
1211                 c_ = 0;
1212                 val_ = 0;
1213                 return;
1214             }
1215             val_ = c_->impl_->get_pointer();
1216         }
1217 
1218         void increment_()
1219         {
1220             BOOST_ASSERT( c_);
1221             BOOST_ASSERT( * c_);
1222 
1223             ( * c_)();
1224             fetch_();
1225         }
1226 
1227     public:
1228         typedef std::input_iterator_tag iterator_category;
1229         typedef typename remove_reference< R >::type value_type;
1230         typedef std::ptrdiff_t difference_type;
1231         typedef value_type * pointer;
1232         typedef value_type & reference;
1233 
1234         typedef pointer   pointer_t;
1235         typedef reference reference_t;
1236 
1237         iterator() :
1238             c_( 0), val_( 0)
1239         {}
1240 
1241         explicit iterator( pull_coroutine< R & > * c) :
1242             c_( c), val_( 0)
1243         { fetch_(); }
1244 
1245         iterator( iterator const& other) :
1246             c_( other.c_), val_( other.val_)
1247         {}
1248 
1249         iterator & operator=( iterator const& other)
1250         {
1251             if ( this == & other) return * this;
1252             c_ = other.c_;
1253             val_ = other.val_;
1254             return * this;
1255         }
1256 
1257         bool operator==( iterator const& other) const
1258         { return other.c_ == c_ && other.val_ == val_; }
1259 
1260         bool operator!=( iterator const& other) const
1261         { return other.c_ != c_ || other.val_ != val_; }
1262 
1263         iterator & operator++()
1264         {
1265             increment_();
1266             return * this;
1267         }
1268 
1269         iterator operator++( int);
1270 
1271         reference_t operator*() const
1272         {
1273             if ( ! val_)
1274                 boost::throw_exception(
1275                     invalid_result() );
1276             return * val_;
1277         }
1278 
1279         pointer_t operator->() const
1280         {
1281             if ( ! val_)
1282                 boost::throw_exception(
1283                     invalid_result() );
1284             return val_;
1285         }
1286     };
1287 
1288     class const_iterator
1289     {
1290     private:
1291         pull_coroutine< R & >   *   c_;
1292         R                       *   val_;
1293 
1294         void fetch_()
1295         {
1296             BOOST_ASSERT( c_);
1297 
1298             if ( ! ( * c_) )
1299             {
1300                 c_ = 0;
1301                 val_ = 0;
1302                 return;
1303             }
1304             val_ = c_->impl_->get_pointer();
1305         }
1306 
1307         void increment_()
1308         {
1309             BOOST_ASSERT( c_);
1310             BOOST_ASSERT( * c_);
1311 
1312             ( * c_)();
1313             fetch_();
1314         }
1315 
1316     public:
1317         typedef std::input_iterator_tag iterator_category;
1318         typedef const typename remove_reference< R >::type value_type;
1319         typedef std::ptrdiff_t difference_type;
1320         typedef value_type * pointer;
1321         typedef value_type & reference;
1322 
1323         typedef pointer   pointer_t;
1324         typedef reference reference_t;
1325 
1326         const_iterator() :
1327             c_( 0), val_( 0)
1328         {}
1329 
1330         explicit const_iterator( pull_coroutine< R & > const* c) :
1331             c_( const_cast< pull_coroutine< R & > * >( c) ),
1332             val_( 0)
1333         { fetch_(); }
1334 
1335         const_iterator( const_iterator const& other) :
1336             c_( other.c_), val_( other.val_)
1337         {}
1338 
1339         const_iterator & operator=( const_iterator const& other)
1340         {
1341             if ( this == & other) return * this;
1342             c_ = other.c_;
1343             val_ = other.val_;
1344             return * this;
1345         }
1346 
1347         bool operator==( const_iterator const& other) const
1348         { return other.c_ == c_ && other.val_ == val_; }
1349 
1350         bool operator!=( const_iterator const& other) const
1351         { return other.c_ != c_ || other.val_ != val_; }
1352 
1353         const_iterator & operator++()
1354         {
1355             increment_();
1356             return * this;
1357         }
1358 
1359         const_iterator operator++( int);
1360 
1361         reference_t operator*() const
1362         {
1363             if ( ! val_)
1364                 boost::throw_exception(
1365                     invalid_result() );
1366             return * val_;
1367         }
1368 
1369         pointer_t operator->() const
1370         {
1371             if ( ! val_)
1372                 boost::throw_exception(
1373                     invalid_result() );
1374             return val_;
1375         }
1376     };
1377 
1378     friend class iterator;
1379     friend class const_iterator;
1380 };
1381 
1382 template<>
1383 class pull_coroutine< void >
1384 {
1385 private:
1386     template< typename V, typename X, typename Y, typename Z >
1387     friend class detail::push_coroutine_object;
1388 
1389     typedef detail::pull_coroutine_impl< void >            impl_type;
1390     typedef detail::pull_coroutine_synthesized< void >     synth_type;
1391     typedef detail::parameters< void >                     param_type;
1392 
1393     struct dummy {};
1394 
1395     impl_type       *   impl_;
1396 
1397     BOOST_MOVABLE_BUT_NOT_COPYABLE( pull_coroutine)
1398 
1399     explicit pull_coroutine( detail::synthesized_t::flag_t, impl_type & impl) :
1400         impl_( & impl)
1401     { BOOST_ASSERT( impl_); }
1402 
1403 public:
1404     pull_coroutine() BOOST_NOEXCEPT :
1405         impl_( 0)
1406     {}
1407 
1408 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
1409 # ifdef BOOST_MSVC
1410     typedef void ( * coroutine_fn)( push_coroutine< void > &);
1411 
1412     explicit pull_coroutine( coroutine_fn fn,
1413                              attributes const& attrs = attributes() ) :
1414         impl_( 0)
1415     {
1416         // create a stack-context
1417         stack_context stack_ctx;
1418         stack_allocator stack_alloc;
1419         // allocate the coroutine-stack
1420         stack_alloc.allocate( stack_ctx, attrs.size);
1421         BOOST_ASSERT( 0 != stack_ctx.sp);
1422         // typedef of internal coroutine-type
1423         typedef detail::pull_coroutine_object<
1424             push_coroutine< void >, void, coroutine_fn, stack_allocator
1425         >                                       object_t;
1426         // reserve space on top of coroutine-stack for internal coroutine-type
1427         std::size_t size = stack_ctx.size - sizeof( object_t);
1428         BOOST_ASSERT( 0 != size);
1429         void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
1430         BOOST_ASSERT( 0 != sp);
1431         // placement new for internal coroutine
1432         impl_ = new ( sp) object_t(
1433                 boost::forward< coroutine_fn >( fn), attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc); 
1434         BOOST_ASSERT( impl_);
1435         impl_->pull();
1436     }
1437 
1438     template< typename StackAllocator >
1439     explicit pull_coroutine( coroutine_fn fn,
1440                              attributes const& attrs,
1441                              StackAllocator stack_alloc) :
1442         impl_( 0)
1443     {
1444         // create a stack-context
1445         stack_context stack_ctx;
1446         // allocate the coroutine-stack
1447         stack_alloc.allocate( stack_ctx, attrs.size);
1448         BOOST_ASSERT( 0 != stack_ctx.sp);
1449         // typedef of internal coroutine-type
1450         typedef detail::pull_coroutine_object<
1451             push_coroutine< void >, void, coroutine_fn, StackAllocator
1452         >                                                                   object_t;
1453         // reserve space on top of coroutine-stack for internal coroutine-type
1454         std::size_t size = stack_ctx.size - sizeof( object_t);
1455         BOOST_ASSERT( 0 != size);
1456         void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
1457         BOOST_ASSERT( 0 != sp);
1458         // placement new for internal coroutine
1459         impl_ = new ( sp) object_t(
1460                 boost::forward< coroutine_fn >( fn), attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc); 
1461         BOOST_ASSERT( impl_);
1462         impl_->pull();
1463     }
1464 # endif
1465     template< typename Fn >
1466     explicit pull_coroutine( BOOST_RV_REF( Fn) fn,
1467                              attributes const& attrs = attributes() ) :
1468         impl_( 0)
1469     {
1470         // create a stack-context
1471         stack_context stack_ctx;
1472         stack_allocator stack_alloc;
1473         // allocate the coroutine-stack
1474         stack_alloc.allocate( stack_ctx, attrs.size);
1475         BOOST_ASSERT( 0 != stack_ctx.sp);
1476         // typedef of internal coroutine-type
1477         typedef detail::pull_coroutine_object<
1478             push_coroutine< void >, void, Fn, stack_allocator
1479         >                                                       object_t;
1480         // reserve space on top of coroutine-stack for internal coroutine-type
1481         std::size_t size = stack_ctx.size - sizeof( object_t);
1482         BOOST_ASSERT( 0 != size);
1483         void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
1484         BOOST_ASSERT( 0 != sp);
1485         // placement new for internal coroutine
1486         impl_ = new ( sp) object_t(
1487                 boost::forward< Fn >( fn), attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc); 
1488         BOOST_ASSERT( impl_);
1489         impl_->pull();
1490     }
1491 
1492     template< typename Fn, typename StackAllocator >
1493     explicit pull_coroutine( BOOST_RV_REF( Fn) fn,
1494                              attributes const& attrs,
1495                              StackAllocator stack_alloc) :
1496         impl_( 0)
1497     {
1498         // create a stack-context
1499         stack_context stack_ctx;
1500         // allocate the coroutine-stack
1501         stack_alloc.allocate( stack_ctx, attrs.size);
1502         BOOST_ASSERT( 0 != stack_ctx.sp);
1503         // typedef of internal coroutine-type
1504         typedef detail::pull_coroutine_object<
1505             push_coroutine< void >, void, Fn, StackAllocator
1506         >                                                       object_t;
1507         // reserve space on top of coroutine-stack for internal coroutine-type
1508         std::size_t size = stack_ctx.size - sizeof( object_t);
1509         BOOST_ASSERT( 0 != size);
1510         void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
1511         BOOST_ASSERT( 0 != sp);
1512         // placement new for internal coroutine
1513         impl_ = new ( sp) object_t(
1514                 boost::forward< Fn >( fn), attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc); 
1515         BOOST_ASSERT( impl_);
1516         impl_->pull();
1517     }
1518 #else
1519     template< typename Fn >
1520     explicit pull_coroutine( Fn fn,
1521                              attributes const& attrs = attributes() ) :
1522         impl_( 0)
1523     {
1524         // create a stack-context
1525         stack_context stack_ctx;
1526         stack_allocator stack_alloc;
1527         // allocate the coroutine-stack
1528         stack_alloc.allocate( stack_ctx, attrs.size);
1529         BOOST_ASSERT( 0 != stack_ctx.sp);
1530         // typedef of internal coroutine-type
1531         typedef detail::pull_coroutine_object<
1532             push_coroutine< void >, void, Fn, stack_allocator
1533         >                                                       object_t;
1534         // reserve space on top of coroutine-stack for internal coroutine-type
1535         std::size_t size = stack_ctx.size - sizeof( object_t);
1536         BOOST_ASSERT( 0 != size);
1537         void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
1538         BOOST_ASSERT( 0 != sp);
1539         // placement new for internal coroutine
1540         impl_ = new ( sp) object_t(
1541                 fn, attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc); 
1542         BOOST_ASSERT( impl_);
1543         impl_->pull();
1544     }
1545 
1546     template< typename Fn, typename StackAllocator >
1547     explicit pull_coroutine( Fn fn,
1548                              attributes const& attrs,
1549                              StackAllocator stack_alloc) :
1550         impl_( 0)
1551     {
1552         // create a stack-context
1553         stack_context stack_ctx;
1554         // allocate the coroutine-stack
1555         stack_alloc.allocate( stack_ctx, attrs.size);
1556         BOOST_ASSERT( 0 != stack_ctx.sp);
1557         // typedef of internal coroutine-type
1558         typedef detail::pull_coroutine_object<
1559             push_coroutine< void >, void, Fn, StackAllocator
1560         >                                                       object_t;
1561         // reserve space on top of coroutine-stack for internal coroutine-type
1562         std::size_t size = stack_ctx.size - sizeof( object_t);
1563         BOOST_ASSERT( 0 != size);
1564         void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
1565         BOOST_ASSERT( 0 != sp);
1566         // placement new for internal coroutine
1567         impl_ = new ( sp) object_t(
1568                 fn, attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc); 
1569         BOOST_ASSERT( impl_);
1570         impl_->pull();
1571     }
1572 
1573     template< typename Fn >
1574     explicit pull_coroutine( BOOST_RV_REF( Fn) fn,
1575                              attributes const& attrs = attributes() ) :
1576         impl_( 0)
1577     {
1578         // create a stack-context
1579         stack_context stack_ctx;
1580         stack_allocator stack_alloc;
1581         // allocate the coroutine-stack
1582         stack_alloc.allocate( stack_ctx, attrs.size);
1583         BOOST_ASSERT( 0 != stack_ctx.sp);
1584         // typedef of internal coroutine-type
1585         typedef detail::pull_coroutine_object<
1586             push_coroutine< void >, void, Fn, stack_allocator
1587         >                                           object_t;
1588         // reserve space on top of coroutine-stack for internal coroutine-type
1589         std::size_t size = stack_ctx.size - sizeof( object_t);
1590         BOOST_ASSERT( 0 != size);
1591         void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
1592         BOOST_ASSERT( 0 != sp);
1593         // placement new for internal coroutine
1594         impl_ = new ( sp) object_t(
1595                 fn, attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc); 
1596         BOOST_ASSERT( impl_);
1597         impl_->pull();
1598     }
1599 
1600     template< typename Fn, typename StackAllocator >
1601     explicit pull_coroutine( BOOST_RV_REF( Fn) fn,
1602                              attributes const& attrs,
1603                              StackAllocator stack_alloc) :
1604         impl_( 0)
1605     {
1606         // create a stack-context
1607         stack_context stack_ctx;
1608         // allocate the coroutine-stack
1609         stack_alloc.allocate( stack_ctx, attrs.size);
1610         BOOST_ASSERT( 0 != stack_ctx.sp);
1611         // typedef of internal coroutine-type
1612         typedef detail::pull_coroutine_object<
1613             push_coroutine< void >, void, Fn, StackAllocator
1614         >                                           object_t;
1615         // reserve space on top of coroutine-stack for internal coroutine-type
1616         std::size_t size = stack_ctx.size - sizeof( object_t);
1617         BOOST_ASSERT( 0 != size);
1618         void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
1619         BOOST_ASSERT( 0 != sp);
1620         // placement new for internal coroutine
1621         impl_ = new ( sp) object_t(
1622                 fn, attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc); 
1623         BOOST_ASSERT( impl_);
1624         impl_->pull();
1625     }
1626 #endif
1627 
1628     ~pull_coroutine()
1629     {
1630         if ( 0 != impl_)
1631         {
1632             impl_->destroy();
1633             impl_ = 0;
1634         }
1635     }
1636 
1637     inline pull_coroutine( BOOST_RV_REF( pull_coroutine) other) BOOST_NOEXCEPT :
1638         impl_( 0)
1639     { swap( other); }
1640 
1641     inline pull_coroutine & operator=( BOOST_RV_REF( pull_coroutine) other) BOOST_NOEXCEPT
1642     {
1643         pull_coroutine tmp( boost::move( other) );
1644         swap( tmp);
1645         return * this;
1646     }
1647 
1648     BOOST_EXPLICIT_OPERATOR_BOOL();
1649 
1650     inline bool operator!() const BOOST_NOEXCEPT
1651     { return 0 == impl_ || impl_->is_complete(); }
1652 
1653     inline void swap( pull_coroutine & other) BOOST_NOEXCEPT
1654     { std::swap( impl_, other.impl_); }
1655 
1656     inline pull_coroutine & operator()()
1657     {
1658         BOOST_ASSERT( * this);
1659 
1660         impl_->pull();
1661         return * this;
1662     }
1663 
1664     struct iterator;
1665     struct const_iterator;
1666 };
1667 
1668 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
1669 # ifdef BOOST_MSVC
1670 template< typename Arg >
1671 push_coroutine< Arg >::push_coroutine( coroutine_fn fn,
1672                                        attributes const& attrs) :
1673     impl_( 0)
1674 {
1675     // create a stack-context
1676     stack_context stack_ctx;
1677     stack_allocator stack_alloc;
1678     // allocate the coroutine-stack
1679     stack_alloc.allocate( stack_ctx, attrs.size);
1680     BOOST_ASSERT( 0 != stack_ctx.sp);
1681     // typedef of internal coroutine-type
1682     typedef detail::push_coroutine_object<
1683         pull_coroutine< Arg >, Arg, coroutine_fn, stack_allocator
1684     >                                                            object_t;
1685     // reserve space on top of coroutine-stack for internal coroutine-type
1686     std::size_t size = stack_ctx.size - sizeof( object_t);
1687     BOOST_ASSERT( 0 != size);
1688     void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
1689     BOOST_ASSERT( 0 != sp);
1690     // placement new for internal coroutine
1691     impl_ = new ( sp) object_t(
1692             boost::forward< coroutine_fn >( fn), attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc); 
1693     BOOST_ASSERT( impl_);
1694 }
1695 
1696 template< typename Arg >
1697 template< typename StackAllocator >
1698 push_coroutine< Arg >::push_coroutine( coroutine_fn fn,
1699                                        attributes const& attrs,
1700                                        StackAllocator stack_alloc) :
1701     impl_( 0)
1702 {
1703     // create a stack-context
1704     stack_context stack_ctx;
1705     // allocate the coroutine-stack
1706     stack_alloc.allocate( stack_ctx, attrs.size);
1707     BOOST_ASSERT( 0 != stack_ctx.sp);
1708     // typedef of internal coroutine-type
1709     typedef detail::push_coroutine_object<
1710         pull_coroutine< Arg >, Arg, coroutine_fn, StackAllocator
1711     >                                                            object_t;
1712     // reserve space on top of coroutine-stack for internal coroutine-type
1713     std::size_t size = stack_ctx.size - sizeof( object_t);
1714     BOOST_ASSERT( 0 != size);
1715     void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
1716     BOOST_ASSERT( 0 != sp);
1717     // placement new for internal coroutine
1718     impl_ = new ( sp) object_t(
1719             boost::forward< coroutine_fn >( fn), attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc); 
1720     BOOST_ASSERT( impl_);
1721 }
1722 
1723 template< typename Arg >
1724 push_coroutine< Arg & >::push_coroutine( coroutine_fn fn,
1725                                          attributes const& attrs) :
1726     impl_( 0)
1727 {
1728     // create a stack-context
1729     stack_context stack_ctx;
1730     stack_allocator stack_alloc;
1731     // allocate the coroutine-stack
1732     stack_alloc.allocate( stack_ctx, attrs.size);
1733     BOOST_ASSERT( 0 != stack_ctx.sp);
1734     // typedef of internal coroutine-type
1735     typedef detail::push_coroutine_object<
1736         pull_coroutine< Arg & >, Arg &, coroutine_fn, stack_allocator
1737     >                                                            object_t;
1738     // reserve space on top of coroutine-stack for internal coroutine-type
1739     std::size_t size = stack_ctx.size - sizeof( object_t);
1740     BOOST_ASSERT( 0 != size);
1741     void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
1742     BOOST_ASSERT( 0 != sp);
1743     // placement new for internal coroutine
1744     impl_ = new ( sp) object_t(
1745             boost::forward< coroutine_fn >( fn), attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc); 
1746     BOOST_ASSERT( impl_);
1747 }
1748 
1749 template< typename Arg >
1750 template< typename StackAllocator >
1751 push_coroutine< Arg & >::push_coroutine( coroutine_fn fn,
1752                                          attributes const& attrs,
1753                                          StackAllocator stack_alloc) :
1754     impl_( 0)
1755 {
1756     // create a stack-context
1757     stack_context stack_ctx;
1758     // allocate the coroutine-stack
1759     stack_alloc.allocate( stack_ctx, attrs.size);
1760     BOOST_ASSERT( 0 != stack_ctx.sp);
1761     // typedef of internal coroutine-type
1762     typedef detail::push_coroutine_object<
1763         pull_coroutine< Arg & >, Arg &, coroutine_fn, StackAllocator
1764     >                                                            object_t;
1765     // reserve space on top of coroutine-stack for internal coroutine-type
1766     std::size_t size = stack_ctx.size - sizeof( object_t);
1767     BOOST_ASSERT( 0 != size);
1768     void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
1769     BOOST_ASSERT( 0 != sp);
1770     // placement new for internal coroutine
1771     impl_ = new ( sp) object_t(
1772             boost::forward< coroutine_fn >( fn), attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc); 
1773     BOOST_ASSERT( impl_);
1774 }
1775 
1776 inline push_coroutine< void >::push_coroutine( coroutine_fn fn,
1777                                                attributes const& attrs) :
1778     impl_( 0)
1779 {
1780     // create a stack-context
1781     stack_context stack_ctx;
1782     stack_allocator stack_alloc;
1783     // allocate the coroutine-stack
1784     stack_alloc.allocate( stack_ctx, attrs.size);
1785     BOOST_ASSERT( 0 != stack_ctx.sp);
1786     // typedef of internal coroutine-type
1787     typedef detail::push_coroutine_object<
1788         pull_coroutine< void >, void, coroutine_fn, stack_allocator
1789     >                                                               object_t;
1790     // reserve space on top of coroutine-stack for internal coroutine-type
1791     std::size_t size = stack_ctx.size - sizeof( object_t);
1792     BOOST_ASSERT( 0 != size);
1793     void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
1794     BOOST_ASSERT( 0 != sp);
1795     // placement new for internal coroutine
1796     impl_ = new ( sp) object_t(
1797             boost::forward< coroutine_fn >( fn), attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc); 
1798     BOOST_ASSERT( impl_);
1799 }
1800 
1801 template< typename StackAllocator >
1802 push_coroutine< void >::push_coroutine( coroutine_fn fn,
1803                                         attributes const& attrs,
1804                                         StackAllocator stack_alloc) :
1805     impl_( 0)
1806 {
1807     // create a stack-context
1808     stack_context stack_ctx;
1809     // allocate the coroutine-stack
1810     stack_alloc.allocate( stack_ctx, attrs.size);
1811     BOOST_ASSERT( 0 != stack_ctx.sp);
1812     // typedef of internal coroutine-type
1813     typedef detail::push_coroutine_object<
1814         pull_coroutine< void >, void, coroutine_fn, StackAllocator
1815     >                                                               object_t;
1816     // reserve space on top of coroutine-stack for internal coroutine-type
1817     std::size_t size = stack_ctx.size - sizeof( object_t);
1818     BOOST_ASSERT( 0 != size);
1819     void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
1820     BOOST_ASSERT( 0 != sp);
1821     // placement new for internal coroutine
1822     impl_ = new ( sp) object_t(
1823             boost::forward< coroutine_fn >( fn), attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc); 
1824     BOOST_ASSERT( impl_);
1825 }
1826 # endif
1827 template< typename Arg >
1828 template< typename Fn >
1829 push_coroutine< Arg >::push_coroutine( BOOST_RV_REF( Fn) fn,
1830                                        attributes const& attrs) :
1831     impl_( 0)
1832 {
1833     // create a stack-context
1834     stack_context stack_ctx;
1835     stack_allocator stack_alloc;
1836     // allocate the coroutine-stack
1837     stack_alloc.allocate( stack_ctx, attrs.size);
1838     BOOST_ASSERT( 0 != stack_ctx.sp);
1839     // typedef of internal coroutine-type
1840     typedef detail::push_coroutine_object<
1841         pull_coroutine< Arg >, Arg, Fn, stack_allocator
1842     >                                                    object_t;
1843     // reserve space on top of coroutine-stack for internal coroutine-type
1844     std::size_t size = stack_ctx.size - sizeof( object_t);
1845     BOOST_ASSERT( 0 != size);
1846     void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
1847     BOOST_ASSERT( 0 != sp);
1848     // placement new for internal coroutine
1849     impl_ = new ( sp) object_t(
1850             boost::forward< Fn >( fn), attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc); 
1851     BOOST_ASSERT( impl_);
1852 }
1853 
1854 template< typename Arg >
1855 template< typename Fn, typename StackAllocator >
1856 push_coroutine< Arg >::push_coroutine( BOOST_RV_REF( Fn) fn,
1857                                        attributes const& attrs,
1858                                        StackAllocator stack_alloc) :
1859     impl_( 0)
1860 {
1861     // create a stack-context
1862     stack_context stack_ctx;
1863     // allocate the coroutine-stack
1864     stack_alloc.allocate( stack_ctx, attrs.size);
1865     BOOST_ASSERT( 0 != stack_ctx.sp);
1866     // typedef of internal coroutine-type
1867     typedef detail::push_coroutine_object<
1868         pull_coroutine< Arg >, Arg, Fn, StackAllocator
1869     >                                                    object_t;
1870     // reserve space on top of coroutine-stack for internal coroutine-type
1871     std::size_t size = stack_ctx.size - sizeof( object_t);
1872     BOOST_ASSERT( 0 != size);
1873     void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
1874     BOOST_ASSERT( 0 != sp);
1875     // placement new for internal coroutine
1876     impl_ = new ( sp) object_t(
1877             boost::forward< Fn >( fn), attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc); 
1878     BOOST_ASSERT( impl_);
1879 }
1880 
1881 template< typename Arg >
1882 template< typename Fn >
1883 push_coroutine< Arg & >::push_coroutine( BOOST_RV_REF( Fn) fn,
1884                                          attributes const& attrs) :
1885     impl_( 0)
1886 {
1887     // create a stack-context
1888     stack_context stack_ctx;
1889     stack_allocator stack_alloc;
1890     // allocate the coroutine-stack
1891     stack_alloc.allocate( stack_ctx, attrs.size);
1892     BOOST_ASSERT( 0 != stack_ctx.sp);
1893     // typedef of internal coroutine-type
1894     typedef detail::push_coroutine_object<
1895         pull_coroutine< Arg & >, Arg &, Fn, stack_allocator
1896     >                                                            object_t;
1897     // reserve space on top of coroutine-stack for internal coroutine-type
1898     std::size_t size = stack_ctx.size - sizeof( object_t);
1899     BOOST_ASSERT( 0 != size);
1900     void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
1901     BOOST_ASSERT( 0 != sp);
1902     // placement new for internal coroutine
1903     impl_ = new ( sp) object_t(
1904             boost::forward< Fn >( fn), attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc); 
1905     BOOST_ASSERT( impl_);
1906 }
1907 
1908 template< typename Arg >
1909 template< typename Fn, typename StackAllocator >
1910 push_coroutine< Arg & >::push_coroutine( BOOST_RV_REF( Fn) fn,
1911                                          attributes const& attrs,
1912                                          StackAllocator stack_alloc) :
1913     impl_( 0)
1914 {
1915     // create a stack-context
1916     stack_context stack_ctx;
1917     // allocate the coroutine-stack
1918     stack_alloc.allocate( stack_ctx, attrs.size);
1919     BOOST_ASSERT( 0 != stack_ctx.sp);
1920     // typedef of internal coroutine-type
1921     typedef detail::push_coroutine_object<
1922         pull_coroutine< Arg & >, Arg &, Fn, StackAllocator
1923     >                                                            object_t;
1924     // reserve space on top of coroutine-stack for internal coroutine-type
1925     std::size_t size = stack_ctx.size - sizeof( object_t);
1926     BOOST_ASSERT( 0 != size);
1927     void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
1928     BOOST_ASSERT( 0 != sp);
1929     // placement new for internal coroutine
1930     impl_ = new ( sp) object_t(
1931             boost::forward< Fn >( fn), attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc); 
1932     BOOST_ASSERT( impl_);
1933 }
1934 
1935 template< typename Fn >
1936 push_coroutine< void >::push_coroutine( BOOST_RV_REF( Fn) fn,
1937                                         attributes const& attrs) :
1938     impl_( 0)
1939 {
1940     // create a stack-context
1941     stack_context stack_ctx;
1942     stack_allocator stack_alloc;
1943     // allocate the coroutine-stack
1944     stack_alloc.allocate( stack_ctx, attrs.size);
1945     BOOST_ASSERT( 0 != stack_ctx.sp);
1946     // typedef of internal coroutine-type
1947     typedef detail::push_coroutine_object<
1948         pull_coroutine< void >, void, Fn, stack_allocator
1949     >                                                            object_t;
1950     // reserve space on top of coroutine-stack for internal coroutine-type
1951     std::size_t size = stack_ctx.size - sizeof( object_t);
1952     BOOST_ASSERT( 0 != size);
1953     void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
1954     BOOST_ASSERT( 0 != sp);
1955     // placement new for internal coroutine
1956     impl_ = new ( sp) object_t(
1957             boost::forward< Fn >( fn), attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc); 
1958     BOOST_ASSERT( impl_);
1959 }
1960 
1961 template< typename Fn, typename StackAllocator >
1962 push_coroutine< void >::push_coroutine( BOOST_RV_REF( Fn) fn,
1963                                         attributes const& attrs,
1964                                         StackAllocator stack_alloc) :
1965     impl_( 0)
1966 {
1967     // create a stack-context
1968     stack_context stack_ctx;
1969     // allocate the coroutine-stack
1970     stack_alloc.allocate( stack_ctx, attrs.size);
1971     BOOST_ASSERT( 0 != stack_ctx.sp);
1972     // typedef of internal coroutine-type
1973     typedef detail::push_coroutine_object<
1974         pull_coroutine< void >, void, Fn, StackAllocator
1975     >                                                            object_t;
1976     // reserve space on top of coroutine-stack for internal coroutine-type
1977     std::size_t size = stack_ctx.size - sizeof( object_t);
1978     BOOST_ASSERT( 0 != size);
1979     void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
1980     BOOST_ASSERT( 0 != sp);
1981     // placement new for internal coroutine
1982     impl_ = new ( sp) object_t(
1983             boost::forward< Fn >( fn), attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc); 
1984     BOOST_ASSERT( impl_);
1985 }
1986 #else
1987 template< typename Arg >
1988 template< typename Fn >
1989 push_coroutine< Arg >::push_coroutine( Fn fn,
1990                                        attributes const& attrs) :
1991     impl_( 0)
1992 {
1993     // create a stack-context
1994     stack_context stack_ctx;
1995     stack_allocator stack_alloc;
1996     // allocate the coroutine-stack
1997     stack_alloc.allocate( stack_ctx, attrs.size);
1998     BOOST_ASSERT( 0 != stack_ctx.sp);
1999     // typedef of internal coroutine-type
2000     typedef detail::push_coroutine_object<
2001         pull_coroutine< Arg >, Arg, Fn, stack_allocator
2002     >                                                    object_t;
2003     // reserve space on top of coroutine-stack for internal coroutine-type
2004     std::size_t size = stack_ctx.size - sizeof( object_t);
2005     BOOST_ASSERT( 0 != size);
2006     void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
2007     BOOST_ASSERT( 0 != sp);
2008     // placement new for internal coroutine
2009     impl_ = new ( sp) object_t(
2010             fn, attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc); 
2011     BOOST_ASSERT( impl_);
2012 }
2013 
2014 template< typename Arg >
2015 template< typename Fn, typename StackAllocator >
2016 push_coroutine< Arg >::push_coroutine( Fn fn,
2017                                        attributes const& attrs,
2018                                        StackAllocator stack_alloc) :
2019     impl_( 0)
2020 {
2021     // create a stack-context
2022     stack_context stack_ctx;
2023     // allocate the coroutine-stack
2024     stack_alloc.allocate( stack_ctx, attrs.size);
2025     BOOST_ASSERT( 0 != stack_ctx.sp);
2026     // typedef of internal coroutine-type
2027     typedef detail::push_coroutine_object<
2028         pull_coroutine< Arg >, Arg, Fn, StackAllocator
2029     >                                                    object_t;
2030     // reserve space on top of coroutine-stack for internal coroutine-type
2031     std::size_t size = stack_ctx.size - sizeof( object_t);
2032     BOOST_ASSERT( 0 != size);
2033     void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
2034     BOOST_ASSERT( 0 != sp);
2035     // placement new for internal coroutine
2036     impl_ = new ( sp) object_t(
2037             fn, attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc); 
2038     BOOST_ASSERT( impl_);
2039 }
2040 
2041 template< typename Arg >
2042 template< typename Fn >
2043 push_coroutine< Arg & >::push_coroutine( Fn fn,
2044                                          attributes const& attrs) :
2045     impl_( 0)
2046 {
2047     // create a stack-context
2048     stack_context stack_ctx;
2049     stack_allocator stack_alloc;
2050     // allocate the coroutine-stack
2051     stack_alloc.allocate( stack_ctx, attrs.size);
2052     BOOST_ASSERT( 0 != stack_ctx.sp);
2053     // typedef of internal coroutine-type
2054     typedef detail::push_coroutine_object<
2055         pull_coroutine< Arg & >, Arg &, Fn, stack_allocator
2056     >                                                            object_t;
2057     // reserve space on top of coroutine-stack for internal coroutine-type
2058     std::size_t size = stack_ctx.size - sizeof( object_t);
2059     BOOST_ASSERT( 0 != size);
2060     void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
2061     BOOST_ASSERT( 0 != sp);
2062     // placement new for internal coroutine
2063     impl_ = new ( sp) object_t(
2064             fn, attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc); 
2065     BOOST_ASSERT( impl_);
2066 }
2067 
2068 template< typename Arg >
2069 template< typename Fn, typename StackAllocator >
2070 push_coroutine< Arg & >::push_coroutine( Fn fn,
2071                                          attributes const& attrs,
2072                                          StackAllocator stack_alloc) :
2073     impl_( 0)
2074 {
2075     // create a stack-context
2076     stack_context stack_ctx;
2077     // allocate the coroutine-stack
2078     stack_alloc.allocate( stack_ctx, attrs.size);
2079     BOOST_ASSERT( 0 != stack_ctx.sp);
2080     // typedef of internal coroutine-type
2081     typedef detail::push_coroutine_object<
2082         pull_coroutine< Arg & >, Arg &, Fn, StackAllocator
2083     >                                                            object_t;
2084     // reserve space on top of coroutine-stack for internal coroutine-type
2085     std::size_t size = stack_ctx.size - sizeof( object_t);
2086     BOOST_ASSERT( 0 != size);
2087     void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
2088     BOOST_ASSERT( 0 != sp);
2089     // placement new for internal coroutine
2090     impl_ = new ( sp) object_t(
2091             fn, attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc); 
2092     BOOST_ASSERT( impl_);
2093 }
2094 
2095 template< typename Fn >
2096 push_coroutine< void >::push_coroutine( Fn fn,
2097                                         attributes const& attrs) :
2098     impl_( 0)
2099 {
2100     // create a stack-context
2101     stack_context stack_ctx;
2102     stack_allocator stack_alloc;
2103     // allocate the coroutine-stack
2104     stack_alloc.allocate( stack_ctx, attrs.size);
2105     BOOST_ASSERT( 0 != stack_ctx.sp);
2106     // typedef of internal coroutine-type
2107     typedef detail::push_coroutine_object<
2108         pull_coroutine< void >, void, Fn, stack_allocator
2109     >                                                            object_t;
2110     // reserve space on top of coroutine-stack for internal coroutine-type
2111     std::size_t size = stack_ctx.size - sizeof( object_t);
2112     BOOST_ASSERT( 0 != size);
2113     void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
2114     BOOST_ASSERT( 0 != sp);
2115     // placement new for internal coroutine
2116     impl_ = new ( sp) object_t(
2117             fn, attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc); 
2118     BOOST_ASSERT( impl_);
2119 }
2120 
2121 template< typename Fn, typename StackAllocator >
2122 push_coroutine< void >::push_coroutine( Fn fn,
2123                                         attributes const& attrs,
2124                                         StackAllocator stack_alloc) :
2125     impl_( 0)
2126 {
2127     // create a stack-context
2128     stack_context stack_ctx;
2129     // allocate the coroutine-stack
2130     stack_alloc.allocate( stack_ctx, attrs.size);
2131     BOOST_ASSERT( 0 != stack_ctx.sp);
2132     // typedef of internal coroutine-type
2133     typedef detail::push_coroutine_object<
2134         pull_coroutine< void >, void, Fn, StackAllocator
2135     >                                                            object_t;
2136     // reserve space on top of coroutine-stack for internal coroutine-type
2137     std::size_t size = stack_ctx.size - sizeof( object_t);
2138     BOOST_ASSERT( 0 != size);
2139     void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
2140     BOOST_ASSERT( 0 != sp);
2141     // placement new for internal coroutine
2142     impl_ = new ( sp) object_t(
2143             fn, attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc); 
2144     BOOST_ASSERT( impl_);
2145 }
2146 
2147 template< typename Arg >
2148 template< typename Fn >
2149 push_coroutine< Arg >::push_coroutine( BOOST_RV_REF( Fn) fn,
2150                                        attributes const& attrs) :
2151     impl_( 0)
2152 {
2153     // create a stack-context
2154     stack_context stack_ctx;
2155     stack_allocator stack_alloc;
2156     // allocate the coroutine-stack
2157     stack_alloc.allocate( stack_ctx, attrs.size);
2158     BOOST_ASSERT( 0 != stack_ctx.sp);
2159     // typedef of internal coroutine-type
2160     typedef detail::push_coroutine_object<
2161         pull_coroutine< Arg >, Arg, Fn, stack_allocator
2162     >                                                    object_t;
2163     // reserve space on top of coroutine-stack for internal coroutine-type
2164     std::size_t size = stack_ctx.size - sizeof( object_t);
2165     BOOST_ASSERT( 0 != size);
2166     void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
2167     BOOST_ASSERT( 0 != sp);
2168     // placement new for internal coroutine
2169     impl_ = new ( sp) object_t(
2170             fn, attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc); 
2171     BOOST_ASSERT( impl_);
2172 }
2173 
2174 template< typename Arg >
2175 template< typename Fn, typename StackAllocator >
2176 push_coroutine< Arg >::push_coroutine( BOOST_RV_REF( Fn) fn,
2177                                        attributes const& attrs,
2178                                        StackAllocator stack_alloc) :
2179     impl_( 0)
2180 {
2181     // create a stack-context
2182     stack_context stack_ctx;
2183     // allocate the coroutine-stack
2184     stack_alloc.allocate( stack_ctx, attrs.size);
2185     BOOST_ASSERT( 0 != stack_ctx.sp);
2186     // typedef of internal coroutine-type
2187     typedef detail::push_coroutine_object<
2188         pull_coroutine< Arg >, Arg, Fn, StackAllocator
2189     >                                                    object_t;
2190     // reserve space on top of coroutine-stack for internal coroutine-type
2191     std::size_t size = stack_ctx.size - sizeof( object_t);
2192     BOOST_ASSERT( 0 != size);
2193     void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
2194     BOOST_ASSERT( 0 != sp);
2195     // placement new for internal coroutine
2196     impl_ = new ( sp) object_t(
2197             fn, attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc); 
2198     BOOST_ASSERT( impl_);
2199 }
2200 
2201 template< typename Arg >
2202 template< typename Fn >
2203 push_coroutine< Arg & >::push_coroutine( BOOST_RV_REF( Fn) fn,
2204                                          attributes const& attrs) :
2205     impl_( 0)
2206 {
2207     // create a stack-context
2208     stack_context stack_ctx;
2209     stack_allocator stack_alloc;
2210     // allocate the coroutine-stack
2211     stack_alloc.allocate( stack_ctx, attrs.size);
2212     BOOST_ASSERT( 0 != stack_ctx.sp);
2213     // typedef of internal coroutine-type
2214     typedef detail::push_coroutine_object<
2215         pull_coroutine< Arg & >, Arg &, Fn, stack_allocator
2216     >                                                            object_t;
2217     // reserve space on top of coroutine-stack for internal coroutine-type
2218     std::size_t size = stack_ctx.size - sizeof( object_t);
2219     BOOST_ASSERT( 0 != size);
2220     void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
2221     BOOST_ASSERT( 0 != sp);
2222     // placement new for internal coroutine
2223     impl_ = new ( sp) object_t(
2224             fn, attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc); 
2225     BOOST_ASSERT( impl_);
2226 }
2227 
2228 template< typename Arg >
2229 template< typename Fn, typename StackAllocator >
2230 push_coroutine< Arg & >::push_coroutine( BOOST_RV_REF( Fn) fn,
2231                                          attributes const& attrs,
2232                                          StackAllocator stack_alloc) :
2233     impl_( 0)
2234 {
2235     // create a stack-context
2236     stack_context stack_ctx;
2237     // allocate the coroutine-stack
2238     stack_alloc.allocate( stack_ctx, attrs.size);
2239     BOOST_ASSERT( 0 != stack_ctx.sp);
2240     // typedef of internal coroutine-type
2241     typedef detail::push_coroutine_object<
2242         pull_coroutine< Arg & >, Arg &, Fn, StackAllocator
2243     >                                                            object_t;
2244     // reserve space on top of coroutine-stack for internal coroutine-type
2245     std::size_t size = stack_ctx.size - sizeof( object_t);
2246     BOOST_ASSERT( 0 != size);
2247     void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
2248     BOOST_ASSERT( 0 != sp);
2249     // placement new for internal coroutine
2250     impl_ = new ( sp) object_t(
2251             fn, attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc); 
2252     BOOST_ASSERT( impl_);
2253 }
2254 
2255 template< typename Fn >
2256 push_coroutine< void >::push_coroutine( BOOST_RV_REF( Fn) fn,
2257                                         attributes const& attrs) :
2258     impl_( 0)
2259 {
2260     // create a stack-context
2261     stack_context stack_ctx;
2262     stack_allocator stack_alloc;
2263     // allocate the coroutine-stack
2264     stack_alloc.allocate( stack_ctx, attrs.size);
2265     BOOST_ASSERT( 0 != stack_ctx.sp);
2266     // typedef of internal coroutine-type
2267     typedef detail::push_coroutine_object<
2268         pull_coroutine< void >, void, Fn, stack_allocator
2269     >                                                            object_t;
2270     // reserve space on top of coroutine-stack for internal coroutine-type
2271     std::size_t size = stack_ctx.size - sizeof( object_t);
2272     BOOST_ASSERT( 0 != size);
2273     void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
2274     BOOST_ASSERT( 0 != sp);
2275     // placement new for internal coroutine
2276     impl_ = new ( sp) object_t(
2277             fn, attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc); 
2278     BOOST_ASSERT( impl_);
2279 }
2280 
2281 template< typename Fn, typename StackAllocator >
2282 push_coroutine< void >::push_coroutine( BOOST_RV_REF( Fn) fn,
2283                                         attributes const& attrs,
2284                                         StackAllocator stack_alloc) :
2285     impl_( 0)
2286 {
2287     // create a stack-context
2288     stack_context stack_ctx;
2289     // allocate the coroutine-stack
2290     stack_alloc.allocate( stack_ctx, attrs.size);
2291     BOOST_ASSERT( 0 != stack_ctx.sp);
2292     // typedef of internal coroutine-type
2293     typedef detail::push_coroutine_object<
2294         pull_coroutine< void >, void, Fn, StackAllocator
2295     >                                                            object_t;
2296     // reserve space on top of coroutine-stack for internal coroutine-type
2297     std::size_t size = stack_ctx.size - sizeof( object_t);
2298     BOOST_ASSERT( 0 != size);
2299     void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
2300     BOOST_ASSERT( 0 != sp);
2301     // placement new for internal coroutine
2302     impl_ = new ( sp) object_t(
2303             fn, attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc); 
2304     BOOST_ASSERT( impl_);
2305 }
2306 #endif
2307 
2308 template< typename R >
2309 void swap( pull_coroutine< R > & l, pull_coroutine< R > & r) BOOST_NOEXCEPT
2310 { l.swap( r); }
2311 
2312 template< typename Arg >
2313 void swap( push_coroutine< Arg > & l, push_coroutine< Arg > & r) BOOST_NOEXCEPT
2314 { l.swap( r); }
2315 
2316 template< typename R >
2317 typename pull_coroutine< R >::iterator
2318 range_begin( pull_coroutine< R > & c)
2319 { return typename pull_coroutine< R >::iterator( & c); }
2320 
2321 template< typename R >
2322 typename pull_coroutine< R >::const_iterator
2323 range_begin( pull_coroutine< R > const& c)
2324 { return typename pull_coroutine< R >::const_iterator( & c); }
2325 
2326 template< typename R >
2327 typename pull_coroutine< R >::iterator
2328 range_end( pull_coroutine< R > &)
2329 { return typename pull_coroutine< R >::iterator(); }
2330 
2331 template< typename R >
2332 typename pull_coroutine< R >::const_iterator
2333 range_end( pull_coroutine< R > const&)
2334 { return typename pull_coroutine< R >::const_iterator(); }
2335 
2336 template< typename Arg >
2337 typename push_coroutine< Arg >::iterator
2338 range_begin( push_coroutine< Arg > & c)
2339 { return typename push_coroutine< Arg >::iterator( & c); }
2340 
2341 template< typename Arg >
2342 typename push_coroutine< Arg >::iterator
2343 range_end( push_coroutine< Arg > &)
2344 { return typename push_coroutine< Arg >::iterator(); }
2345 
2346 template< typename T >
2347 struct asymmetric_coroutine
2348 {
2349     typedef push_coroutine< T > push_type;
2350     typedef pull_coroutine< T > pull_type;
2351 };
2352 
2353 // deprecated
2354 template< typename T >
2355 struct coroutine
2356 {
2357     typedef push_coroutine< T > push_type;
2358     typedef pull_coroutine< T > pull_type;
2359 };
2360 
2361 template< typename R >
2362 typename pull_coroutine< R >::iterator
2363 begin( pull_coroutine< R > & c)
2364 { return coroutines::range_begin( c); }
2365 
2366 template< typename R >
2367 typename pull_coroutine< R >::const_iterator
2368 begin( pull_coroutine< R > const& c)
2369 { return coroutines::range_begin( c); }
2370 
2371 template< typename R >
2372 typename pull_coroutine< R >::iterator
2373 end( pull_coroutine< R > & c)
2374 { return coroutines::range_end( c); }
2375 
2376 template< typename R >
2377 typename pull_coroutine< R >::const_iterator
2378 end( pull_coroutine< R > const& c)
2379 { return coroutines::range_end( c); }
2380 
2381 template< typename R >
2382 typename push_coroutine< R >::iterator
2383 begin( push_coroutine< R > & c)
2384 { return coroutines::range_begin( c); }
2385 
2386 template< typename R >
2387 typename push_coroutine< R >::iterator
2388 end( push_coroutine< R > & c)
2389 { return coroutines::range_end( c); }
2390 
2391 }
2392 
2393 // forward declaration of Boost.Range traits to break dependency on it
2394 template<typename C, typename Enabler>
2395 struct range_mutable_iterator;
2396 
2397 template<typename C, typename Enabler>
2398 struct range_const_iterator;
2399 
2400 template< typename Arg >
2401 struct range_mutable_iterator< coroutines::push_coroutine< Arg >, void >
2402 { typedef typename coroutines::push_coroutine< Arg >::iterator type; };
2403 
2404 template< typename R >
2405 struct range_mutable_iterator< coroutines::pull_coroutine< R >, void >
2406 { typedef typename coroutines::pull_coroutine< R >::iterator type; };
2407 
2408 }
2409 
2410 #ifdef BOOST_HAS_ABI_HEADERS
2411 #  include BOOST_ABI_SUFFIX
2412 #endif
2413 
2414 #endif // BOOST_COROUTINES_ASYMMETRIC_COROUTINE_H