diff options
Diffstat (limited to 'boost/coroutine2/detail/push_control_block.ipp')
-rw-r--r-- | boost/coroutine2/detail/push_control_block.ipp | 212 |
1 files changed, 110 insertions, 102 deletions
diff --git a/boost/coroutine2/detail/push_control_block.ipp b/boost/coroutine2/detail/push_control_block.ipp index ebef5092b5..ce6776f600 100644 --- a/boost/coroutine2/detail/push_control_block.ipp +++ b/boost/coroutine2/detail/push_control_block.ipp @@ -9,6 +9,7 @@ #include <algorithm> #include <exception> +#include <memory> #include <boost/assert.hpp> #include <boost/config.hpp> @@ -34,42 +35,46 @@ template< typename StackAllocator, typename Fn > push_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 pull_coroutine< T > - typename pull_coroutine< T >::control_block synthesized_cb( this); - pull_coroutine< T > synthesized( & synthesized_cb); - other = & synthesized_cb; - try { - // call coroutine-fn with synthesized pull_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); - caller( preserve_fpu); - BOOST_ASSERT_MSG( false, "push_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 pull_coroutine< T > + typename pull_coroutine< T >::control_block synthesized_cb( this, ctx); + pull_coroutine< T > synthesized( & synthesized_cb); + other = & synthesized_cb; + // jump back to ctor + T * t = reinterpret_cast< T * >( ctx( nullptr, preserve_fpu) ); + // set transferred value + synthesized_cb.set( t); + try { + // call coroutine-fn with synthesized pull_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, "push_coroutine is complete"); + }), preserve_fpu( preserve_fpu_), state( static_cast< int >( state_t::unwind) ), - except(), - t( nullptr) { + except() { + // enter coroutine-fn in order to get other set + ctx( nullptr, preserve_fpu); } template< typename T > -push_coroutine< T >::control_block::control_block( typename pull_coroutine< T >::control_block * cb) : +push_coroutine< T >::control_block::control_block( typename pull_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(), - t( nullptr) { + except() { } template< typename T > @@ -78,19 +83,16 @@ push_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 -push_coroutine< T >::control_block::resume( T const& t_) { - // store data on this stack - // pass an pointer (address of tmp) to other context - T tmp( t_); - t = & tmp; - callee( preserve_fpu); - t = nullptr; +push_coroutine< T >::control_block::resume( T const& t) { + other->ctx = boost::context::execution_context::current(); + // pass an pointer to other context + ctx( const_cast< T * >( & t), preserve_fpu); if ( except) { std::rethrow_exception( except); } @@ -102,13 +104,10 @@ push_coroutine< T >::control_block::resume( T const& t_) { template< typename T > void -push_coroutine< T >::control_block::resume( T && t_) { - // store data on this stack - // pass an pointer (address of tmp) to other context - T tmp( std::move( t_) ); - t = & tmp; - callee( preserve_fpu); - t = nullptr; +push_coroutine< T >::control_block::resume( T && t) { + other->ctx = boost::context::execution_context::current(); + // pass an pointer to other context + ctx( std::addressof( t), preserve_fpu); if ( except) { std::rethrow_exception( except); } @@ -132,42 +131,46 @@ template< typename StackAllocator, typename Fn > push_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 pull_coroutine< T > - typename pull_coroutine< T & >::control_block synthesized_cb( this); - pull_coroutine< T & > synthesized( & synthesized_cb); - other = & synthesized_cb; - try { - // call coroutine-fn with synthesized pull_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); - caller( preserve_fpu); - BOOST_ASSERT_MSG( false, "push_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 pull_coroutine< T > + typename pull_coroutine< T & >::control_block synthesized_cb( this, ctx); + pull_coroutine< T & > synthesized( & synthesized_cb); + other = & synthesized_cb; + // jump back to ctor + T * t = reinterpret_cast< T * >( ctx( nullptr, preserve_fpu) ); + // set transferred value + synthesized_cb.t = t; + try { + // call coroutine-fn with synthesized pull_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, "push_coroutine is complete"); + }), preserve_fpu( preserve_fpu_), state( static_cast< int >( state_t::unwind) ), - except(), - t( nullptr) { + except() { + // enter coroutine-fn in order to get other set + ctx( nullptr, preserve_fpu); } template< typename T > -push_coroutine< T & >::control_block::control_block( typename pull_coroutine< T & >::control_block * cb) : +push_coroutine< T & >::control_block::control_block( typename pull_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(), - t( nullptr) { + except() { } template< typename T > @@ -176,16 +179,16 @@ push_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 -push_coroutine< T & >::control_block::resume( T & t_) { - t = & t_; - callee( preserve_fpu); - t = nullptr; +push_coroutine< T & >::control_block::resume( T & t) { + other->ctx = boost::context::execution_context::current(); + // pass an pointer to other context + ctx( const_cast< typename std::remove_const< T >::type * >( std::addressof( t) ), preserve_fpu); if ( except) { std::rethrow_exception( except); } @@ -207,37 +210,41 @@ push_coroutine< T & >::control_block::valid() const noexcept { template< typename StackAllocator, typename Fn > push_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 pull_coroutine< T > - typename pull_coroutine< void >::control_block synthesized_cb( this); - pull_coroutine< void > synthesized( & synthesized_cb); - other = & synthesized_cb; - try { - // call coroutine-fn with synthesized pull_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); - caller( preserve_fpu); - BOOST_ASSERT_MSG( false, "push_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 pull_coroutine< T > + typename pull_coroutine< void >::control_block synthesized_cb( this, ctx); + pull_coroutine< void > synthesized( & synthesized_cb); + other = & synthesized_cb; + // jump back to ctor + ctx( nullptr, preserve_fpu); + try { + // call coroutine-fn with synthesized pull_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, "push_coroutine is complete"); + }), preserve_fpu( preserve_fpu_), state( static_cast< int >( state_t::unwind) ), except() { + // enter coroutine-fn in order to get other set + ctx( nullptr, preserve_fpu); } inline -push_coroutine< void >::control_block::control_block( pull_coroutine< void >::control_block * cb) : +push_coroutine< void >::control_block::control_block( pull_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() { @@ -249,14 +256,15 @@ push_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 push_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); } |