| |
| // Copyright Oliver Kowalke 2009. |
| // Distributed under the Boost Software License, Version 1.0. |
| // (See accompanying file LICENSE_1_0.txt or copy at |
| // http://www.boost.org/LICENSE_1_0.txt) |
| |
| #ifndef BOOST_COROUTINES_DETAIL_SYMMETRIC_COROUTINE_CALL_H |
| #define BOOST_COROUTINES_DETAIL_SYMMETRIC_COROUTINE_CALL_H |
| |
| #include <boost/assert.hpp> |
| #include <boost/config.hpp> |
| #include <boost/move/move.hpp> |
| #include <boost/utility/explicit_operator_bool.hpp> |
| |
| #include <boost/coroutine/attributes.hpp> |
| #include <boost/coroutine/detail/config.hpp> |
| #include <boost/coroutine/detail/symmetric_coroutine_impl.hpp> |
| #include <boost/coroutine/detail/symmetric_coroutine_object.hpp> |
| #include <boost/coroutine/detail/symmetric_coroutine_yield.hpp> |
| #include <boost/coroutine/stack_allocator.hpp> |
| #include <boost/coroutine/stack_context.hpp> |
| |
| #ifdef BOOST_HAS_ABI_HEADERS |
| # include BOOST_ABI_PREFIX |
| #endif |
| |
| namespace boost { |
| namespace coroutines { |
| namespace detail { |
| |
| template< typename Arg > |
| class symmetric_coroutine_call |
| { |
| private: |
| template< typename X > |
| friend class symmetric_coroutine_yield; |
| |
| typedef symmetric_coroutine_impl< Arg > impl_type; |
| |
| BOOST_MOVABLE_BUT_NOT_COPYABLE( symmetric_coroutine_call) |
| |
| struct dummy {}; |
| |
| impl_type * impl_; |
| |
| public: |
| typedef Arg value_type; |
| typedef symmetric_coroutine_yield< Arg > yield_type; |
| |
| symmetric_coroutine_call() BOOST_NOEXCEPT : |
| impl_( 0) |
| {} |
| |
| #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES |
| # ifdef BOOST_MSVC |
| typedef void ( * coroutine_fn)( yield_type &); |
| |
| explicit symmetric_coroutine_call( coroutine_fn fn, |
| attributes const& attrs = attributes(), |
| stack_allocator stack_alloc = stack_allocator() ) : |
| impl_( 0) |
| { |
| // create a stack-context |
| stack_context stack_ctx; |
| // allocate the coroutine-stack |
| stack_alloc.allocate( stack_ctx, attrs.size); |
| BOOST_ASSERT( 0 < stack_ctx.sp); |
| // typedef of internal coroutine-type |
| typedef symmetric_coroutine_object< Arg, coroutine_fn, stack_allocator > object_t; |
| // reserve space on top of coroutine-stack for internal coroutine-type |
| stack_context internal_stack_ctx; |
| internal_stack_ctx.sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t); |
| BOOST_ASSERT( 0 < internal_stack_ctx.sp); |
| internal_stack_ctx.size = stack_ctx.size - sizeof( object_t); |
| BOOST_ASSERT( 0 < internal_stack_ctx.size); |
| // placement new for internal coroutine |
| impl_ = new ( internal_stack_ctx.sp) object_t( |
| boost::forward< coroutine_fn >( fn), attrs, stack_ctx, internal_stack_ctx, stack_alloc); |
| BOOST_ASSERT( impl_); |
| } |
| |
| template< typename StackAllocator > |
| explicit symmetric_coroutine_call( coroutine_fn fn, |
| attributes const& attrs, |
| StackAllocator stack_alloc) : |
| impl_( 0) |
| { |
| // create a stack-context |
| stack_context stack_ctx; |
| // allocate the coroutine-stack |
| stack_alloc.allocate( stack_ctx, attrs.size); |
| BOOST_ASSERT( 0 < stack_ctx.sp); |
| // typedef of internal coroutine-type |
| typedef symmetric_coroutine_object< Arg, coroutine_fn, StackAllocator > object_t; |
| // reserve space on top of coroutine-stack for internal coroutine-type |
| stack_context internal_stack_ctx; |
| internal_stack_ctx.sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t); |
| BOOST_ASSERT( 0 < internal_stack_ctx.sp); |
| internal_stack_ctx.size = stack_ctx.size - sizeof( object_t); |
| BOOST_ASSERT( 0 < internal_stack_ctx.size); |
| // placement new for internal coroutine |
| impl_ = new ( internal_stack_ctx.sp) object_t( |
| boost::forward< coroutine_fn >( fn), attrs, stack_ctx, internal_stack_ctx, stack_alloc); |
| BOOST_ASSERT( impl_); |
| } |
| # endif |
| template< typename Fn > |
| explicit symmetric_coroutine_call( BOOST_RV_REF( Fn) fn, |
| attributes const& attrs = attributes(), |
| stack_allocator stack_alloc = stack_allocator() ) : |
| impl_( 0) |
| { |
| // create a stack-context |
| stack_context stack_ctx; |
| // allocate the coroutine-stack |
| stack_alloc.allocate( stack_ctx, attrs.size); |
| BOOST_ASSERT( 0 < stack_ctx.sp); |
| // typedef of internal coroutine-type |
| typedef symmetric_coroutine_object< Arg, Fn, stack_allocator > object_t; |
| // reserve space on top of coroutine-stack for internal coroutine-type |
| stack_context internal_stack_ctx; |
| internal_stack_ctx.sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t); |
| BOOST_ASSERT( 0 < internal_stack_ctx.sp); |
| internal_stack_ctx.size = stack_ctx.size - sizeof( object_t); |
| BOOST_ASSERT( 0 < internal_stack_ctx.size); |
| // placement new for internal coroutine |
| impl_ = new ( internal_stack_ctx.sp) object_t( |
| boost::forward< Fn >( fn), attrs, stack_ctx, internal_stack_ctx, stack_alloc); |
| BOOST_ASSERT( impl_); |
| } |
| |
| template< typename Fn, typename StackAllocator > |
| explicit symmetric_coroutine_call( BOOST_RV_REF( Fn) fn, |
| attributes const& attrs, |
| StackAllocator stack_alloc) : |
| impl_( 0) |
| { |
| // create a stack-context |
| stack_context stack_ctx; |
| // allocate the coroutine-stack |
| stack_alloc.allocate( stack_ctx, attrs.size); |
| BOOST_ASSERT( 0 < stack_ctx.sp); |
| // typedef of internal coroutine-type |
| typedef symmetric_coroutine_object< Arg, Fn, StackAllocator > object_t; |
| // reserve space on top of coroutine-stack for internal coroutine-type |
| stack_context internal_stack_ctx; |
| internal_stack_ctx.sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t); |
| BOOST_ASSERT( 0 < internal_stack_ctx.sp); |
| internal_stack_ctx.size = stack_ctx.size - sizeof( object_t); |
| BOOST_ASSERT( 0 < internal_stack_ctx.size); |
| // placement new for internal coroutine |
| impl_ = new ( internal_stack_ctx.sp) object_t( |
| boost::forward< Fn >( fn), attrs, stack_ctx, internal_stack_ctx, stack_alloc); |
| BOOST_ASSERT( impl_); |
| } |
| #else |
| template< typename Fn > |
| explicit symmetric_coroutine_call( Fn fn, |
| attributes const& attrs = attributes(), |
| stack_allocator stack_alloc = stack_allocator() ) : |
| impl_( 0) |
| { |
| // create a stack-context |
| stack_context stack_ctx; |
| // allocate the coroutine-stack |
| stack_alloc.allocate( stack_ctx, attrs.size); |
| BOOST_ASSERT( 0 < stack_ctx.sp); |
| // typedef of internal coroutine-type |
| typedef symmetric_coroutine_object< Arg, Fn, stack_allocator > object_t; |
| // reserve space on top of coroutine-stack for internal coroutine-type |
| stack_context internal_stack_ctx; |
| internal_stack_ctx.sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t); |
| BOOST_ASSERT( 0 < internal_stack_ctx.sp); |
| internal_stack_ctx.size = stack_ctx.size - sizeof( object_t); |
| BOOST_ASSERT( 0 < internal_stack_ctx.size); |
| // placement new for internal coroutine |
| impl_ = new ( internal_stack_ctx.sp) object_t( fn, attrs, stack_ctx, internal_stack_ctx, stack_alloc); |
| BOOST_ASSERT( impl_); |
| } |
| |
| template< typename Fn, typename StackAllocator > |
| explicit symmetric_coroutine_call( Fn fn, |
| attributes const& attrs, |
| StackAllocator stack_alloc) : |
| impl_( 0) |
| { |
| // create a stack-context |
| stack_context stack_ctx; |
| // allocate the coroutine-stack |
| stack_alloc.allocate( stack_ctx, attrs.size); |
| BOOST_ASSERT( 0 < stack_ctx.sp); |
| // typedef of internal coroutine-type |
| typedef symmetric_coroutine_object< Arg, Fn, StackAllocator > object_t; |
| // reserve space on top of coroutine-stack for internal coroutine-type |
| stack_context internal_stack_ctx; |
| internal_stack_ctx.sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t); |
| BOOST_ASSERT( 0 < internal_stack_ctx.sp); |
| internal_stack_ctx.size = stack_ctx.size - sizeof( object_t); |
| BOOST_ASSERT( 0 < internal_stack_ctx.size); |
| // placement new for internal coroutine |
| impl_ = new ( internal_stack_ctx.sp) object_t( fn, attrs, stack_ctx, internal_stack_ctx, stack_alloc); |
| BOOST_ASSERT( impl_); |
| } |
| |
| template< typename Fn > |
| explicit symmetric_coroutine_call( BOOST_RV_REF( Fn) fn, |
| attributes const& attrs = attributes(), |
| stack_allocator stack_alloc = stack_allocator() ) : |
| impl_( 0) |
| { |
| // create a stack-context |
| stack_context stack_ctx; |
| // allocate the coroutine-stack |
| stack_alloc.allocate( stack_ctx, attrs.size); |
| BOOST_ASSERT( 0 < stack_ctx.sp); |
| // typedef of internal coroutine-type |
| typedef symmetric_coroutine_object< Arg, Fn, stack_allocator > object_t; |
| // reserve space on top of coroutine-stack for internal coroutine-type |
| stack_context internal_stack_ctx; |
| internal_stack_ctx.sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t); |
| BOOST_ASSERT( 0 < internal_stack_ctx.sp); |
| internal_stack_ctx.size = stack_ctx.size - sizeof( object_t); |
| BOOST_ASSERT( 0 < internal_stack_ctx.size); |
| // placement new for internal coroutine |
| impl_ = new ( internal_stack_ctx.sp) object_t( fn, attrs, stack_ctx, internal_stack_ctx, stack_alloc); |
| BOOST_ASSERT( impl_); |
| } |
| |
| template< typename Fn, typename StackAllocator > |
| explicit symmetric_coroutine_call( BOOST_RV_REF( Fn) fn, |
| attributes const& attrs, |
| StackAllocator stack_alloc) : |
| impl_( 0) |
| { |
| // create a stack-context |
| stack_context stack_ctx; |
| // allocate the coroutine-stack |
| stack_alloc.allocate( stack_ctx, attrs.size); |
| BOOST_ASSERT( 0 < stack_ctx.sp); |
| // typedef of internal coroutine-type |
| typedef symmetric_coroutine_object< Arg, Fn, StackAllocator > object_t; |
| // reserve space on top of coroutine-stack for internal coroutine-type |
| stack_context internal_stack_ctx; |
| internal_stack_ctx.sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t); |
| BOOST_ASSERT( 0 < internal_stack_ctx.sp); |
| internal_stack_ctx.size = stack_ctx.size - sizeof( object_t); |
| BOOST_ASSERT( 0 < internal_stack_ctx.size); |
| // placement new for internal coroutine |
| impl_ = new ( internal_stack_ctx.sp) object_t( fn, attrs, stack_ctx, internal_stack_ctx, stack_alloc); |
| BOOST_ASSERT( impl_); |
| } |
| #endif |
| |
| ~symmetric_coroutine_call() |
| { |
| if ( 0 != impl_) |
| { |
| impl_->destroy(); |
| impl_ = 0; |
| } |
| } |
| |
| symmetric_coroutine_call( BOOST_RV_REF( symmetric_coroutine_call) other) BOOST_NOEXCEPT : |
| impl_( 0) |
| { swap( other); } |
| |
| symmetric_coroutine_call & operator=( BOOST_RV_REF( symmetric_coroutine_call) other) BOOST_NOEXCEPT |
| { |
| symmetric_coroutine_call tmp( boost::move( other) ); |
| swap( tmp); |
| return * this; |
| } |
| |
| BOOST_EXPLICIT_OPERATOR_BOOL(); |
| |
| bool operator!() const BOOST_NOEXCEPT |
| { return 0 == impl_ || impl_->is_complete() || impl_->is_running(); } |
| |
| void swap( symmetric_coroutine_call & other) BOOST_NOEXCEPT |
| { std::swap( impl_, other.impl_); } |
| |
| symmetric_coroutine_call & operator()( Arg arg) BOOST_NOEXCEPT |
| { |
| BOOST_ASSERT( * this); |
| |
| impl_->resume( arg); |
| return * this; |
| } |
| }; |
| |
| template< typename Arg > |
| class symmetric_coroutine_call< Arg & > |
| { |
| private: |
| template< typename X > |
| friend class symmetric_coroutine_yield; |
| |
| typedef symmetric_coroutine_impl< Arg & > impl_type; |
| |
| BOOST_MOVABLE_BUT_NOT_COPYABLE( symmetric_coroutine_call) |
| |
| struct dummy {}; |
| |
| impl_type * impl_; |
| |
| public: |
| typedef Arg value_type; |
| typedef symmetric_coroutine_yield< Arg & > yield_type; |
| |
| symmetric_coroutine_call() BOOST_NOEXCEPT : |
| impl_( 0) |
| {} |
| |
| #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES |
| # ifdef BOOST_MSVC |
| typedef void ( * coroutine_fn)( yield_type &); |
| |
| explicit symmetric_coroutine_call( coroutine_fn fn, |
| attributes const& attrs = attributes(), |
| stack_allocator stack_alloc = stack_allocator() ) : |
| impl_( 0) |
| { |
| // create a stack-context |
| stack_context stack_ctx; |
| // allocate the coroutine-stack |
| stack_alloc.allocate( stack_ctx, attrs.size); |
| BOOST_ASSERT( 0 < stack_ctx.sp); |
| // typedef of internal coroutine-type |
| typedef symmetric_coroutine_object< Arg &, coroutine_fn, stack_allocator > object_t; |
| // reserve space on top of coroutine-stack for internal coroutine-type |
| stack_context internal_stack_ctx; |
| internal_stack_ctx.sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t); |
| BOOST_ASSERT( 0 < internal_stack_ctx.sp); |
| internal_stack_ctx.size = stack_ctx.size - sizeof( object_t); |
| BOOST_ASSERT( 0 < internal_stack_ctx.size); |
| // placement new for internal coroutine |
| impl_ = new ( internal_stack_ctx.sp) object_t( |
| boost::forward< coroutine_fn >( fn), attrs, stack_ctx, internal_stack_ctx, stack_alloc); |
| BOOST_ASSERT( impl_); |
| } |
| |
| template< typename StackAllocator > |
| explicit symmetric_coroutine_call( coroutine_fn fn, |
| attributes const& attrs, |
| StackAllocator stack_alloc) : |
| impl_( 0) |
| { |
| // create a stack-context |
| stack_context stack_ctx; |
| // allocate the coroutine-stack |
| stack_alloc.allocate( stack_ctx, attrs.size); |
| BOOST_ASSERT( 0 < stack_ctx.sp); |
| // typedef of internal coroutine-type |
| typedef symmetric_coroutine_object< Arg &, coroutine_fn, StackAllocator > object_t; |
| // reserve space on top of coroutine-stack for internal coroutine-type |
| stack_context internal_stack_ctx; |
| internal_stack_ctx.sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t); |
| BOOST_ASSERT( 0 < internal_stack_ctx.sp); |
| internal_stack_ctx.size = stack_ctx.size - sizeof( object_t); |
| BOOST_ASSERT( 0 < internal_stack_ctx.size); |
| // placement new for internal coroutine |
| impl_ = new ( internal_stack_ctx.sp) object_t( |
| boost::forward< coroutine_fn >( fn), attrs, stack_ctx, internal_stack_ctx, stack_alloc); |
| BOOST_ASSERT( impl_); |
| } |
| # endif |
| template< typename Fn > |
| explicit symmetric_coroutine_call( BOOST_RV_REF( Fn) fn, |
| attributes const& attrs = attributes(), |
| stack_allocator stack_alloc = stack_allocator() ) : |
| impl_( 0) |
| { |
| // create a stack-context |
| stack_context stack_ctx; |
| // allocate the coroutine-stack |
| stack_alloc.allocate( stack_ctx, attrs.size); |
| BOOST_ASSERT( 0 < stack_ctx.sp); |
| // typedef of internal coroutine-type |
| typedef symmetric_coroutine_object< Arg &, Fn, stack_allocator > object_t; |
| // reserve space on top of coroutine-stack for internal coroutine-type |
| stack_context internal_stack_ctx; |
| internal_stack_ctx.sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t); |
| BOOST_ASSERT( 0 < internal_stack_ctx.sp); |
| internal_stack_ctx.size = stack_ctx.size - sizeof( object_t); |
| BOOST_ASSERT( 0 < internal_stack_ctx.size); |
| // placement new for internal coroutine |
| impl_ = new ( internal_stack_ctx.sp) object_t( |
| boost::forward< Fn >( fn), attrs, stack_ctx, internal_stack_ctx, stack_alloc); |
| BOOST_ASSERT( impl_); |
| } |
| |
| template< typename Fn, typename StackAllocator > |
| explicit symmetric_coroutine_call( BOOST_RV_REF( Fn) fn, |
| attributes const& attrs, |
| StackAllocator stack_alloc) : |
| impl_( 0) |
| { |
| // create a stack-context |
| stack_context stack_ctx; |
| // allocate the coroutine-stack |
| stack_alloc.allocate( stack_ctx, attrs.size); |
| BOOST_ASSERT( 0 < stack_ctx.sp); |
| // typedef of internal coroutine-type |
| typedef symmetric_coroutine_object< Arg &, Fn, StackAllocator > object_t; |
| // reserve space on top of coroutine-stack for internal coroutine-type |
| stack_context internal_stack_ctx; |
| internal_stack_ctx.sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t); |
| BOOST_ASSERT( 0 < internal_stack_ctx.sp); |
| internal_stack_ctx.size = stack_ctx.size - sizeof( object_t); |
| BOOST_ASSERT( 0 < internal_stack_ctx.size); |
| // placement new for internal coroutine |
| impl_ = new ( internal_stack_ctx.sp) object_t( |
| boost::forward< Fn >( fn), attrs, stack_ctx, internal_stack_ctx, stack_alloc); |
| BOOST_ASSERT( impl_); |
| } |
| #else |
| template< typename Fn > |
| explicit symmetric_coroutine_call( Fn fn, |
| attributes const& attrs = attributes(), |
| stack_allocator stack_alloc = stack_allocator() ) : |
| impl_( 0) |
| { |
| // create a stack-context |
| stack_context stack_ctx; |
| // allocate the coroutine-stack |
| stack_alloc.allocate( stack_ctx, attrs.size); |
| BOOST_ASSERT( 0 < stack_ctx.sp); |
| // typedef of internal coroutine-type |
| typedef symmetric_coroutine_object< Arg &, Fn, stack_allocator > object_t; |
| // reserve space on top of coroutine-stack for internal coroutine-type |
| stack_context internal_stack_ctx; |
| internal_stack_ctx.sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t); |
| BOOST_ASSERT( 0 < internal_stack_ctx.sp); |
| internal_stack_ctx.size = stack_ctx.size - sizeof( object_t); |
| BOOST_ASSERT( 0 < internal_stack_ctx.size); |
| // placement new for internal coroutine |
| impl_ = new ( internal_stack_ctx.sp) object_t( fn, attrs, stack_ctx, internal_stack_ctx, stack_alloc); |
| BOOST_ASSERT( impl_); |
| } |
| |
| template< typename Fn, typename StackAllocator > |
| explicit symmetric_coroutine_call( Fn fn, |
| attributes const& attrs, |
| StackAllocator stack_alloc) : |
| impl_( 0) |
| { |
| // create a stack-context |
| stack_context stack_ctx; |
| // allocate the coroutine-stack |
| stack_alloc.allocate( stack_ctx, attrs.size); |
| BOOST_ASSERT( 0 < stack_ctx.sp); |
| // typedef of internal coroutine-type |
| typedef symmetric_coroutine_object< Arg &, Fn, StackAllocator > object_t; |
| // reserve space on top of coroutine-stack for internal coroutine-type |
| stack_context internal_stack_ctx; |
| internal_stack_ctx.sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t); |
| BOOST_ASSERT( 0 < internal_stack_ctx.sp); |
| internal_stack_ctx.size = stack_ctx.size - sizeof( object_t); |
| BOOST_ASSERT( 0 < internal_stack_ctx.size); |
| // placement new for internal coroutine |
| impl_ = new ( internal_stack_ctx.sp) object_t( fn, attrs, stack_ctx, internal_stack_ctx, stack_alloc); |
| BOOST_ASSERT( impl_); |
| } |
| |
| template< typename Fn > |
| explicit symmetric_coroutine_call( BOOST_RV_REF( Fn) fn, |
| attributes const& attrs = attributes(), |
| stack_allocator stack_alloc = stack_allocator() ) : |
| impl_( 0) |
| { |
| // create a stack-context |
| stack_context stack_ctx; |
| // allocate the coroutine-stack |
| stack_alloc.allocate( stack_ctx, attrs.size); |
| BOOST_ASSERT( 0 < stack_ctx.sp); |
| // typedef of internal coroutine-type |
| typedef symmetric_coroutine_object< Arg &, Fn, stack_allocator > object_t; |
| // reserve space on top of coroutine-stack for internal coroutine-type |
| stack_context internal_stack_ctx; |
| internal_stack_ctx.sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t); |
| BOOST_ASSERT( 0 < internal_stack_ctx.sp); |
| internal_stack_ctx.size = stack_ctx.size - sizeof( object_t); |
| BOOST_ASSERT( 0 < internal_stack_ctx.size); |
| // placement new for internal coroutine |
| impl_ = new ( internal_stack_ctx.sp) object_t( fn, attrs, stack_ctx, internal_stack_ctx, stack_alloc); |
| BOOST_ASSERT( impl_); |
| } |
| |
| template< typename Fn, typename StackAllocator > |
| explicit symmetric_coroutine_call( BOOST_RV_REF( Fn) fn, |
| attributes const& attrs, |
| StackAllocator stack_alloc) : |
| impl_( 0) |
| { |
| // create a stack-context |
| stack_context stack_ctx; |
| // allocate the coroutine-stack |
| stack_alloc.allocate( stack_ctx, attrs.size); |
| BOOST_ASSERT( 0 < stack_ctx.sp); |
| // typedef of internal coroutine-type |
| typedef symmetric_coroutine_object< Arg &, Fn, StackAllocator > object_t; |
| // reserve space on top of coroutine-stack for internal coroutine-type |
| stack_context internal_stack_ctx; |
| internal_stack_ctx.sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t); |
| BOOST_ASSERT( 0 < internal_stack_ctx.sp); |
| internal_stack_ctx.size = stack_ctx.size - sizeof( object_t); |
| BOOST_ASSERT( 0 < internal_stack_ctx.size); |
| // placement new for internal coroutine |
| impl_ = new ( internal_stack_ctx.sp) object_t( fn, attrs, stack_ctx, internal_stack_ctx, stack_alloc); |
| BOOST_ASSERT( impl_); |
| } |
| #endif |
| |
| ~symmetric_coroutine_call() |
| { |
| if ( 0 != impl_) |
| { |
| impl_->destroy(); |
| impl_ = 0; |
| } |
| } |
| |
| symmetric_coroutine_call( BOOST_RV_REF( symmetric_coroutine_call) other) BOOST_NOEXCEPT : |
| impl_( 0) |
| { swap( other); } |
| |
| symmetric_coroutine_call & operator=( BOOST_RV_REF( symmetric_coroutine_call) other) BOOST_NOEXCEPT |
| { |
| symmetric_coroutine_call tmp( boost::move( other) ); |
| swap( tmp); |
| return * this; |
| } |
| |
| BOOST_EXPLICIT_OPERATOR_BOOL(); |
| |
| bool operator!() const BOOST_NOEXCEPT |
| { return 0 == impl_ || impl_->is_complete() || impl_->is_running(); } |
| |
| void swap( symmetric_coroutine_call & other) BOOST_NOEXCEPT |
| { std::swap( impl_, other.impl_); } |
| |
| symmetric_coroutine_call & operator()( Arg & arg) BOOST_NOEXCEPT |
| { |
| BOOST_ASSERT( * this); |
| |
| impl_->resume( arg); |
| return * this; |
| } |
| }; |
| |
| template<> |
| class symmetric_coroutine_call< void > |
| { |
| private: |
| template< typename X > |
| friend class symmetric_coroutine_yield; |
| |
| typedef symmetric_coroutine_impl< void > impl_type; |
| |
| BOOST_MOVABLE_BUT_NOT_COPYABLE( symmetric_coroutine_call) |
| |
| struct dummy {}; |
| |
| impl_type * impl_; |
| |
| public: |
| typedef void value_type; |
| typedef symmetric_coroutine_yield< void > yield_type; |
| |
| symmetric_coroutine_call() BOOST_NOEXCEPT : |
| impl_( 0) |
| {} |
| |
| #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES |
| # ifdef BOOST_MSVC |
| typedef void ( * coroutine_fn)( yield_type &); |
| |
| explicit symmetric_coroutine_call( coroutine_fn fn, |
| attributes const& attrs = attributes(), |
| stack_allocator stack_alloc = stack_allocator() ) : |
| impl_( 0) |
| { |
| // create a stack-context |
| stack_context stack_ctx; |
| // allocate the coroutine-stack |
| stack_alloc.allocate( stack_ctx, attrs.size); |
| BOOST_ASSERT( 0 < stack_ctx.sp); |
| // typedef of internal coroutine-type |
| typedef symmetric_coroutine_object< void, coroutine_fn, stack_allocator > object_t; |
| // reserve space on top of coroutine-stack for internal coroutine-type |
| stack_context internal_stack_ctx; |
| internal_stack_ctx.sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t); |
| BOOST_ASSERT( 0 < internal_stack_ctx.sp); |
| internal_stack_ctx.size = stack_ctx.size - sizeof( object_t); |
| BOOST_ASSERT( 0 < internal_stack_ctx.size); |
| // placement new for internal coroutine |
| impl_ = new ( internal_stack_ctx.sp) object_t( |
| boost::forward< coroutine_fn >( fn), attrs, stack_ctx, internal_stack_ctx, stack_alloc); |
| BOOST_ASSERT( impl_); |
| } |
| |
| template< typename StackAllocator > |
| explicit symmetric_coroutine_call( coroutine_fn fn, |
| attributes const& attrs, |
| StackAllocator stack_alloc) : |
| impl_( 0) |
| { |
| // create a stack-context |
| stack_context stack_ctx; |
| // allocate the coroutine-stack |
| stack_alloc.allocate( stack_ctx, attrs.size); |
| BOOST_ASSERT( 0 < stack_ctx.sp); |
| // typedef of internal coroutine-type |
| typedef symmetric_coroutine_object< void, coroutine_fn, StackAllocator > object_t; |
| // reserve space on top of coroutine-stack for internal coroutine-type |
| stack_context internal_stack_ctx; |
| internal_stack_ctx.sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t); |
| BOOST_ASSERT( 0 < internal_stack_ctx.sp); |
| internal_stack_ctx.size = stack_ctx.size - sizeof( object_t); |
| BOOST_ASSERT( 0 < internal_stack_ctx.size); |
| // placement new for internal coroutine |
| impl_ = new ( internal_stack_ctx.sp) object_t( |
| boost::forward< coroutine_fn >( fn), attrs, stack_ctx, internal_stack_ctx, stack_alloc); |
| BOOST_ASSERT( impl_); |
| } |
| # endif |
| template< typename Fn > |
| explicit symmetric_coroutine_call( BOOST_RV_REF( Fn) fn, |
| attributes const& attrs = attributes(), |
| stack_allocator stack_alloc = stack_allocator() ) : |
| impl_( 0) |
| { |
| // create a stack-context |
| stack_context stack_ctx; |
| // allocate the coroutine-stack |
| stack_alloc.allocate( stack_ctx, attrs.size); |
| BOOST_ASSERT( 0 < stack_ctx.sp); |
| // typedef of internal coroutine-type |
| typedef symmetric_coroutine_object< void, Fn, stack_allocator > object_t; |
| // reserve space on top of coroutine-stack for internal coroutine-type |
| stack_context internal_stack_ctx; |
| internal_stack_ctx.sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t); |
| BOOST_ASSERT( 0 < internal_stack_ctx.sp); |
| internal_stack_ctx.size = stack_ctx.size - sizeof( object_t); |
| BOOST_ASSERT( 0 < internal_stack_ctx.size); |
| // placement new for internal coroutine |
| impl_ = new ( internal_stack_ctx.sp) object_t( |
| boost::forward< Fn >( fn), attrs, stack_ctx, internal_stack_ctx, stack_alloc); |
| BOOST_ASSERT( impl_); |
| } |
| |
| template< typename Fn, typename StackAllocator > |
| explicit symmetric_coroutine_call( BOOST_RV_REF( Fn) fn, |
| attributes const& attrs, |
| StackAllocator stack_alloc) : |
| impl_( 0) |
| { |
| // create a stack-context |
| stack_context stack_ctx; |
| // allocate the coroutine-stack |
| stack_alloc.allocate( stack_ctx, attrs.size); |
| BOOST_ASSERT( 0 < stack_ctx.sp); |
| // typedef of internal coroutine-type |
| typedef symmetric_coroutine_object< void, Fn, StackAllocator > object_t; |
| // reserve space on top of coroutine-stack for internal coroutine-type |
| stack_context internal_stack_ctx; |
| internal_stack_ctx.sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t); |
| BOOST_ASSERT( 0 < internal_stack_ctx.sp); |
| internal_stack_ctx.size = stack_ctx.size - sizeof( object_t); |
| BOOST_ASSERT( 0 < internal_stack_ctx.size); |
| // placement new for internal coroutine |
| impl_ = new ( internal_stack_ctx.sp) object_t( |
| boost::forward< Fn >( fn), attrs, stack_ctx, internal_stack_ctx, stack_alloc); |
| BOOST_ASSERT( impl_); |
| } |
| #else |
| template< typename Fn > |
| explicit symmetric_coroutine_call( Fn fn, |
| attributes const& attrs = attributes(), |
| stack_allocator stack_alloc = stack_allocator() ) : |
| impl_( 0) |
| { |
| // create a stack-context |
| stack_context stack_ctx; |
| // allocate the coroutine-stack |
| stack_alloc.allocate( stack_ctx, attrs.size); |
| BOOST_ASSERT( 0 < stack_ctx.sp); |
| // typedef of internal coroutine-type |
| typedef symmetric_coroutine_object< void, Fn, stack_allocator > object_t; |
| // reserve space on top of coroutine-stack for internal coroutine-type |
| stack_context internal_stack_ctx; |
| internal_stack_ctx.sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t); |
| BOOST_ASSERT( 0 < internal_stack_ctx.sp); |
| internal_stack_ctx.size = stack_ctx.size - sizeof( object_t); |
| BOOST_ASSERT( 0 < internal_stack_ctx.size); |
| // placement new for internal coroutine |
| impl_ = new ( internal_stack_ctx.sp) object_t( fn, attrs, stack_ctx, internal_stack_ctx, stack_alloc); |
| BOOST_ASSERT( impl_); |
| } |
| |
| template< typename Fn, typename StackAllocator > |
| explicit symmetric_coroutine_call( Fn fn, |
| attributes const& attrs, |
| StackAllocator stack_alloc) : |
| impl_( 0) |
| { |
| // create a stack-context |
| stack_context stack_ctx; |
| // allocate the coroutine-stack |
| stack_alloc.allocate( stack_ctx, attrs.size); |
| BOOST_ASSERT( 0 < stack_ctx.sp); |
| // typedef of internal coroutine-type |
| typedef symmetric_coroutine_object< void, Fn, StackAllocator > object_t; |
| // reserve space on top of coroutine-stack for internal coroutine-type |
| stack_context internal_stack_ctx; |
| internal_stack_ctx.sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t); |
| BOOST_ASSERT( 0 < internal_stack_ctx.sp); |
| internal_stack_ctx.size = stack_ctx.size - sizeof( object_t); |
| BOOST_ASSERT( 0 < internal_stack_ctx.size); |
| // placement new for internal coroutine |
| impl_ = new ( internal_stack_ctx.sp) object_t( fn, attrs, stack_ctx, internal_stack_ctx, stack_alloc); |
| BOOST_ASSERT( impl_); |
| } |
| |
| template< typename Fn > |
| explicit symmetric_coroutine_call( BOOST_RV_REF( Fn) fn, |
| attributes const& attrs = attributes(), |
| stack_allocator stack_alloc = stack_allocator() ) : |
| impl_( 0) |
| { |
| // create a stack-context |
| stack_context stack_ctx; |
| // allocate the coroutine-stack |
| stack_alloc.allocate( stack_ctx, attrs.size); |
| BOOST_ASSERT( 0 < stack_ctx.sp); |
| // typedef of internal coroutine-type |
| typedef symmetric_coroutine_object< void, Fn, stack_allocator > object_t; |
| // reserve space on top of coroutine-stack for internal coroutine-type |
| stack_context internal_stack_ctx; |
| internal_stack_ctx.sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t); |
| BOOST_ASSERT( 0 < internal_stack_ctx.sp); |
| internal_stack_ctx.size = stack_ctx.size - sizeof( object_t); |
| BOOST_ASSERT( 0 < internal_stack_ctx.size); |
| // placement new for internal coroutine |
| impl_ = new ( internal_stack_ctx.sp) object_t( fn, attrs, stack_ctx, internal_stack_ctx, stack_alloc); |
| BOOST_ASSERT( impl_); |
| } |
| |
| template< typename Fn, typename StackAllocator > |
| explicit symmetric_coroutine_call( BOOST_RV_REF( Fn) fn, |
| attributes const& attrs, |
| StackAllocator stack_alloc) : |
| impl_( 0) |
| { |
| // create a stack-context |
| stack_context stack_ctx; |
| // allocate the coroutine-stack |
| stack_alloc.allocate( stack_ctx, attrs.size); |
| BOOST_ASSERT( 0 < stack_ctx.sp); |
| // typedef of internal coroutine-type |
| typedef symmetric_coroutine_object< void, Fn, StackAllocator > object_t; |
| // reserve space on top of coroutine-stack for internal coroutine-type |
| stack_context internal_stack_ctx; |
| internal_stack_ctx.sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t); |
| BOOST_ASSERT( 0 < internal_stack_ctx.sp); |
| internal_stack_ctx.size = stack_ctx.size - sizeof( object_t); |
| BOOST_ASSERT( 0 < internal_stack_ctx.size); |
| // placement new for internal coroutine |
| impl_ = new ( internal_stack_ctx.sp) object_t( fn, attrs, stack_ctx, internal_stack_ctx, stack_alloc); |
| BOOST_ASSERT( impl_); |
| } |
| #endif |
| |
| ~symmetric_coroutine_call() |
| { |
| if ( 0 != impl_) |
| { |
| impl_->destroy(); |
| impl_ = 0; |
| } |
| } |
| |
| inline symmetric_coroutine_call( BOOST_RV_REF( symmetric_coroutine_call) other) BOOST_NOEXCEPT : |
| impl_( 0) |
| { swap( other); } |
| |
| inline symmetric_coroutine_call & operator=( BOOST_RV_REF( symmetric_coroutine_call) other) BOOST_NOEXCEPT |
| { |
| symmetric_coroutine_call tmp( boost::move( other) ); |
| swap( tmp); |
| return * this; |
| } |
| |
| BOOST_EXPLICIT_OPERATOR_BOOL(); |
| |
| inline bool operator!() const BOOST_NOEXCEPT |
| { return 0 == impl_ || impl_->is_complete() || impl_->is_running(); } |
| |
| inline void swap( symmetric_coroutine_call & other) BOOST_NOEXCEPT |
| { std::swap( impl_, other.impl_); } |
| |
| inline symmetric_coroutine_call & operator()() BOOST_NOEXCEPT |
| { |
| BOOST_ASSERT( * this); |
| |
| impl_->resume(); |
| return * this; |
| } |
| }; |
| |
| template< typename Arg > |
| void swap( symmetric_coroutine_call< Arg > & l, |
| symmetric_coroutine_call< Arg > & r) |
| { l.swap( r); } |
| |
| }}} |
| |
| #ifdef BOOST_HAS_ABI_HEADERS |
| # include BOOST_ABI_SUFFIX |
| #endif |
| |
| #endif // BOOST_COROUTINES_DETAIL_SYMMETRIC_COROUTINE_CALL_H |