diff options
Diffstat (limited to 'boost/coroutine2/detail')
-rw-r--r-- | boost/coroutine2/detail/config.hpp | 12 | ||||
-rw-r--r-- | boost/coroutine2/detail/pull_control_block.hpp | 33 | ||||
-rw-r--r-- | boost/coroutine2/detail/pull_control_block.ipp | 221 | ||||
-rw-r--r-- | boost/coroutine2/detail/pull_coroutine.hpp | 12 | ||||
-rw-r--r-- | boost/coroutine2/detail/pull_coroutine.ipp | 15 | ||||
-rw-r--r-- | boost/coroutine2/detail/push_control_block.hpp | 17 | ||||
-rw-r--r-- | boost/coroutine2/detail/push_control_block.ipp | 212 | ||||
-rw-r--r-- | boost/coroutine2/detail/push_coroutine.ipp | 7 |
8 files changed, 285 insertions, 244 deletions
diff --git a/boost/coroutine2/detail/config.hpp b/boost/coroutine2/detail/config.hpp index c439ecc0ea..cfb95846a5 100644 --- a/boost/coroutine2/detail/config.hpp +++ b/boost/coroutine2/detail/config.hpp @@ -36,16 +36,4 @@ # include <boost/config/auto_link.hpp> #endif -#if defined(BOOST_USE_SEGMENTED_STACKS) -# if ! ( (defined(__GNUC__) && __GNUC__ > 3 && __GNUC_MINOR__ > 6) || \ - (defined(__clang__) && __clang_major__ > 2 && __clang_minor__ > 3) ) -# error "compiler does not support segmented_stack stacks" -# endif -# define BOOST_COROUTINES2_SEGMENTS 10 -#endif - -#if defined(BOOST_CONTEXT_NO_EXECUTION_CONTEXT) -# error "execution_context from boost.context not supported" -#endif - #endif // BOOST_COROUTINES2_DETAIL_CONFIG_H diff --git a/boost/coroutine2/detail/pull_control_block.hpp b/boost/coroutine2/detail/pull_control_block.hpp index 1abb34a0db..7009454c88 100644 --- a/boost/coroutine2/detail/pull_control_block.hpp +++ b/boost/coroutine2/detail/pull_control_block.hpp @@ -8,6 +8,7 @@ #define BOOST_COROUTINES2_DETAIL_PULL_CONTROL_BLOCK_HPP #include <exception> +#include <type_traits> #include <boost/config.hpp> #include <boost/context/execution_context.hpp> @@ -22,17 +23,18 @@ namespace detail { template< typename T > struct pull_coroutine< T >::control_block { - typename push_coroutine< T >::control_block * other; - boost::context::execution_context caller; - boost::context::execution_context callee; - bool preserve_fpu; - int state; - std::exception_ptr except; + typename push_coroutine< T >::control_block * other; + boost::context::execution_context ctx; + bool preserve_fpu; + int state; + std::exception_ptr except; + bool bvalid; + typename std::aligned_storage< sizeof( T), alignof( T) >::type storage[1]; template< typename StackAllocator, typename Fn > control_block( context::preallocated, StackAllocator, Fn &&, bool); - explicit control_block( typename push_coroutine< T >::control_block *); + explicit control_block( typename push_coroutine< T >::control_block *, boost::context::execution_context const&); ~control_block(); @@ -41,22 +43,26 @@ struct pull_coroutine< T >::control_block { void resume(); + void set( T *); + + T & get(); + bool valid() const noexcept; }; template< typename T > struct pull_coroutine< T & >::control_block { typename push_coroutine< T & >::control_block * other; - boost::context::execution_context caller; - boost::context::execution_context callee; + boost::context::execution_context ctx; bool preserve_fpu; int state; std::exception_ptr except; + T * t; template< typename StackAllocator, typename Fn > control_block( context::preallocated, StackAllocator, Fn &&, bool); - explicit control_block( typename push_coroutine< T & >::control_block *); + explicit control_block( typename push_coroutine< T & >::control_block *, boost::context::execution_context const&); ~control_block(); @@ -65,13 +71,14 @@ struct pull_coroutine< T & >::control_block { void resume(); + T & get(); + bool valid() const noexcept; }; struct pull_coroutine< void >::control_block { push_coroutine< void >::control_block * other; - boost::context::execution_context caller; - boost::context::execution_context callee; + boost::context::execution_context ctx; bool preserve_fpu; int state; std::exception_ptr except; @@ -79,7 +86,7 @@ struct pull_coroutine< void >::control_block { template< typename StackAllocator, typename Fn > control_block( context::preallocated, StackAllocator, Fn &&, bool); - explicit control_block( push_coroutine< void >::control_block *); + explicit control_block( push_coroutine< void >::control_block *, boost::context::execution_context const&); ~control_block(); 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); } diff --git a/boost/coroutine2/detail/pull_coroutine.hpp b/boost/coroutine2/detail/pull_coroutine.hpp index ff76bd3aac..c78750442e 100644 --- a/boost/coroutine2/detail/pull_coroutine.hpp +++ b/boost/coroutine2/detail/pull_coroutine.hpp @@ -66,7 +66,7 @@ public: bool operator!() const noexcept; - T get() const noexcept; + T get(); class iterator : public std::iterator< std::input_iterator_tag, typename std::remove_reference< T >::type > { private: @@ -126,11 +126,11 @@ public: iterator operator++( int) = delete; reference_t operator*() const { - return * c_->cb_->other->t; + return c_->cb_->get(); } pointer_t operator->() const { - return c_->cb_->other->t; + return std::addressof( c_->cb_->get() ); } }; @@ -179,7 +179,7 @@ public: bool operator!() const noexcept; - T & get() const noexcept; + T & get(); class iterator : public std::iterator< std::input_iterator_tag, typename std::remove_reference< T >::type > { private: @@ -239,11 +239,11 @@ public: iterator operator++( int) = delete; reference_t operator*() const { - return * c_->cb_->other->t; + return c_->cb_->get(); } pointer_t operator->() const { - return c_->cb_->other->t; + return std::addressof( c_->cb_->get() ); } }; diff --git a/boost/coroutine2/detail/pull_coroutine.ipp b/boost/coroutine2/detail/pull_coroutine.ipp index f59bb3cb5f..2e37ef2a98 100644 --- a/boost/coroutine2/detail/pull_coroutine.ipp +++ b/boost/coroutine2/detail/pull_coroutine.ipp @@ -19,6 +19,7 @@ #include <boost/coroutine2/detail/config.hpp> #include <boost/coroutine2/fixedsize_stack.hpp> +#include <boost/coroutine2/segmented_stack.hpp> #ifdef BOOST_HAS_ABI_HEADERS # include BOOST_ABI_PREFIX @@ -44,7 +45,7 @@ pull_coroutine< T >::has_result_() const { template< typename T > template< typename Fn > pull_coroutine< T >::pull_coroutine( Fn && fn, bool preserve_fpu) : - pull_coroutine( fixedsize_stack(), std::forward< Fn >( fn), preserve_fpu) { + pull_coroutine( default_stack(), std::forward< Fn >( fn), preserve_fpu) { } template< typename T > @@ -106,8 +107,8 @@ pull_coroutine< T >::operator!() const noexcept { template< typename T > T -pull_coroutine< T >::get() const noexcept { - return std::move( * cb_->other->t); +pull_coroutine< T >::get() { + return std::move( cb_->get() ); } @@ -127,7 +128,7 @@ pull_coroutine< T & >::has_result_() const { template< typename T > template< typename Fn > pull_coroutine< T & >::pull_coroutine( Fn && fn, bool preserve_fpu) : - pull_coroutine( fixedsize_stack(), std::forward< Fn >( fn), preserve_fpu) { + pull_coroutine( default_stack(), std::forward< Fn >( fn), preserve_fpu) { } template< typename T > @@ -189,8 +190,8 @@ pull_coroutine< T & >::operator!() const noexcept { template< typename T > T & -pull_coroutine< T & >::get() const noexcept { - return * cb_->other->t; +pull_coroutine< T & >::get() { + return cb_->get(); } @@ -203,7 +204,7 @@ pull_coroutine< void >::pull_coroutine( control_block * cb) : template< typename Fn > pull_coroutine< void >::pull_coroutine( Fn && fn, bool preserve_fpu) : - pull_coroutine( fixedsize_stack(), std::forward< Fn >( fn), preserve_fpu) { + pull_coroutine( default_stack(), std::forward< Fn >( fn), preserve_fpu) { } template< typename StackAllocator, typename Fn > diff --git a/boost/coroutine2/detail/push_control_block.hpp b/boost/coroutine2/detail/push_control_block.hpp index e6c86ffd81..03aa9125eb 100644 --- a/boost/coroutine2/detail/push_control_block.hpp +++ b/boost/coroutine2/detail/push_control_block.hpp @@ -23,17 +23,15 @@ namespace detail { template< typename T > struct push_coroutine< T >::control_block { typename pull_coroutine< T >::control_block * other; - boost::context::execution_context caller; - boost::context::execution_context callee; + boost::context::execution_context ctx; bool preserve_fpu; int state; std::exception_ptr except; - T * t; template< typename StackAllocator, typename Fn > control_block( context::preallocated, StackAllocator, Fn &&, bool); - explicit control_block( typename pull_coroutine< T >::control_block *); + explicit control_block( typename pull_coroutine< T >::control_block *, boost::context::execution_context const&); ~control_block(); @@ -50,17 +48,15 @@ struct push_coroutine< T >::control_block { template< typename T > struct push_coroutine< T & >::control_block { typename pull_coroutine< T & >::control_block * other; - boost::context::execution_context caller; - boost::context::execution_context callee; + boost::context::execution_context ctx; bool preserve_fpu; int state; std::exception_ptr except; - T * t; template< typename StackAllocator, typename Fn > control_block( context::preallocated, StackAllocator, Fn &&, bool); - explicit control_block( typename pull_coroutine< T & >::control_block *); + explicit control_block( typename pull_coroutine< T & >::control_block *, boost::context::execution_context const&); ~control_block(); @@ -74,8 +70,7 @@ struct push_coroutine< T & >::control_block { struct push_coroutine< void >::control_block { pull_coroutine< void >::control_block * other; - boost::context::execution_context caller; - boost::context::execution_context callee; + boost::context::execution_context ctx; bool preserve_fpu; int state; std::exception_ptr except; @@ -83,7 +78,7 @@ struct push_coroutine< void >::control_block { template< typename StackAllocator, typename Fn > control_block( context::preallocated, StackAllocator, Fn &&, bool); - explicit control_block( pull_coroutine< void >::control_block *); + explicit control_block( pull_coroutine< void >::control_block *, boost::context::execution_context const&); ~control_block(); 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); } diff --git a/boost/coroutine2/detail/push_coroutine.ipp b/boost/coroutine2/detail/push_coroutine.ipp index 4617e73aac..5f4817802a 100644 --- a/boost/coroutine2/detail/push_coroutine.ipp +++ b/boost/coroutine2/detail/push_coroutine.ipp @@ -18,6 +18,7 @@ #include <boost/coroutine2/detail/config.hpp> #include <boost/coroutine2/fixedsize_stack.hpp> +#include <boost/coroutine2/segmented_stack.hpp> #ifdef BOOST_HAS_ABI_HEADERS # include BOOST_ABI_PREFIX @@ -37,7 +38,7 @@ push_coroutine< T >::push_coroutine( control_block * cb) : template< typename T > template< typename Fn > push_coroutine< T >::push_coroutine( Fn && fn, bool preserve_fpu) : - push_coroutine( fixedsize_stack(), std::forward< Fn >( fn), preserve_fpu) { + push_coroutine( default_stack(), std::forward< Fn >( fn), preserve_fpu) { } template< typename T > @@ -115,7 +116,7 @@ push_coroutine< T & >::push_coroutine( control_block * cb) : template< typename T > template< typename Fn > push_coroutine< T & >::push_coroutine( Fn && fn, bool preserve_fpu) : - push_coroutine( fixedsize_stack(), std::forward< Fn >( fn), preserve_fpu) { + push_coroutine( default_stack(), std::forward< Fn >( fn), preserve_fpu) { } template< typename T > @@ -185,7 +186,7 @@ push_coroutine< void >::push_coroutine( control_block * cb) : template< typename Fn > push_coroutine< void >::push_coroutine( Fn && fn, bool preserve_fpu) : - push_coroutine( fixedsize_stack(), std::forward< Fn >( fn), preserve_fpu) { + push_coroutine( default_stack(), std::forward< Fn >( fn), preserve_fpu) { } template< typename StackAllocator, typename Fn > |