File indexing completed on 2025-01-18 09:30:32
0001
0002
0003
0004
0005
0006
0007 #ifndef BOOST_COROUTINES_DETAIL_SYMMETRIC_COROUTINE_CALL_H
0008 #define BOOST_COROUTINES_DETAIL_SYMMETRIC_COROUTINE_CALL_H
0009
0010 #include <boost/assert.hpp>
0011 #include <boost/config.hpp>
0012 #include <boost/move/move.hpp>
0013 #include <boost/utility/explicit_operator_bool.hpp>
0014
0015 #include <boost/coroutine/attributes.hpp>
0016 #include <boost/coroutine/detail/config.hpp>
0017 #include <boost/coroutine/detail/preallocated.hpp>
0018 #include <boost/coroutine/detail/symmetric_coroutine_impl.hpp>
0019 #include <boost/coroutine/detail/symmetric_coroutine_object.hpp>
0020 #include <boost/coroutine/detail/symmetric_coroutine_yield.hpp>
0021 #include <boost/coroutine/stack_allocator.hpp>
0022 #include <boost/coroutine/stack_context.hpp>
0023
0024 #ifdef BOOST_HAS_ABI_HEADERS
0025 # include BOOST_ABI_PREFIX
0026 #endif
0027
0028 namespace boost {
0029 namespace coroutines {
0030 namespace detail {
0031
0032 template< typename Arg >
0033 class symmetric_coroutine_call
0034 {
0035 private:
0036 template< typename X >
0037 friend class symmetric_coroutine_yield;
0038
0039 typedef symmetric_coroutine_impl< Arg > impl_type;
0040
0041 BOOST_MOVABLE_BUT_NOT_COPYABLE( symmetric_coroutine_call)
0042
0043 struct dummy {};
0044
0045 impl_type * impl_;
0046
0047 public:
0048 typedef Arg value_type;
0049 typedef symmetric_coroutine_yield< Arg > yield_type;
0050
0051 symmetric_coroutine_call() BOOST_NOEXCEPT :
0052 impl_( 0)
0053 {}
0054
0055 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
0056 # ifdef BOOST_MSVC
0057 typedef void ( * coroutine_fn)( yield_type &);
0058
0059 explicit symmetric_coroutine_call( coroutine_fn fn,
0060 attributes const& attrs = attributes(),
0061 stack_allocator stack_alloc = stack_allocator() ) :
0062 impl_( 0)
0063 {
0064
0065 stack_context stack_ctx;
0066
0067 stack_alloc.allocate( stack_ctx, attrs.size);
0068 BOOST_ASSERT( 0 != stack_ctx.sp);
0069
0070 typedef symmetric_coroutine_object< Arg, coroutine_fn, stack_allocator > object_t;
0071
0072 std::size_t size = stack_ctx.size - sizeof( object_t);
0073 BOOST_ASSERT( 0 != size);
0074 void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
0075 BOOST_ASSERT( 0 != sp);
0076
0077 impl_ = new ( sp) object_t(
0078 boost::forward< coroutine_fn >( fn), attrs, preallocated( sp, size, stack_ctx), stack_alloc);
0079 BOOST_ASSERT( impl_);
0080 }
0081
0082 template< typename StackAllocator >
0083 explicit symmetric_coroutine_call( coroutine_fn fn,
0084 attributes const& attrs,
0085 StackAllocator stack_alloc) :
0086 impl_( 0)
0087 {
0088
0089 stack_context stack_ctx;
0090
0091 stack_alloc.allocate( stack_ctx, attrs.size);
0092 BOOST_ASSERT( 0 != stack_ctx.sp);
0093
0094 typedef symmetric_coroutine_object< Arg, coroutine_fn, StackAllocator > object_t;
0095
0096 std::size_t size = stack_ctx.size - sizeof( object_t);
0097 BOOST_ASSERT( 0 != size);
0098 void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
0099 BOOST_ASSERT( 0 != sp);
0100
0101 impl_ = new ( sp) object_t(
0102 boost::forward< coroutine_fn >( fn), attrs, preallocated( sp, size, stack_ctx), stack_alloc);
0103 BOOST_ASSERT( impl_);
0104 }
0105 # endif
0106 template< typename Fn >
0107 explicit symmetric_coroutine_call( BOOST_RV_REF( Fn) fn,
0108 attributes const& attrs = attributes(),
0109 stack_allocator stack_alloc = stack_allocator() ) :
0110 impl_( 0)
0111 {
0112
0113 stack_context stack_ctx;
0114
0115 stack_alloc.allocate( stack_ctx, attrs.size);
0116 BOOST_ASSERT( 0 != stack_ctx.sp);
0117
0118 typedef symmetric_coroutine_object< Arg, Fn, stack_allocator > object_t;
0119
0120 std::size_t size = stack_ctx.size - sizeof( object_t);
0121 BOOST_ASSERT( 0 != size);
0122 void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
0123 BOOST_ASSERT( 0 != sp);
0124
0125 impl_ = new ( sp) object_t(
0126 boost::forward< Fn >( fn), attrs, preallocated( sp, size, stack_ctx), stack_alloc);
0127 BOOST_ASSERT( impl_);
0128 }
0129
0130 template< typename Fn, typename StackAllocator >
0131 explicit symmetric_coroutine_call( BOOST_RV_REF( Fn) fn,
0132 attributes const& attrs,
0133 StackAllocator stack_alloc) :
0134 impl_( 0)
0135 {
0136
0137 stack_context stack_ctx;
0138
0139 stack_alloc.allocate( stack_ctx, attrs.size);
0140 BOOST_ASSERT( 0 != stack_ctx.sp);
0141
0142 typedef symmetric_coroutine_object< Arg, Fn, StackAllocator > object_t;
0143
0144 std::size_t size = stack_ctx.size - sizeof( object_t);
0145 BOOST_ASSERT( 0 != size);
0146 void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
0147 BOOST_ASSERT( 0 != sp);
0148
0149 impl_ = new ( sp) object_t(
0150 boost::forward< Fn >( fn), attrs, preallocated( sp, size, stack_ctx), stack_alloc);
0151 BOOST_ASSERT( impl_);
0152 }
0153 #else
0154 template< typename Fn >
0155 explicit symmetric_coroutine_call( Fn fn,
0156 attributes const& attrs = attributes(),
0157 stack_allocator stack_alloc = stack_allocator() ) :
0158 impl_( 0)
0159 {
0160
0161 stack_context stack_ctx;
0162
0163 stack_alloc.allocate( stack_ctx, attrs.size);
0164 BOOST_ASSERT( 0 != stack_ctx.sp);
0165
0166 typedef symmetric_coroutine_object< Arg, Fn, stack_allocator > object_t;
0167
0168 std::size_t size = stack_ctx.size - sizeof( object_t);
0169 BOOST_ASSERT( 0 != size);
0170 void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
0171 BOOST_ASSERT( 0 != sp);
0172
0173 impl_ = new ( sp) object_t(
0174 fn, attrs, preallocated( sp, size, stack_ctx), stack_alloc);
0175 BOOST_ASSERT( impl_);
0176 }
0177
0178 template< typename Fn, typename StackAllocator >
0179 explicit symmetric_coroutine_call( Fn fn,
0180 attributes const& attrs,
0181 StackAllocator stack_alloc) :
0182 impl_( 0)
0183 {
0184
0185 stack_context stack_ctx;
0186
0187 stack_alloc.allocate( stack_ctx, attrs.size);
0188 BOOST_ASSERT( 0 != stack_ctx.sp);
0189
0190 typedef symmetric_coroutine_object< Arg, Fn, StackAllocator > object_t;
0191
0192 std::size_t size = stack_ctx.size - sizeof( object_t);
0193 BOOST_ASSERT( 0 != size);
0194 void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
0195 BOOST_ASSERT( 0 != sp);
0196
0197 impl_ = new ( sp) object_t(
0198 fn, attrs, preallocated( sp, size, stack_ctx), stack_alloc);
0199 BOOST_ASSERT( impl_);
0200 }
0201
0202 template< typename Fn >
0203 explicit symmetric_coroutine_call( BOOST_RV_REF( Fn) fn,
0204 attributes const& attrs = attributes(),
0205 stack_allocator stack_alloc = stack_allocator() ) :
0206 impl_( 0)
0207 {
0208
0209 stack_context stack_ctx;
0210
0211 stack_alloc.allocate( stack_ctx, attrs.size);
0212 BOOST_ASSERT( 0 != stack_ctx.sp);
0213
0214 typedef symmetric_coroutine_object< Arg, Fn, stack_allocator > object_t;
0215
0216 std::size_t size = stack_ctx.size - sizeof( object_t);
0217 BOOST_ASSERT( 0 != size);
0218 void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
0219 BOOST_ASSERT( 0 != sp);
0220
0221 impl_ = new ( sp) object_t(
0222 fn, attrs, preallocated( sp, size, stack_ctx), stack_alloc);
0223 BOOST_ASSERT( impl_);
0224 }
0225
0226 template< typename Fn, typename StackAllocator >
0227 explicit symmetric_coroutine_call( BOOST_RV_REF( Fn) fn,
0228 attributes const& attrs,
0229 StackAllocator stack_alloc) :
0230 impl_( 0)
0231 {
0232
0233 stack_context stack_ctx;
0234
0235 stack_alloc.allocate( stack_ctx, attrs.size);
0236 BOOST_ASSERT( 0 != stack_ctx.sp);
0237
0238 typedef symmetric_coroutine_object< Arg, Fn, StackAllocator > object_t;
0239
0240 std::size_t size = stack_ctx.size - sizeof( object_t);
0241 BOOST_ASSERT( 0 != size);
0242 void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
0243 BOOST_ASSERT( 0 != sp);
0244
0245 impl_ = new ( sp) object_t(
0246 fn, attrs, preallocated( sp, size, stack_ctx), stack_alloc);
0247 BOOST_ASSERT( impl_);
0248 }
0249 #endif
0250
0251 ~symmetric_coroutine_call()
0252 {
0253 if ( 0 != impl_)
0254 {
0255 impl_->destroy();
0256 impl_ = 0;
0257 }
0258 }
0259
0260 symmetric_coroutine_call( BOOST_RV_REF( symmetric_coroutine_call) other) BOOST_NOEXCEPT :
0261 impl_( 0)
0262 { swap( other); }
0263
0264 symmetric_coroutine_call & operator=( BOOST_RV_REF( symmetric_coroutine_call) other) BOOST_NOEXCEPT
0265 {
0266 symmetric_coroutine_call tmp( boost::move( other) );
0267 swap( tmp);
0268 return * this;
0269 }
0270
0271 BOOST_EXPLICIT_OPERATOR_BOOL();
0272
0273 bool operator!() const BOOST_NOEXCEPT
0274 { return 0 == impl_ || impl_->is_complete() || impl_->is_running(); }
0275
0276 void swap( symmetric_coroutine_call & other) BOOST_NOEXCEPT
0277 { std::swap( impl_, other.impl_); }
0278
0279 symmetric_coroutine_call & operator()( Arg arg) BOOST_NOEXCEPT
0280 {
0281 BOOST_ASSERT( * this);
0282
0283 impl_->resume( arg);
0284 return * this;
0285 }
0286 };
0287
0288 template< typename Arg >
0289 class symmetric_coroutine_call< Arg & >
0290 {
0291 private:
0292 template< typename X >
0293 friend class symmetric_coroutine_yield;
0294
0295 typedef symmetric_coroutine_impl< Arg & > impl_type;
0296
0297 BOOST_MOVABLE_BUT_NOT_COPYABLE( symmetric_coroutine_call)
0298
0299 struct dummy {};
0300
0301 impl_type * impl_;
0302
0303 public:
0304 typedef Arg value_type;
0305 typedef symmetric_coroutine_yield< Arg & > yield_type;
0306
0307 symmetric_coroutine_call() BOOST_NOEXCEPT :
0308 impl_( 0)
0309 {}
0310
0311 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
0312 # ifdef BOOST_MSVC
0313 typedef void ( * coroutine_fn)( yield_type &);
0314
0315 explicit symmetric_coroutine_call( coroutine_fn fn,
0316 attributes const& attrs = attributes(),
0317 stack_allocator stack_alloc = stack_allocator() ) :
0318 impl_( 0)
0319 {
0320
0321 stack_context stack_ctx;
0322
0323 stack_alloc.allocate( stack_ctx, attrs.size);
0324 BOOST_ASSERT( 0 != stack_ctx.sp);
0325
0326 typedef symmetric_coroutine_object< Arg &, coroutine_fn, stack_allocator > object_t;
0327
0328 std::size_t size = stack_ctx.size - sizeof( object_t);
0329 BOOST_ASSERT( 0 != size);
0330 void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
0331 BOOST_ASSERT( 0 != sp);
0332
0333 impl_ = new ( sp) object_t(
0334 boost::forward< coroutine_fn >( fn), attrs, preallocated( sp, size, stack_ctx), stack_alloc);
0335 BOOST_ASSERT( impl_);
0336 }
0337
0338 template< typename StackAllocator >
0339 explicit symmetric_coroutine_call( coroutine_fn fn,
0340 attributes const& attrs,
0341 StackAllocator stack_alloc) :
0342 impl_( 0)
0343 {
0344
0345 stack_context stack_ctx;
0346
0347 stack_alloc.allocate( stack_ctx, attrs.size);
0348 BOOST_ASSERT( 0 != stack_ctx.sp);
0349
0350 typedef symmetric_coroutine_object< Arg &, coroutine_fn, StackAllocator > object_t;
0351
0352 std::size_t size = stack_ctx.size - sizeof( object_t);
0353 BOOST_ASSERT( 0 != size);
0354 void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
0355 BOOST_ASSERT( 0 != sp);
0356
0357 impl_ = new ( sp) object_t(
0358 boost::forward< coroutine_fn >( fn), attrs, preallocated( sp, size, stack_ctx), stack_alloc);
0359 BOOST_ASSERT( impl_);
0360 }
0361 # endif
0362 template< typename Fn >
0363 explicit symmetric_coroutine_call( BOOST_RV_REF( Fn) fn,
0364 attributes const& attrs = attributes(),
0365 stack_allocator stack_alloc = stack_allocator() ) :
0366 impl_( 0)
0367 {
0368
0369 stack_context stack_ctx;
0370
0371 stack_alloc.allocate( stack_ctx, attrs.size);
0372 BOOST_ASSERT( 0 != stack_ctx.sp);
0373
0374 typedef symmetric_coroutine_object< Arg &, Fn, stack_allocator > object_t;
0375
0376 std::size_t size = stack_ctx.size - sizeof( object_t);
0377 BOOST_ASSERT( 0 != size);
0378 void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
0379 BOOST_ASSERT( 0 != sp);
0380
0381 impl_ = new ( sp) object_t(
0382 boost::forward< Fn >( fn), attrs, preallocated( sp, size, stack_ctx), stack_alloc);
0383 BOOST_ASSERT( impl_);
0384 }
0385
0386 template< typename Fn, typename StackAllocator >
0387 explicit symmetric_coroutine_call( BOOST_RV_REF( Fn) fn,
0388 attributes const& attrs,
0389 StackAllocator stack_alloc) :
0390 impl_( 0)
0391 {
0392
0393 stack_context stack_ctx;
0394
0395 stack_alloc.allocate( stack_ctx, attrs.size);
0396 BOOST_ASSERT( 0 != stack_ctx.sp);
0397
0398 typedef symmetric_coroutine_object< Arg &, Fn, StackAllocator > object_t;
0399
0400 std::size_t size = stack_ctx.size - sizeof( object_t);
0401 BOOST_ASSERT( 0 != size);
0402 void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
0403 BOOST_ASSERT( 0 != sp);
0404
0405 impl_ = new ( sp) object_t(
0406 boost::forward< Fn >( fn), attrs, preallocated( sp, size, stack_ctx), stack_alloc);
0407 BOOST_ASSERT( impl_);
0408 }
0409 #else
0410 template< typename Fn >
0411 explicit symmetric_coroutine_call( Fn fn,
0412 attributes const& attrs = attributes(),
0413 stack_allocator stack_alloc = stack_allocator() ) :
0414 impl_( 0)
0415 {
0416
0417 stack_context stack_ctx;
0418
0419 stack_alloc.allocate( stack_ctx, attrs.size);
0420 BOOST_ASSERT( 0 != stack_ctx.sp);
0421
0422 typedef symmetric_coroutine_object< Arg &, Fn, stack_allocator > object_t;
0423
0424 std::size_t size = stack_ctx.size - sizeof( object_t);
0425 BOOST_ASSERT( 0 != size);
0426 void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
0427 BOOST_ASSERT( 0 != sp);
0428
0429 impl_ = new ( sp) object_t(
0430 fn, attrs, preallocated( sp, size, stack_ctx), stack_alloc);
0431 BOOST_ASSERT( impl_);
0432 }
0433
0434 template< typename Fn, typename StackAllocator >
0435 explicit symmetric_coroutine_call( Fn fn,
0436 attributes const& attrs,
0437 StackAllocator stack_alloc) :
0438 impl_( 0)
0439 {
0440
0441 stack_context stack_ctx;
0442
0443 stack_alloc.allocate( stack_ctx, attrs.size);
0444 BOOST_ASSERT( 0 != stack_ctx.sp);
0445
0446 typedef symmetric_coroutine_object< Arg &, Fn, StackAllocator > object_t;
0447
0448 std::size_t size = stack_ctx.size - sizeof( object_t);
0449 BOOST_ASSERT( 0 != size);
0450 void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
0451 BOOST_ASSERT( 0 != sp);
0452
0453 impl_ = new ( sp) object_t(
0454 fn, attrs, preallocated( sp, size, stack_ctx), stack_alloc);
0455 BOOST_ASSERT( impl_);
0456 }
0457
0458 template< typename Fn >
0459 explicit symmetric_coroutine_call( BOOST_RV_REF( Fn) fn,
0460 attributes const& attrs = attributes(),
0461 stack_allocator stack_alloc = stack_allocator() ) :
0462 impl_( 0)
0463 {
0464
0465 stack_context stack_ctx;
0466
0467 stack_alloc.allocate( stack_ctx, attrs.size);
0468 BOOST_ASSERT( 0 != stack_ctx.sp);
0469
0470 typedef symmetric_coroutine_object< Arg &, Fn, stack_allocator > object_t;
0471
0472 std::size_t size = stack_ctx.size - sizeof( object_t);
0473 BOOST_ASSERT( 0 != size);
0474 void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
0475 BOOST_ASSERT( 0 != sp);
0476
0477 impl_ = new ( sp) object_t(
0478 fn, attrs, preallocated( sp, size, stack_ctx), stack_alloc);
0479 BOOST_ASSERT( impl_);
0480 }
0481
0482 template< typename Fn, typename StackAllocator >
0483 explicit symmetric_coroutine_call( BOOST_RV_REF( Fn) fn,
0484 attributes const& attrs,
0485 StackAllocator stack_alloc) :
0486 impl_( 0)
0487 {
0488
0489 stack_context stack_ctx;
0490
0491 stack_alloc.allocate( stack_ctx, attrs.size);
0492 BOOST_ASSERT( 0 != stack_ctx.sp);
0493
0494 typedef symmetric_coroutine_object< Arg &, Fn, StackAllocator > object_t;
0495
0496 std::size_t size = stack_ctx.size - sizeof( object_t);
0497 BOOST_ASSERT( 0 != size);
0498 void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
0499 BOOST_ASSERT( 0 != sp);
0500
0501 impl_ = new ( sp) object_t(
0502 fn, attrs, preallocated( sp, size, stack_ctx), stack_alloc);
0503 BOOST_ASSERT( impl_);
0504 }
0505 #endif
0506
0507 ~symmetric_coroutine_call()
0508 {
0509 if ( 0 != impl_)
0510 {
0511 impl_->destroy();
0512 impl_ = 0;
0513 }
0514 }
0515
0516 symmetric_coroutine_call( BOOST_RV_REF( symmetric_coroutine_call) other) BOOST_NOEXCEPT :
0517 impl_( 0)
0518 { swap( other); }
0519
0520 symmetric_coroutine_call & operator=( BOOST_RV_REF( symmetric_coroutine_call) other) BOOST_NOEXCEPT
0521 {
0522 symmetric_coroutine_call tmp( boost::move( other) );
0523 swap( tmp);
0524 return * this;
0525 }
0526
0527 BOOST_EXPLICIT_OPERATOR_BOOL();
0528
0529 bool operator!() const BOOST_NOEXCEPT
0530 { return 0 == impl_ || impl_->is_complete() || impl_->is_running(); }
0531
0532 void swap( symmetric_coroutine_call & other) BOOST_NOEXCEPT
0533 { std::swap( impl_, other.impl_); }
0534
0535 symmetric_coroutine_call & operator()( Arg & arg) BOOST_NOEXCEPT
0536 {
0537 BOOST_ASSERT( * this);
0538
0539 impl_->resume( arg);
0540 return * this;
0541 }
0542 };
0543
0544 template<>
0545 class symmetric_coroutine_call< void >
0546 {
0547 private:
0548 template< typename X >
0549 friend class symmetric_coroutine_yield;
0550
0551 typedef symmetric_coroutine_impl< void > impl_type;
0552
0553 BOOST_MOVABLE_BUT_NOT_COPYABLE( symmetric_coroutine_call)
0554
0555 struct dummy {};
0556
0557 impl_type * impl_;
0558
0559 public:
0560 typedef void value_type;
0561 typedef symmetric_coroutine_yield< void > yield_type;
0562
0563 symmetric_coroutine_call() BOOST_NOEXCEPT :
0564 impl_( 0)
0565 {}
0566
0567 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
0568 # ifdef BOOST_MSVC
0569 typedef void ( * coroutine_fn)( yield_type &);
0570
0571 explicit symmetric_coroutine_call( coroutine_fn fn,
0572 attributes const& attrs = attributes(),
0573 stack_allocator stack_alloc = stack_allocator() ) :
0574 impl_( 0)
0575 {
0576
0577 stack_context stack_ctx;
0578
0579 stack_alloc.allocate( stack_ctx, attrs.size);
0580 BOOST_ASSERT( 0 != stack_ctx.sp);
0581
0582 typedef symmetric_coroutine_object< void, coroutine_fn, stack_allocator > object_t;
0583
0584 std::size_t size = stack_ctx.size - sizeof( object_t);
0585 BOOST_ASSERT( 0 != size);
0586 void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
0587 BOOST_ASSERT( 0 != sp);
0588
0589 impl_ = new ( sp) object_t(
0590 boost::forward< coroutine_fn >( fn), attrs, preallocated( sp, size, stack_ctx), stack_alloc);
0591 BOOST_ASSERT( impl_);
0592 }
0593
0594 template< typename StackAllocator >
0595 explicit symmetric_coroutine_call( coroutine_fn fn,
0596 attributes const& attrs,
0597 StackAllocator stack_alloc) :
0598 impl_( 0)
0599 {
0600
0601 stack_context stack_ctx;
0602
0603 stack_alloc.allocate( stack_ctx, attrs.size);
0604 BOOST_ASSERT( 0 != stack_ctx.sp);
0605
0606 typedef symmetric_coroutine_object< void, coroutine_fn, StackAllocator > object_t;
0607
0608 std::size_t size = stack_ctx.size - sizeof( object_t);
0609 BOOST_ASSERT( 0 != size);
0610 void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
0611 BOOST_ASSERT( 0 != sp);
0612
0613 impl_ = new ( sp) object_t(
0614 boost::forward< coroutine_fn >( fn), attrs, preallocated( sp, size, stack_ctx), stack_alloc);
0615 BOOST_ASSERT( impl_);
0616 }
0617 # endif
0618 template< typename Fn >
0619 explicit symmetric_coroutine_call( BOOST_RV_REF( Fn) fn,
0620 attributes const& attrs = attributes(),
0621 stack_allocator stack_alloc = stack_allocator() ) :
0622 impl_( 0)
0623 {
0624
0625 stack_context stack_ctx;
0626
0627 stack_alloc.allocate( stack_ctx, attrs.size);
0628 BOOST_ASSERT( 0 != stack_ctx.sp);
0629
0630 typedef symmetric_coroutine_object< void, Fn, stack_allocator > object_t;
0631
0632 std::size_t size = stack_ctx.size - sizeof( object_t);
0633 BOOST_ASSERT( 0 != size);
0634 void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
0635 BOOST_ASSERT( 0 != sp);
0636
0637 impl_ = new ( sp) object_t(
0638 boost::forward< Fn >( fn), attrs, preallocated( sp, size, stack_ctx), stack_alloc);
0639 BOOST_ASSERT( impl_);
0640 }
0641
0642 template< typename Fn, typename StackAllocator >
0643 explicit symmetric_coroutine_call( BOOST_RV_REF( Fn) fn,
0644 attributes const& attrs,
0645 StackAllocator stack_alloc) :
0646 impl_( 0)
0647 {
0648
0649 stack_context stack_ctx;
0650
0651 stack_alloc.allocate( stack_ctx, attrs.size);
0652 BOOST_ASSERT( 0 != stack_ctx.sp);
0653
0654 typedef symmetric_coroutine_object< void, Fn, StackAllocator > object_t;
0655
0656 std::size_t size = stack_ctx.size - sizeof( object_t);
0657 BOOST_ASSERT( 0 != size);
0658 void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
0659 BOOST_ASSERT( 0 != sp);
0660
0661 impl_ = new ( sp) object_t(
0662 boost::forward< Fn >( fn), attrs, preallocated( sp, size, stack_ctx), stack_alloc);
0663 BOOST_ASSERT( impl_);
0664 }
0665 #else
0666 template< typename Fn >
0667 explicit symmetric_coroutine_call( Fn fn,
0668 attributes const& attrs = attributes(),
0669 stack_allocator stack_alloc = stack_allocator() ) :
0670 impl_( 0)
0671 {
0672
0673 stack_context stack_ctx;
0674
0675 stack_alloc.allocate( stack_ctx, attrs.size);
0676 BOOST_ASSERT( 0 != stack_ctx.sp);
0677
0678 typedef symmetric_coroutine_object< void, Fn, stack_allocator > object_t;
0679
0680 std::size_t size = stack_ctx.size - sizeof( object_t);
0681 BOOST_ASSERT( 0 != size);
0682 void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
0683 BOOST_ASSERT( 0 != sp);
0684
0685 impl_ = new ( sp) object_t(
0686 fn, attrs, preallocated( sp, size, stack_ctx), stack_alloc);
0687 BOOST_ASSERT( impl_);
0688 }
0689
0690 template< typename Fn, typename StackAllocator >
0691 explicit symmetric_coroutine_call( Fn fn,
0692 attributes const& attrs,
0693 StackAllocator stack_alloc) :
0694 impl_( 0)
0695 {
0696
0697 stack_context stack_ctx;
0698
0699 stack_alloc.allocate( stack_ctx, attrs.size);
0700 BOOST_ASSERT( 0 != stack_ctx.sp);
0701
0702 typedef symmetric_coroutine_object< void, Fn, StackAllocator > object_t;
0703
0704 std::size_t size = stack_ctx.size - sizeof( object_t);
0705 BOOST_ASSERT( 0 != size);
0706 void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
0707 BOOST_ASSERT( 0 != sp);
0708
0709 impl_ = new ( sp) object_t(
0710 fn, attrs, preallocated( sp, size, stack_ctx), stack_alloc);
0711 BOOST_ASSERT( impl_);
0712 }
0713
0714 template< typename Fn >
0715 explicit symmetric_coroutine_call( BOOST_RV_REF( Fn) fn,
0716 attributes const& attrs = attributes(),
0717 stack_allocator stack_alloc = stack_allocator() ) :
0718 impl_( 0)
0719 {
0720
0721 stack_context stack_ctx;
0722
0723 stack_alloc.allocate( stack_ctx, attrs.size);
0724 BOOST_ASSERT( 0 != stack_ctx.sp);
0725
0726 typedef symmetric_coroutine_object< void, Fn, stack_allocator > object_t;
0727
0728 std::size_t size = stack_ctx.size - sizeof( object_t);
0729 BOOST_ASSERT( 0 != size);
0730 void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
0731 BOOST_ASSERT( 0 != sp);
0732
0733 impl_ = new ( sp) object_t(
0734 fn, attrs, preallocated( sp, size, stack_ctx), stack_alloc);
0735 BOOST_ASSERT( impl_);
0736 }
0737
0738 template< typename Fn, typename StackAllocator >
0739 explicit symmetric_coroutine_call( BOOST_RV_REF( Fn) fn,
0740 attributes const& attrs,
0741 StackAllocator stack_alloc) :
0742 impl_( 0)
0743 {
0744
0745 stack_context stack_ctx;
0746
0747 stack_alloc.allocate( stack_ctx, attrs.size);
0748 BOOST_ASSERT( 0 != stack_ctx.sp);
0749
0750 typedef symmetric_coroutine_object< void, Fn, StackAllocator > object_t;
0751
0752 std::size_t size = stack_ctx.size - sizeof( object_t);
0753 BOOST_ASSERT( 0 != size);
0754 void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
0755 BOOST_ASSERT( 0 != sp);
0756
0757 impl_ = new ( sp) object_t(
0758 fn, attrs, preallocated( sp, size, stack_ctx), stack_alloc);
0759 BOOST_ASSERT( impl_);
0760 }
0761 #endif
0762
0763 ~symmetric_coroutine_call()
0764 {
0765 if ( 0 != impl_)
0766 {
0767 impl_->destroy();
0768 impl_ = 0;
0769 }
0770 }
0771
0772 inline symmetric_coroutine_call( BOOST_RV_REF( symmetric_coroutine_call) other) BOOST_NOEXCEPT :
0773 impl_( 0)
0774 { swap( other); }
0775
0776 inline symmetric_coroutine_call & operator=( BOOST_RV_REF( symmetric_coroutine_call) other) BOOST_NOEXCEPT
0777 {
0778 symmetric_coroutine_call tmp( boost::move( other) );
0779 swap( tmp);
0780 return * this;
0781 }
0782
0783 BOOST_EXPLICIT_OPERATOR_BOOL();
0784
0785 inline bool operator!() const BOOST_NOEXCEPT
0786 { return 0 == impl_ || impl_->is_complete() || impl_->is_running(); }
0787
0788 inline void swap( symmetric_coroutine_call & other) BOOST_NOEXCEPT
0789 { std::swap( impl_, other.impl_); }
0790
0791 inline symmetric_coroutine_call & operator()() BOOST_NOEXCEPT
0792 {
0793 BOOST_ASSERT( * this);
0794
0795 impl_->resume();
0796 return * this;
0797 }
0798 };
0799
0800 template< typename Arg >
0801 void swap( symmetric_coroutine_call< Arg > & l,
0802 symmetric_coroutine_call< Arg > & r)
0803 { l.swap( r); }
0804
0805 }}}
0806
0807 #ifdef BOOST_HAS_ABI_HEADERS
0808 # include BOOST_ABI_SUFFIX
0809 #endif
0810
0811 #endif