Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:30:32

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_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         // create a stack-context
0065         stack_context stack_ctx;
0066         // allocate the coroutine-stack
0067         stack_alloc.allocate( stack_ctx, attrs.size);
0068         BOOST_ASSERT( 0 != stack_ctx.sp);
0069         // typedef of internal coroutine-type
0070         typedef symmetric_coroutine_object< Arg, coroutine_fn, stack_allocator > object_t;
0071         // reserve space on top of coroutine-stack for internal coroutine-type
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         // placement new for internal coroutine
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         // create a stack-context
0089         stack_context stack_ctx;
0090         // allocate the coroutine-stack
0091         stack_alloc.allocate( stack_ctx, attrs.size);
0092         BOOST_ASSERT( 0 != stack_ctx.sp);
0093         // typedef of internal coroutine-type
0094         typedef symmetric_coroutine_object< Arg, coroutine_fn, StackAllocator > object_t;
0095         // reserve space on top of coroutine-stack for internal coroutine-type
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         // placement new for internal coroutine
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         // create a stack-context
0113         stack_context stack_ctx;
0114         // allocate the coroutine-stack
0115         stack_alloc.allocate( stack_ctx, attrs.size);
0116         BOOST_ASSERT( 0 != stack_ctx.sp);
0117         // typedef of internal coroutine-type
0118         typedef symmetric_coroutine_object< Arg, Fn, stack_allocator > object_t;
0119         // reserve space on top of coroutine-stack for internal coroutine-type
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         // placement new for internal coroutine
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         // create a stack-context
0137         stack_context stack_ctx;
0138         // allocate the coroutine-stack
0139         stack_alloc.allocate( stack_ctx, attrs.size);
0140         BOOST_ASSERT( 0 != stack_ctx.sp);
0141         // typedef of internal coroutine-type
0142         typedef symmetric_coroutine_object< Arg, Fn, StackAllocator > object_t;
0143         // reserve space on top of coroutine-stack for internal coroutine-type
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         // placement new for internal coroutine
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         // create a stack-context
0161         stack_context stack_ctx;
0162         // allocate the coroutine-stack
0163         stack_alloc.allocate( stack_ctx, attrs.size);
0164         BOOST_ASSERT( 0 != stack_ctx.sp);
0165         // typedef of internal coroutine-type
0166         typedef symmetric_coroutine_object< Arg, Fn, stack_allocator > object_t;
0167         // reserve space on top of coroutine-stack for internal coroutine-type
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         // placement new for internal coroutine
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         // create a stack-context
0185         stack_context stack_ctx;
0186         // allocate the coroutine-stack
0187         stack_alloc.allocate( stack_ctx, attrs.size);
0188         BOOST_ASSERT( 0 != stack_ctx.sp);
0189         // typedef of internal coroutine-type
0190         typedef symmetric_coroutine_object< Arg, Fn, StackAllocator > object_t;
0191         // reserve space on top of coroutine-stack for internal coroutine-type
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         // placement new for internal coroutine
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         // create a stack-context
0209         stack_context stack_ctx;
0210         // allocate the coroutine-stack
0211         stack_alloc.allocate( stack_ctx, attrs.size);
0212         BOOST_ASSERT( 0 != stack_ctx.sp);
0213         // typedef of internal coroutine-type
0214         typedef symmetric_coroutine_object< Arg, Fn, stack_allocator > object_t;
0215         // reserve space on top of coroutine-stack for internal coroutine-type
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         // placement new for internal coroutine
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         // create a stack-context
0233         stack_context stack_ctx;
0234         // allocate the coroutine-stack
0235         stack_alloc.allocate( stack_ctx, attrs.size);
0236         BOOST_ASSERT( 0 != stack_ctx.sp);
0237         // typedef of internal coroutine-type
0238         typedef symmetric_coroutine_object< Arg, Fn, StackAllocator > object_t;
0239         // reserve space on top of coroutine-stack for internal coroutine-type
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         // placement new for internal coroutine
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         // create a stack-context
0321         stack_context stack_ctx;
0322         // allocate the coroutine-stack
0323         stack_alloc.allocate( stack_ctx, attrs.size);
0324         BOOST_ASSERT( 0 != stack_ctx.sp);
0325         // typedef of internal coroutine-type
0326         typedef symmetric_coroutine_object< Arg &, coroutine_fn, stack_allocator > object_t;
0327         // reserve space on top of coroutine-stack for internal coroutine-type
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         // placement new for internal coroutine
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         // create a stack-context
0345         stack_context stack_ctx;
0346         // allocate the coroutine-stack
0347         stack_alloc.allocate( stack_ctx, attrs.size);
0348         BOOST_ASSERT( 0 != stack_ctx.sp);
0349         // typedef of internal coroutine-type
0350         typedef symmetric_coroutine_object< Arg &, coroutine_fn, StackAllocator > object_t;
0351         // reserve space on top of coroutine-stack for internal coroutine-type
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         // placement new for internal coroutine
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         // create a stack-context
0369         stack_context stack_ctx;
0370         // allocate the coroutine-stack
0371         stack_alloc.allocate( stack_ctx, attrs.size);
0372         BOOST_ASSERT( 0 != stack_ctx.sp);
0373         // typedef of internal coroutine-type
0374         typedef symmetric_coroutine_object< Arg &, Fn, stack_allocator > object_t;
0375         // reserve space on top of coroutine-stack for internal coroutine-type
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         // placement new for internal coroutine
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         // create a stack-context
0393         stack_context stack_ctx;
0394         // allocate the coroutine-stack
0395         stack_alloc.allocate( stack_ctx, attrs.size);
0396         BOOST_ASSERT( 0 != stack_ctx.sp);
0397         // typedef of internal coroutine-type
0398         typedef symmetric_coroutine_object< Arg &, Fn, StackAllocator > object_t;
0399         // reserve space on top of coroutine-stack for internal coroutine-type
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         // placement new for internal coroutine
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         // create a stack-context
0417         stack_context stack_ctx;
0418         // allocate the coroutine-stack
0419         stack_alloc.allocate( stack_ctx, attrs.size);
0420         BOOST_ASSERT( 0 != stack_ctx.sp);
0421         // typedef of internal coroutine-type
0422         typedef symmetric_coroutine_object< Arg &, Fn, stack_allocator > object_t;
0423         // reserve space on top of coroutine-stack for internal coroutine-type
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         // placement new for internal coroutine
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         // create a stack-context
0441         stack_context stack_ctx;
0442         // allocate the coroutine-stack
0443         stack_alloc.allocate( stack_ctx, attrs.size);
0444         BOOST_ASSERT( 0 != stack_ctx.sp);
0445         // typedef of internal coroutine-type
0446         typedef symmetric_coroutine_object< Arg &, Fn, StackAllocator > object_t;
0447         // reserve space on top of coroutine-stack for internal coroutine-type
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         // placement new for internal coroutine
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         // create a stack-context
0465         stack_context stack_ctx;
0466         // allocate the coroutine-stack
0467         stack_alloc.allocate( stack_ctx, attrs.size);
0468         BOOST_ASSERT( 0 != stack_ctx.sp);
0469         // typedef of internal coroutine-type
0470         typedef symmetric_coroutine_object< Arg &, Fn, stack_allocator > object_t;
0471         // reserve space on top of coroutine-stack for internal coroutine-type
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         // placement new for internal coroutine
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         // create a stack-context
0489         stack_context stack_ctx;
0490         // allocate the coroutine-stack
0491         stack_alloc.allocate( stack_ctx, attrs.size);
0492         BOOST_ASSERT( 0 != stack_ctx.sp);
0493         // typedef of internal coroutine-type
0494         typedef symmetric_coroutine_object< Arg &, Fn, StackAllocator > object_t;
0495         // reserve space on top of coroutine-stack for internal coroutine-type
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         // placement new for internal coroutine
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         // create a stack-context
0577         stack_context stack_ctx;
0578         // allocate the coroutine-stack
0579         stack_alloc.allocate( stack_ctx, attrs.size);
0580         BOOST_ASSERT( 0 != stack_ctx.sp);
0581         // typedef of internal coroutine-type
0582         typedef symmetric_coroutine_object< void, coroutine_fn, stack_allocator > object_t;
0583         // reserve space on top of coroutine-stack for internal coroutine-type
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         // placement new for internal coroutine
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         // create a stack-context
0601         stack_context stack_ctx;
0602         // allocate the coroutine-stack
0603         stack_alloc.allocate( stack_ctx, attrs.size);
0604         BOOST_ASSERT( 0 != stack_ctx.sp);
0605         // typedef of internal coroutine-type
0606         typedef symmetric_coroutine_object< void, coroutine_fn, StackAllocator > object_t;
0607         // reserve space on top of coroutine-stack for internal coroutine-type
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         // placement new for internal coroutine
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         // create a stack-context
0625         stack_context stack_ctx;
0626         // allocate the coroutine-stack
0627         stack_alloc.allocate( stack_ctx, attrs.size);
0628         BOOST_ASSERT( 0 != stack_ctx.sp);
0629         // typedef of internal coroutine-type
0630         typedef symmetric_coroutine_object< void, Fn, stack_allocator > object_t;
0631         // reserve space on top of coroutine-stack for internal coroutine-type
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         // placement new for internal coroutine
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         // create a stack-context
0649         stack_context stack_ctx;
0650         // allocate the coroutine-stack
0651         stack_alloc.allocate( stack_ctx, attrs.size);
0652         BOOST_ASSERT( 0 != stack_ctx.sp);
0653         // typedef of internal coroutine-type
0654         typedef symmetric_coroutine_object< void, Fn, StackAllocator > object_t;
0655         // reserve space on top of coroutine-stack for internal coroutine-type
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         // placement new for internal coroutine
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         // create a stack-context
0673         stack_context stack_ctx;
0674         // allocate the coroutine-stack
0675         stack_alloc.allocate( stack_ctx, attrs.size);
0676         BOOST_ASSERT( 0 != stack_ctx.sp);
0677         // typedef of internal coroutine-type
0678         typedef symmetric_coroutine_object< void, Fn, stack_allocator > object_t;
0679         // reserve space on top of coroutine-stack for internal coroutine-type
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         // placement new for internal coroutine
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         // create a stack-context
0697         stack_context stack_ctx;
0698         // allocate the coroutine-stack
0699         stack_alloc.allocate( stack_ctx, attrs.size);
0700         BOOST_ASSERT( 0 != stack_ctx.sp);
0701         // typedef of internal coroutine-type
0702         typedef symmetric_coroutine_object< void, Fn, StackAllocator > object_t;
0703         // reserve space on top of coroutine-stack for internal coroutine-type
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         // placement new for internal coroutine
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         // create a stack-context
0721         stack_context stack_ctx;
0722         // allocate the coroutine-stack
0723         stack_alloc.allocate( stack_ctx, attrs.size);
0724         BOOST_ASSERT( 0 != stack_ctx.sp);
0725         // typedef of internal coroutine-type
0726         typedef symmetric_coroutine_object< void, Fn, stack_allocator > object_t;
0727         // reserve space on top of coroutine-stack for internal coroutine-type
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         // placement new for internal coroutine
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         // create a stack-context
0745         stack_context stack_ctx;
0746         // allocate the coroutine-stack
0747         stack_alloc.allocate( stack_ctx, attrs.size);
0748         BOOST_ASSERT( 0 != stack_ctx.sp);
0749         // typedef of internal coroutine-type
0750         typedef symmetric_coroutine_object< void, Fn, StackAllocator > object_t;
0751         // reserve space on top of coroutine-stack for internal coroutine-type
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         // placement new for internal coroutine
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 // BOOST_COROUTINES_DETAIL_SYMMETRIC_COROUTINE_CALL_H