File indexing completed on 2025-12-16 09:45:10
0001
0002
0003
0004
0005
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
0477 stack_context stack_ctx;
0478 stack_allocator stack_alloc;
0479
0480 stack_alloc.allocate( stack_ctx, attrs.size);
0481 BOOST_ASSERT( 0 != stack_ctx.sp);
0482
0483 typedef detail::pull_coroutine_object<
0484 push_coroutine< R >, R, coroutine_fn, stack_allocator
0485 > object_t;
0486
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
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
0505 stack_context stack_ctx;
0506
0507 stack_alloc.allocate( stack_ctx, attrs.size);
0508 BOOST_ASSERT( 0 != stack_ctx.sp);
0509
0510 typedef detail::pull_coroutine_object<
0511 push_coroutine< R >, R, coroutine_fn, StackAllocator
0512 > object_t;
0513
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
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
0531 stack_context stack_ctx;
0532 stack_allocator stack_alloc;
0533
0534 stack_alloc.allocate( stack_ctx, attrs.size);
0535 BOOST_ASSERT( 0 != stack_ctx.sp);
0536
0537 typedef detail::pull_coroutine_object<
0538 push_coroutine< R >, R, Fn, stack_allocator
0539 > object_t;
0540
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
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
0559 stack_context stack_ctx;
0560
0561 stack_alloc.allocate( stack_ctx, attrs.size);
0562 BOOST_ASSERT( 0 != stack_ctx.sp);
0563
0564 typedef detail::pull_coroutine_object<
0565 push_coroutine< R >, R, Fn, StackAllocator
0566 > object_t;
0567
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
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
0585 stack_context stack_ctx;
0586 stack_allocator stack_alloc;
0587
0588 stack_alloc.allocate( stack_ctx, attrs.size);
0589 BOOST_ASSERT( 0 != stack_ctx.sp);
0590
0591 typedef detail::pull_coroutine_object<
0592 push_coroutine< R >, R, Fn, stack_allocator
0593 > object_t;
0594
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
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
0613 stack_context stack_ctx;
0614
0615 stack_alloc.allocate( stack_ctx, attrs.size);
0616 BOOST_ASSERT( 0 != stack_ctx.sp);
0617
0618 typedef detail::pull_coroutine_object<
0619 push_coroutine< R >, R, Fn, StackAllocator
0620 > object_t;
0621
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
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
0639 stack_context stack_ctx;
0640 stack_allocator stack_alloc;
0641
0642 stack_alloc.allocate( stack_ctx, attrs.size);
0643 BOOST_ASSERT( 0 != stack_ctx.sp);
0644
0645 typedef detail::pull_coroutine_object<
0646 push_coroutine< R >, R, Fn, stack_allocator
0647 > object_t;
0648
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
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
0667 stack_context stack_ctx;
0668
0669 stack_alloc.allocate( stack_ctx, attrs.size);
0670 BOOST_ASSERT( 0 != stack_ctx.sp);
0671
0672 typedef detail::pull_coroutine_object<
0673 push_coroutine< R >, R, Fn, StackAllocator
0674 > object_t;
0675
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
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
0949 stack_context stack_ctx;
0950 stack_allocator stack_alloc;
0951
0952 stack_alloc.allocate( stack_ctx, attrs.size);
0953 BOOST_ASSERT( 0 != stack_ctx.sp);
0954
0955 typedef detail::pull_coroutine_object<
0956 push_coroutine< R & >, R &, coroutine_fn, stack_allocator
0957 > object_t;
0958
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
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
0977 stack_context stack_ctx;
0978
0979 stack_alloc.allocate( stack_ctx, attrs.size);
0980 BOOST_ASSERT( 0 != stack_ctx.sp);
0981
0982 typedef detail::pull_coroutine_object<
0983 push_coroutine< R & >, R &, coroutine_fn, StackAllocator
0984 > object_t;
0985
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
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
1003 stack_context stack_ctx;
1004 stack_allocator stack_alloc;
1005
1006 stack_alloc.allocate( stack_ctx, attrs.size);
1007 BOOST_ASSERT( 0 != stack_ctx.sp);
1008
1009 typedef detail::pull_coroutine_object<
1010 push_coroutine< R & >, R &, Fn, stack_allocator
1011 > object_t;
1012
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
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
1031 stack_context stack_ctx;
1032
1033 stack_alloc.allocate( stack_ctx, attrs.size);
1034 BOOST_ASSERT( 0 != stack_ctx.sp);
1035
1036 typedef detail::pull_coroutine_object<
1037 push_coroutine< R & >, R &, Fn, StackAllocator
1038 > object_t;
1039
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
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
1057 stack_context stack_ctx;
1058 stack_allocator stack_alloc;
1059
1060 stack_alloc.allocate( stack_ctx, attrs.size);
1061 BOOST_ASSERT( 0 != stack_ctx.sp);
1062
1063 typedef detail::pull_coroutine_object<
1064 push_coroutine< R & >, R &, Fn, stack_allocator
1065 > object_t;
1066
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
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
1085 stack_context stack_ctx;
1086
1087 stack_alloc.allocate( stack_ctx, attrs.size);
1088 BOOST_ASSERT( 0 != stack_ctx.sp);
1089
1090 typedef detail::pull_coroutine_object<
1091 push_coroutine< R & >, R &, Fn, StackAllocator
1092 > object_t;
1093
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
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
1111 stack_context stack_ctx;
1112 stack_allocator stack_alloc;
1113
1114 stack_alloc.allocate( stack_ctx, attrs.size);
1115 BOOST_ASSERT( 0 != stack_ctx.sp);
1116
1117 typedef detail::pull_coroutine_object<
1118 push_coroutine< R & >, R &, Fn, stack_allocator
1119 > object_t;
1120
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
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
1139 stack_context stack_ctx;
1140
1141 stack_alloc.allocate( stack_ctx, attrs.size);
1142 BOOST_ASSERT( 0 != stack_ctx.sp);
1143
1144 typedef detail::pull_coroutine_object<
1145 push_coroutine< R & >, R &, Fn, StackAllocator
1146 > object_t;
1147
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
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
1417 stack_context stack_ctx;
1418 stack_allocator stack_alloc;
1419
1420 stack_alloc.allocate( stack_ctx, attrs.size);
1421 BOOST_ASSERT( 0 != stack_ctx.sp);
1422
1423 typedef detail::pull_coroutine_object<
1424 push_coroutine< void >, void, coroutine_fn, stack_allocator
1425 > object_t;
1426
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
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
1445 stack_context stack_ctx;
1446
1447 stack_alloc.allocate( stack_ctx, attrs.size);
1448 BOOST_ASSERT( 0 != stack_ctx.sp);
1449
1450 typedef detail::pull_coroutine_object<
1451 push_coroutine< void >, void, coroutine_fn, StackAllocator
1452 > object_t;
1453
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
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
1471 stack_context stack_ctx;
1472 stack_allocator stack_alloc;
1473
1474 stack_alloc.allocate( stack_ctx, attrs.size);
1475 BOOST_ASSERT( 0 != stack_ctx.sp);
1476
1477 typedef detail::pull_coroutine_object<
1478 push_coroutine< void >, void, Fn, stack_allocator
1479 > object_t;
1480
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
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
1499 stack_context stack_ctx;
1500
1501 stack_alloc.allocate( stack_ctx, attrs.size);
1502 BOOST_ASSERT( 0 != stack_ctx.sp);
1503
1504 typedef detail::pull_coroutine_object<
1505 push_coroutine< void >, void, Fn, StackAllocator
1506 > object_t;
1507
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
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
1525 stack_context stack_ctx;
1526 stack_allocator stack_alloc;
1527
1528 stack_alloc.allocate( stack_ctx, attrs.size);
1529 BOOST_ASSERT( 0 != stack_ctx.sp);
1530
1531 typedef detail::pull_coroutine_object<
1532 push_coroutine< void >, void, Fn, stack_allocator
1533 > object_t;
1534
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
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
1553 stack_context stack_ctx;
1554
1555 stack_alloc.allocate( stack_ctx, attrs.size);
1556 BOOST_ASSERT( 0 != stack_ctx.sp);
1557
1558 typedef detail::pull_coroutine_object<
1559 push_coroutine< void >, void, Fn, StackAllocator
1560 > object_t;
1561
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
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
1579 stack_context stack_ctx;
1580 stack_allocator stack_alloc;
1581
1582 stack_alloc.allocate( stack_ctx, attrs.size);
1583 BOOST_ASSERT( 0 != stack_ctx.sp);
1584
1585 typedef detail::pull_coroutine_object<
1586 push_coroutine< void >, void, Fn, stack_allocator
1587 > object_t;
1588
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
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
1607 stack_context stack_ctx;
1608
1609 stack_alloc.allocate( stack_ctx, attrs.size);
1610 BOOST_ASSERT( 0 != stack_ctx.sp);
1611
1612 typedef detail::pull_coroutine_object<
1613 push_coroutine< void >, void, Fn, StackAllocator
1614 > object_t;
1615
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
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
1676 stack_context stack_ctx;
1677 stack_allocator stack_alloc;
1678
1679 stack_alloc.allocate( stack_ctx, attrs.size);
1680 BOOST_ASSERT( 0 != stack_ctx.sp);
1681
1682 typedef detail::push_coroutine_object<
1683 pull_coroutine< Arg >, Arg, coroutine_fn, stack_allocator
1684 > object_t;
1685
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
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
1704 stack_context stack_ctx;
1705
1706 stack_alloc.allocate( stack_ctx, attrs.size);
1707 BOOST_ASSERT( 0 != stack_ctx.sp);
1708
1709 typedef detail::push_coroutine_object<
1710 pull_coroutine< Arg >, Arg, coroutine_fn, StackAllocator
1711 > object_t;
1712
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
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
1729 stack_context stack_ctx;
1730 stack_allocator stack_alloc;
1731
1732 stack_alloc.allocate( stack_ctx, attrs.size);
1733 BOOST_ASSERT( 0 != stack_ctx.sp);
1734
1735 typedef detail::push_coroutine_object<
1736 pull_coroutine< Arg & >, Arg &, coroutine_fn, stack_allocator
1737 > object_t;
1738
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
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
1757 stack_context stack_ctx;
1758
1759 stack_alloc.allocate( stack_ctx, attrs.size);
1760 BOOST_ASSERT( 0 != stack_ctx.sp);
1761
1762 typedef detail::push_coroutine_object<
1763 pull_coroutine< Arg & >, Arg &, coroutine_fn, StackAllocator
1764 > object_t;
1765
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
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
1781 stack_context stack_ctx;
1782 stack_allocator stack_alloc;
1783
1784 stack_alloc.allocate( stack_ctx, attrs.size);
1785 BOOST_ASSERT( 0 != stack_ctx.sp);
1786
1787 typedef detail::push_coroutine_object<
1788 pull_coroutine< void >, void, coroutine_fn, stack_allocator
1789 > object_t;
1790
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
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
1808 stack_context stack_ctx;
1809
1810 stack_alloc.allocate( stack_ctx, attrs.size);
1811 BOOST_ASSERT( 0 != stack_ctx.sp);
1812
1813 typedef detail::push_coroutine_object<
1814 pull_coroutine< void >, void, coroutine_fn, StackAllocator
1815 > object_t;
1816
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
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
1834 stack_context stack_ctx;
1835 stack_allocator stack_alloc;
1836
1837 stack_alloc.allocate( stack_ctx, attrs.size);
1838 BOOST_ASSERT( 0 != stack_ctx.sp);
1839
1840 typedef detail::push_coroutine_object<
1841 pull_coroutine< Arg >, Arg, Fn, stack_allocator
1842 > object_t;
1843
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
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
1862 stack_context stack_ctx;
1863
1864 stack_alloc.allocate( stack_ctx, attrs.size);
1865 BOOST_ASSERT( 0 != stack_ctx.sp);
1866
1867 typedef detail::push_coroutine_object<
1868 pull_coroutine< Arg >, Arg, Fn, StackAllocator
1869 > object_t;
1870
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
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
1888 stack_context stack_ctx;
1889 stack_allocator stack_alloc;
1890
1891 stack_alloc.allocate( stack_ctx, attrs.size);
1892 BOOST_ASSERT( 0 != stack_ctx.sp);
1893
1894 typedef detail::push_coroutine_object<
1895 pull_coroutine< Arg & >, Arg &, Fn, stack_allocator
1896 > object_t;
1897
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
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
1916 stack_context stack_ctx;
1917
1918 stack_alloc.allocate( stack_ctx, attrs.size);
1919 BOOST_ASSERT( 0 != stack_ctx.sp);
1920
1921 typedef detail::push_coroutine_object<
1922 pull_coroutine< Arg & >, Arg &, Fn, StackAllocator
1923 > object_t;
1924
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
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
1941 stack_context stack_ctx;
1942 stack_allocator stack_alloc;
1943
1944 stack_alloc.allocate( stack_ctx, attrs.size);
1945 BOOST_ASSERT( 0 != stack_ctx.sp);
1946
1947 typedef detail::push_coroutine_object<
1948 pull_coroutine< void >, void, Fn, stack_allocator
1949 > object_t;
1950
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
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
1968 stack_context stack_ctx;
1969
1970 stack_alloc.allocate( stack_ctx, attrs.size);
1971 BOOST_ASSERT( 0 != stack_ctx.sp);
1972
1973 typedef detail::push_coroutine_object<
1974 pull_coroutine< void >, void, Fn, StackAllocator
1975 > object_t;
1976
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
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
1994 stack_context stack_ctx;
1995 stack_allocator stack_alloc;
1996
1997 stack_alloc.allocate( stack_ctx, attrs.size);
1998 BOOST_ASSERT( 0 != stack_ctx.sp);
1999
2000 typedef detail::push_coroutine_object<
2001 pull_coroutine< Arg >, Arg, Fn, stack_allocator
2002 > object_t;
2003
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
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
2022 stack_context stack_ctx;
2023
2024 stack_alloc.allocate( stack_ctx, attrs.size);
2025 BOOST_ASSERT( 0 != stack_ctx.sp);
2026
2027 typedef detail::push_coroutine_object<
2028 pull_coroutine< Arg >, Arg, Fn, StackAllocator
2029 > object_t;
2030
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
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
2048 stack_context stack_ctx;
2049 stack_allocator stack_alloc;
2050
2051 stack_alloc.allocate( stack_ctx, attrs.size);
2052 BOOST_ASSERT( 0 != stack_ctx.sp);
2053
2054 typedef detail::push_coroutine_object<
2055 pull_coroutine< Arg & >, Arg &, Fn, stack_allocator
2056 > object_t;
2057
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
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
2076 stack_context stack_ctx;
2077
2078 stack_alloc.allocate( stack_ctx, attrs.size);
2079 BOOST_ASSERT( 0 != stack_ctx.sp);
2080
2081 typedef detail::push_coroutine_object<
2082 pull_coroutine< Arg & >, Arg &, Fn, StackAllocator
2083 > object_t;
2084
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
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
2101 stack_context stack_ctx;
2102 stack_allocator stack_alloc;
2103
2104 stack_alloc.allocate( stack_ctx, attrs.size);
2105 BOOST_ASSERT( 0 != stack_ctx.sp);
2106
2107 typedef detail::push_coroutine_object<
2108 pull_coroutine< void >, void, Fn, stack_allocator
2109 > object_t;
2110
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
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
2128 stack_context stack_ctx;
2129
2130 stack_alloc.allocate( stack_ctx, attrs.size);
2131 BOOST_ASSERT( 0 != stack_ctx.sp);
2132
2133 typedef detail::push_coroutine_object<
2134 pull_coroutine< void >, void, Fn, StackAllocator
2135 > object_t;
2136
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
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
2154 stack_context stack_ctx;
2155 stack_allocator stack_alloc;
2156
2157 stack_alloc.allocate( stack_ctx, attrs.size);
2158 BOOST_ASSERT( 0 != stack_ctx.sp);
2159
2160 typedef detail::push_coroutine_object<
2161 pull_coroutine< Arg >, Arg, Fn, stack_allocator
2162 > object_t;
2163
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
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
2182 stack_context stack_ctx;
2183
2184 stack_alloc.allocate( stack_ctx, attrs.size);
2185 BOOST_ASSERT( 0 != stack_ctx.sp);
2186
2187 typedef detail::push_coroutine_object<
2188 pull_coroutine< Arg >, Arg, Fn, StackAllocator
2189 > object_t;
2190
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
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
2208 stack_context stack_ctx;
2209 stack_allocator stack_alloc;
2210
2211 stack_alloc.allocate( stack_ctx, attrs.size);
2212 BOOST_ASSERT( 0 != stack_ctx.sp);
2213
2214 typedef detail::push_coroutine_object<
2215 pull_coroutine< Arg & >, Arg &, Fn, stack_allocator
2216 > object_t;
2217
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
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
2236 stack_context stack_ctx;
2237
2238 stack_alloc.allocate( stack_ctx, attrs.size);
2239 BOOST_ASSERT( 0 != stack_ctx.sp);
2240
2241 typedef detail::push_coroutine_object<
2242 pull_coroutine< Arg & >, Arg &, Fn, StackAllocator
2243 > object_t;
2244
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
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
2261 stack_context stack_ctx;
2262 stack_allocator stack_alloc;
2263
2264 stack_alloc.allocate( stack_ctx, attrs.size);
2265 BOOST_ASSERT( 0 != stack_ctx.sp);
2266
2267 typedef detail::push_coroutine_object<
2268 pull_coroutine< void >, void, Fn, stack_allocator
2269 > object_t;
2270
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
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
2288 stack_context stack_ctx;
2289
2290 stack_alloc.allocate( stack_ctx, attrs.size);
2291 BOOST_ASSERT( 0 != stack_ctx.sp);
2292
2293 typedef detail::push_coroutine_object<
2294 pull_coroutine< void >, void, Fn, StackAllocator
2295 > object_t;
2296
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
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
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
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