diff options
Diffstat (limited to 'boost/coroutine2/detail/pull_control_block.ipp')
-rw-r--r-- | boost/coroutine2/detail/pull_control_block.ipp | 221 |
1 files changed, 131 insertions, 90 deletions
diff --git a/boost/coroutine2/detail/pull_control_block.ipp b/boost/coroutine2/detail/pull_control_block.ipp index fd806ecb21..536e5e6a94 100644 --- a/boost/coroutine2/detail/pull_control_block.ipp +++ b/boost/coroutine2/detail/pull_control_block.ipp @@ -8,6 +8,7 @@ #define BOOST_COROUTINES2_DETAIL_PULL_CONTROL_BLOCK_IPP #include <exception> +#include <memory> #include <boost/assert.hpp> #include <boost/config.hpp> @@ -33,42 +34,46 @@ template< typename StackAllocator, typename Fn > pull_coroutine< T >::control_block::control_block( context::preallocated palloc, StackAllocator salloc, Fn && fn_, bool preserve_fpu_) : other( nullptr), - caller( boost::context::execution_context::current() ), - callee( palloc, salloc, - [=,fn=std::forward< Fn >( fn_)] () mutable -> decltype( auto) { - // create synthesized push_coroutine< T > - typename push_coroutine< T >::control_block synthesized_cb( this); - push_coroutine< T > synthesized( & synthesized_cb); - other = & synthesized_cb; - try { - // call coroutine-fn with synthesized push_coroutine as argument - fn( synthesized); - } catch ( forced_unwind const&) { - // do nothing for unwinding exception - } catch (...) { - // store other exceptions in exception-pointer - except = std::current_exception(); - } - // set termination flags - state |= static_cast< int >( state_t::complete); - // jump back to caller - caller( preserve_fpu); - BOOST_ASSERT_MSG( false, "pull_coroutine is complete"); - }), + ctx( std::allocator_arg, palloc, salloc, + [=,fn=std::forward< Fn >( fn_),ctx=boost::context::execution_context::current()] (void *) mutable -> void { + // create synthesized push_coroutine< T > + typename push_coroutine< T >::control_block synthesized_cb( this, ctx); + push_coroutine< T > synthesized( & synthesized_cb); + other = & synthesized_cb; + try { + // call coroutine-fn with synthesized push_coroutine as argument + fn( synthesized); + } catch ( forced_unwind const&) { + // do nothing for unwinding exception + } catch (...) { + // store other exceptions in exception-pointer + except = std::current_exception(); + } + // set termination flags + state |= static_cast< int >( state_t::complete); + // jump back to ctx + other->ctx( nullptr, preserve_fpu); + BOOST_ASSERT_MSG( false, "pull_coroutine is complete"); + }), preserve_fpu( preserve_fpu_), state( static_cast< int >( state_t::unwind) ), - except() { - callee( preserve_fpu); + except(), + bvalid( false), + storage() { + // enter coroutine-fn in order to have first value available after ctor (of `*this`) returns + set( reinterpret_cast< T * >( ctx( nullptr, preserve_fpu) ) ); } template< typename T > -pull_coroutine< T >::control_block::control_block( typename push_coroutine< T >::control_block * cb) : +pull_coroutine< T >::control_block::control_block( typename push_coroutine< T >::control_block * cb, + boost::context::execution_context const& ctx_) : other( cb), - caller( other->callee), - callee( other->caller), + ctx( ctx_), preserve_fpu( other->preserve_fpu), state( 0), - except() { + except(), + bvalid( false), + storage() { } template< typename T > @@ -77,14 +82,19 @@ pull_coroutine< T >::control_block::~control_block() { 0 != ( state & static_cast< int >( state_t::unwind) ) ) { // set early-exit flag state |= static_cast< int >( state_t::early_exit); - callee( preserve_fpu); + ctx( nullptr, preserve_fpu); + } + // destroy data if it set + if ( bvalid) { + reinterpret_cast< T const* >( storage)->~T(); } } template< typename T > void pull_coroutine< T >::control_block::resume() { - callee( preserve_fpu); + other->ctx = boost::context::execution_context::current(); + set( reinterpret_cast< T * >( ctx( nullptr, preserve_fpu) ) ); if ( except) { std::rethrow_exception( except); } @@ -95,9 +105,30 @@ pull_coroutine< T >::control_block::resume() { } template< typename T > +void +pull_coroutine< T >::control_block::set( T * t) { + // destroy data if it set + if ( bvalid) { + reinterpret_cast< T const* >( storage)->~T(); + } + if ( nullptr != t) { + new ( storage) T( std::move( * t) ); // FIXME: differrentiation between move/copy + bvalid = true; + } else { + bvalid = false; + } +} + +template< typename T > +T & +pull_coroutine< T >::control_block::get() { + return * reinterpret_cast< T * >( storage); +} + +template< typename T > bool pull_coroutine< T >::control_block::valid() const noexcept { - return nullptr != other && nullptr != other->t && 0 == ( state & static_cast< int >( state_t::complete) ); + return nullptr != other && 0 == ( state & static_cast< int >( state_t::complete) ) && bvalid; } @@ -108,42 +139,44 @@ template< typename StackAllocator, typename Fn > pull_coroutine< T & >::control_block::control_block( context::preallocated palloc, StackAllocator salloc, Fn && fn_, bool preserve_fpu_) : other( nullptr), - caller( boost::context::execution_context::current() ), - callee( palloc, salloc, - [=,fn=std::forward< Fn >( fn_)] () mutable -> decltype( auto) { - // create synthesized push_coroutine< T > - typename push_coroutine< T & >::control_block synthesized_cb( this); - push_coroutine< T & > synthesized( & synthesized_cb); - other = & synthesized_cb; - try { - // call coroutine-fn with synthesized push_coroutine as argument - fn( synthesized); - } catch ( forced_unwind const&) { - // do nothing for unwinding exception - } catch (...) { - // store other exceptions in exception-pointer - except = std::current_exception(); - } - // set termination flags - state |= static_cast< int >( state_t::complete); - // jump back to caller - caller( preserve_fpu); - BOOST_ASSERT_MSG( false, "pull_coroutine is complete"); - }), + ctx( std::allocator_arg, palloc, salloc, + [=,fn=std::forward< Fn >( fn_),ctx=boost::context::execution_context::current()] (void *) mutable -> void { + // create synthesized push_coroutine< T > + typename push_coroutine< T & >::control_block synthesized_cb( this, ctx); + push_coroutine< T & > synthesized( & synthesized_cb); + other = & synthesized_cb; + try { + // call coroutine-fn with synthesized push_coroutine as argument + fn( synthesized); + } catch ( forced_unwind const&) { + // do nothing for unwinding exception + } catch (...) { + // store other exceptions in exception-pointer + except = std::current_exception(); + } + // set termination flags + state |= static_cast< int >( state_t::complete); + // jump back to ctx + other->ctx( nullptr, preserve_fpu); + BOOST_ASSERT_MSG( false, "pull_coroutine is complete"); + }), preserve_fpu( preserve_fpu_), state( static_cast< int >( state_t::unwind) ), - except() { - callee( preserve_fpu); + except(), + t( nullptr) { + // enter coroutine-fn in order to have first value available after ctor (of `*this`) returns + t = reinterpret_cast< T * >( ctx( nullptr, preserve_fpu) ); } template< typename T > -pull_coroutine< T & >::control_block::control_block( typename push_coroutine< T & >::control_block * cb) : +pull_coroutine< T & >::control_block::control_block( typename push_coroutine< T & >::control_block * cb, + boost::context::execution_context const& ctx_) : other( cb), - caller( other->callee), - callee( other->caller), + ctx( ctx_), preserve_fpu( other->preserve_fpu), state( 0), - except() { + except(), + t( nullptr) { } template< typename T > @@ -152,14 +185,15 @@ pull_coroutine< T & >::control_block::~control_block() { 0 != ( state & static_cast< int >( state_t::unwind) ) ) { // set early-exit flag state |= static_cast< int >( state_t::early_exit); - callee( preserve_fpu); + ctx( nullptr, preserve_fpu); } } template< typename T > void pull_coroutine< T & >::control_block::resume() { - callee( preserve_fpu); + other->ctx = boost::context::execution_context::current(); + t = reinterpret_cast< T * >( ctx( nullptr, preserve_fpu) ); if ( except) { std::rethrow_exception( except); } @@ -170,9 +204,15 @@ pull_coroutine< T & >::control_block::resume() { } template< typename T > +T & +pull_coroutine< T & >::control_block::get() { + return * reinterpret_cast< T * >( t); +} + +template< typename T > bool pull_coroutine< T & >::control_block::valid() const noexcept { - return nullptr != other && nullptr != other->t && 0 == ( state & static_cast< int >( state_t::complete) ); + return nullptr != other && 0 == ( state & static_cast< int >( state_t::complete) ) && nullptr != t; } @@ -182,39 +222,39 @@ template< typename StackAllocator, typename Fn > pull_coroutine< void >::control_block::control_block( context::preallocated palloc, StackAllocator salloc, Fn && fn_, bool preserve_fpu_) : other( nullptr), - caller( boost::context::execution_context::current() ), - callee( palloc, salloc, - [=,fn=std::forward< Fn >( fn_)] () mutable -> decltype( auto) { - // create synthesized push_coroutine< T > - typename push_coroutine< void >::control_block synthesized_cb( this); - push_coroutine< void > synthesized( & synthesized_cb); - other = & synthesized_cb; - try { - // call coroutine-fn with synthesized push_coroutine as argument - fn( synthesized); - } catch ( forced_unwind const&) { - // do nothing for unwinding exception - } catch (...) { - // store other exceptions in exception-pointer - except = std::current_exception(); - } - // set termination flags - state |= static_cast< int >( state_t::complete); - // jump back to caller - caller( preserve_fpu); - BOOST_ASSERT_MSG( false, "pull_coroutine is complete"); - }), + ctx( std::allocator_arg, palloc, salloc, + [=,fn=std::forward< Fn >( fn_),ctx=boost::context::execution_context::current()] (void *) mutable -> void { + // create synthesized push_coroutine< T > + typename push_coroutine< void >::control_block synthesized_cb( this, ctx); + push_coroutine< void > synthesized( & synthesized_cb); + other = & synthesized_cb; + try { + // call coroutine-fn with synthesized push_coroutine as argument + fn( synthesized); + } catch ( forced_unwind const&) { + // do nothing for unwinding exception + } catch (...) { + // store other exceptions in exception-pointer + except = std::current_exception(); + } + // set termination flags + state |= static_cast< int >( state_t::complete); + // jump back to ctx + other->ctx( nullptr, preserve_fpu); + BOOST_ASSERT_MSG( false, "pull_coroutine is complete"); + }), preserve_fpu( preserve_fpu_), state( static_cast< int >( state_t::unwind) ), except() { - callee( preserve_fpu); + // enter coroutine-fn in order to have first value available after ctor returns + ctx( nullptr, preserve_fpu); } inline -pull_coroutine< void >::control_block::control_block( push_coroutine< void >::control_block * cb) : +pull_coroutine< void >::control_block::control_block( push_coroutine< void >::control_block * cb, + boost::context::execution_context const& ctx_) : other( cb), - caller( other->callee), - callee( other->caller), + ctx( ctx_), preserve_fpu( other->preserve_fpu), state( 0), except() { @@ -226,14 +266,15 @@ pull_coroutine< void >::control_block::~control_block() { 0 != ( state & static_cast< int >( state_t::unwind) ) ) { // set early-exit flag state |= static_cast< int >( state_t::early_exit); - callee( preserve_fpu); + ctx( nullptr, preserve_fpu); } } inline void pull_coroutine< void >::control_block::resume() { - callee( preserve_fpu); + other->ctx = boost::context::execution_context::current(); + ctx( nullptr, preserve_fpu); if ( except) { std::rethrow_exception( except); } |