mirror of
https://github.com/boostorg/coroutine2.git
synced 2025-05-09 23:24:01 +00:00
fix deallocation
- ~control_block() must be run before coroutine's stack is destroyed
This commit is contained in:
parent
302e484e8e
commit
3d76707ea1
@ -25,13 +25,15 @@ namespace detail {
|
||||
|
||||
template< typename T >
|
||||
struct pull_coroutine< T >::control_block {
|
||||
typename push_coroutine< T >::control_block * other;
|
||||
boost::context::captured_context ctx;
|
||||
typename push_coroutine< T >::control_block * other;
|
||||
state_t state;
|
||||
std::exception_ptr except;
|
||||
bool bvalid;
|
||||
typename std::aligned_storage< sizeof( T), alignof( T) >::type storage;
|
||||
|
||||
static void destroy( control_block * cb) noexcept;
|
||||
|
||||
template< typename StackAllocator, typename Fn >
|
||||
control_block( context::preallocated, StackAllocator, Fn &&);
|
||||
|
||||
@ -42,6 +44,8 @@ struct pull_coroutine< T >::control_block {
|
||||
control_block( control_block &) = delete;
|
||||
control_block & operator=( control_block &) = delete;
|
||||
|
||||
void deallocate() noexcept;
|
||||
|
||||
void resume();
|
||||
|
||||
void set( T *);
|
||||
@ -53,22 +57,24 @@ struct pull_coroutine< T >::control_block {
|
||||
|
||||
template< typename T >
|
||||
struct pull_coroutine< T & >::control_block {
|
||||
typename push_coroutine< T & >::control_block * other;
|
||||
boost::context::captured_context ctx;
|
||||
typename push_coroutine< T & >::control_block * other;
|
||||
state_t state;
|
||||
std::exception_ptr except;
|
||||
T * t;
|
||||
|
||||
static void destroy( control_block * cb) noexcept;
|
||||
|
||||
template< typename StackAllocator, typename Fn >
|
||||
control_block( context::preallocated, StackAllocator, Fn &&);
|
||||
|
||||
control_block( typename push_coroutine< T & >::control_block *, boost::context::captured_context &) noexcept;
|
||||
|
||||
~control_block();
|
||||
|
||||
control_block( control_block &) = delete;
|
||||
control_block & operator=( control_block &) = delete;
|
||||
|
||||
void deallocate() noexcept;
|
||||
|
||||
void resume();
|
||||
|
||||
T & get() noexcept;
|
||||
@ -77,21 +83,23 @@ struct pull_coroutine< T & >::control_block {
|
||||
};
|
||||
|
||||
struct pull_coroutine< void >::control_block {
|
||||
push_coroutine< void >::control_block * other;
|
||||
boost::context::captured_context ctx;
|
||||
push_coroutine< void >::control_block * other;
|
||||
state_t state;
|
||||
std::exception_ptr except;
|
||||
|
||||
static void destroy( control_block * cb) noexcept;
|
||||
|
||||
template< typename StackAllocator, typename Fn >
|
||||
control_block( context::preallocated, StackAllocator, Fn &&);
|
||||
|
||||
control_block( push_coroutine< void >::control_block *, boost::context::captured_context &) noexcept;
|
||||
|
||||
~control_block();
|
||||
|
||||
control_block( control_block &) = delete;
|
||||
control_block & operator=( control_block &) = delete;
|
||||
|
||||
void deallocate() noexcept;
|
||||
|
||||
void resume();
|
||||
|
||||
bool valid() const noexcept;
|
||||
|
@ -30,11 +30,20 @@ namespace detail {
|
||||
|
||||
// pull_coroutine< T >
|
||||
|
||||
template< typename T >
|
||||
void
|
||||
pull_coroutine< T >::control_block::destroy( control_block * cb) noexcept {
|
||||
boost::context::captured_context ctx = std::move( cb->ctx);
|
||||
// destroy control structure
|
||||
cb->~control_block();
|
||||
// destroy coroutine's stack
|
||||
ctx();
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
template< typename StackAllocator, typename Fn >
|
||||
pull_coroutine< T >::control_block::control_block( context::preallocated palloc, StackAllocator salloc,
|
||||
Fn && fn) :
|
||||
other{ nullptr },
|
||||
#if defined(BOOST_NO_CXX14_GENERIC_LAMBDAS)
|
||||
ctx{ std::allocator_arg, palloc, salloc,
|
||||
std::move(
|
||||
@ -89,6 +98,7 @@ pull_coroutine< T >::control_block::control_block( context::preallocated palloc,
|
||||
return std::move( other->ctx);
|
||||
}},
|
||||
#endif
|
||||
other{ nullptr },
|
||||
state{ state_t::unwind },
|
||||
except{},
|
||||
bvalid{ false },
|
||||
@ -102,8 +112,8 @@ pull_coroutine< T >::control_block::control_block( context::preallocated palloc,
|
||||
template< typename T >
|
||||
pull_coroutine< T >::control_block::control_block( typename push_coroutine< T >::control_block * cb,
|
||||
boost::context::captured_context & ctx_) noexcept :
|
||||
other{ cb },
|
||||
ctx{ std::move( ctx_) },
|
||||
other{ cb },
|
||||
state{ state_t::none },
|
||||
except{},
|
||||
bvalid{ false },
|
||||
@ -116,9 +126,13 @@ pull_coroutine< T >::control_block::~control_block() {
|
||||
if ( bvalid) {
|
||||
reinterpret_cast< T * >( std::addressof( storage) )->~T();
|
||||
}
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
void
|
||||
pull_coroutine< T >::control_block::deallocate() noexcept {
|
||||
if ( state_t::none != ( state & state_t::unwind) ) {
|
||||
// unwind coroutine stack
|
||||
ctx();
|
||||
destroy( this);
|
||||
}
|
||||
}
|
||||
|
||||
@ -163,11 +177,20 @@ pull_coroutine< T >::control_block::valid() const noexcept {
|
||||
|
||||
// pull_coroutine< T & >
|
||||
|
||||
template< typename T >
|
||||
void
|
||||
pull_coroutine< T & >::control_block::destroy( control_block * cb) noexcept {
|
||||
boost::context::captured_context ctx = std::move( cb->ctx);
|
||||
// destroy control structure
|
||||
cb->~control_block();
|
||||
// destroy coroutine's stack
|
||||
ctx();
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
template< typename StackAllocator, typename Fn >
|
||||
pull_coroutine< T & >::control_block::control_block( context::preallocated palloc, StackAllocator salloc,
|
||||
Fn && fn) :
|
||||
other{ nullptr },
|
||||
#if defined(BOOST_NO_CXX14_GENERIC_LAMBDAS)
|
||||
ctx{ std::allocator_arg, palloc, salloc,
|
||||
std::move(
|
||||
@ -222,6 +245,7 @@ pull_coroutine< T & >::control_block::control_block( context::preallocated pallo
|
||||
return std::move( other->ctx);
|
||||
}},
|
||||
#endif
|
||||
other{ nullptr },
|
||||
state{ state_t::unwind },
|
||||
except{},
|
||||
t{ nullptr } {
|
||||
@ -234,18 +258,18 @@ pull_coroutine< T & >::control_block::control_block( context::preallocated pallo
|
||||
template< typename T >
|
||||
pull_coroutine< T & >::control_block::control_block( typename push_coroutine< T & >::control_block * cb,
|
||||
boost::context::captured_context & ctx_) noexcept :
|
||||
other{ cb },
|
||||
ctx{ std::move( ctx_) },
|
||||
other{ cb },
|
||||
state{ state_t::none },
|
||||
except{},
|
||||
t{ nullptr } {
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
pull_coroutine< T & >::control_block::~control_block() {
|
||||
void
|
||||
pull_coroutine< T & >::control_block::deallocate() noexcept {
|
||||
if ( state_t::none != ( state & state_t::unwind) ) {
|
||||
// unwind coroutine stack
|
||||
ctx();
|
||||
destroy( this);
|
||||
}
|
||||
}
|
||||
|
||||
@ -275,10 +299,19 @@ pull_coroutine< T & >::control_block::valid() const noexcept {
|
||||
|
||||
// pull_coroutine< void >
|
||||
|
||||
inline
|
||||
void
|
||||
pull_coroutine< void >::control_block::destroy( control_block * cb) noexcept {
|
||||
boost::context::captured_context ctx = std::move( cb->ctx);
|
||||
// destroy control structure
|
||||
cb->~control_block();
|
||||
// destroy coroutine's stack
|
||||
ctx();
|
||||
}
|
||||
|
||||
template< typename StackAllocator, typename Fn >
|
||||
pull_coroutine< void >::control_block::control_block( context::preallocated palloc, StackAllocator salloc,
|
||||
Fn && fn) :
|
||||
other{ nullptr },
|
||||
#if defined(BOOST_NO_CXX14_GENERIC_LAMBDAS)
|
||||
ctx{ std::allocator_arg, palloc, salloc,
|
||||
std::move(
|
||||
@ -333,6 +366,7 @@ pull_coroutine< void >::control_block::control_block( context::preallocated pall
|
||||
return std::move( other->ctx);
|
||||
}},
|
||||
#endif
|
||||
other{ nullptr },
|
||||
state{ state_t::unwind },
|
||||
except{} {
|
||||
// enter coroutine-fn in order to have first value available after ctor (of `*this`) returns
|
||||
@ -343,17 +377,17 @@ pull_coroutine< void >::control_block::control_block( context::preallocated pall
|
||||
inline
|
||||
pull_coroutine< void >::control_block::control_block( push_coroutine< void >::control_block * cb,
|
||||
boost::context::captured_context & ctx_) noexcept :
|
||||
other{ cb },
|
||||
ctx{ std::move( ctx_) },
|
||||
other{ cb },
|
||||
state{ state_t::none },
|
||||
except{} {
|
||||
}
|
||||
|
||||
inline
|
||||
pull_coroutine< void >::control_block::~control_block() {
|
||||
void
|
||||
pull_coroutine< void >::control_block::deallocate() noexcept {
|
||||
if ( state_t::none != ( state & state_t::unwind) ) {
|
||||
// unwind coroutine stack
|
||||
ctx();
|
||||
destroy( this);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -26,13 +26,15 @@ namespace detail {
|
||||
|
||||
template< typename T >
|
||||
struct pull_coroutine< T >::control_block {
|
||||
typename push_coroutine< T >::control_block * other;
|
||||
boost::context::execution_context ctx;
|
||||
typename push_coroutine< T >::control_block * other;
|
||||
state_t state;
|
||||
std::exception_ptr except;
|
||||
bool bvalid;
|
||||
typename std::aligned_storage< sizeof( T), alignof( T) >::type storage;
|
||||
|
||||
static void destroy( control_block * cb) noexcept;
|
||||
|
||||
template< typename StackAllocator, typename Fn >
|
||||
control_block( context::preallocated, StackAllocator, Fn &&);
|
||||
|
||||
@ -43,6 +45,8 @@ struct pull_coroutine< T >::control_block {
|
||||
control_block( control_block &) = delete;
|
||||
control_block & operator=( control_block &) = delete;
|
||||
|
||||
void deallocate() noexcept;
|
||||
|
||||
void resume();
|
||||
|
||||
void set( T *);
|
||||
@ -54,12 +58,14 @@ struct pull_coroutine< T >::control_block {
|
||||
|
||||
template< typename T >
|
||||
struct pull_coroutine< T & >::control_block {
|
||||
typename push_coroutine< T & >::control_block * other;
|
||||
boost::context::execution_context ctx;
|
||||
typename push_coroutine< T & >::control_block * other;
|
||||
state_t state;
|
||||
std::exception_ptr except;
|
||||
T * t;
|
||||
|
||||
static void destroy( control_block * cb) noexcept;
|
||||
|
||||
template< typename StackAllocator, typename Fn >
|
||||
control_block( context::preallocated, StackAllocator, Fn &&);
|
||||
|
||||
@ -70,6 +76,8 @@ struct pull_coroutine< T & >::control_block {
|
||||
control_block( control_block &) = delete;
|
||||
control_block & operator=( control_block &) = delete;
|
||||
|
||||
void deallocate() noexcept;
|
||||
|
||||
void resume();
|
||||
|
||||
T & get() noexcept;
|
||||
@ -78,11 +86,13 @@ struct pull_coroutine< T & >::control_block {
|
||||
};
|
||||
|
||||
struct pull_coroutine< void >::control_block {
|
||||
push_coroutine< void >::control_block * other;
|
||||
boost::context::execution_context ctx;
|
||||
push_coroutine< void >::control_block * other;
|
||||
state_t state;
|
||||
std::exception_ptr except;
|
||||
|
||||
static void destroy( control_block * cb) noexcept;
|
||||
|
||||
template< typename StackAllocator, typename Fn >
|
||||
control_block( context::preallocated, StackAllocator, Fn &&);
|
||||
|
||||
@ -93,6 +103,8 @@ struct pull_coroutine< void >::control_block {
|
||||
control_block( control_block &) = delete;
|
||||
control_block & operator=( control_block &) = delete;
|
||||
|
||||
void deallocate() noexcept;
|
||||
|
||||
void resume();
|
||||
|
||||
bool valid() const noexcept;
|
||||
|
@ -31,11 +31,18 @@ namespace detail {
|
||||
|
||||
// pull_coroutine< T >
|
||||
|
||||
template< typename T >
|
||||
void
|
||||
pull_coroutine< T >::control_block::destroy( control_block * cb) noexcept {
|
||||
boost::context::execution_context ctx = cb->ctx;
|
||||
// destroy control structure
|
||||
cb->~control_block();
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
template< typename StackAllocator, typename Fn >
|
||||
pull_coroutine< T >::control_block::control_block( context::preallocated palloc, StackAllocator salloc,
|
||||
Fn && fn) :
|
||||
other{ nullptr },
|
||||
#if defined(BOOST_NO_CXX14_GENERIC_LAMBDAS)
|
||||
ctx{ std::allocator_arg, palloc, salloc,
|
||||
std::move(
|
||||
@ -88,6 +95,7 @@ pull_coroutine< T >::control_block::control_block( context::preallocated palloc,
|
||||
BOOST_ASSERT_MSG( false, "pull_coroutine is complete");
|
||||
}},
|
||||
#endif
|
||||
other{ nullptr },
|
||||
state{ state_t::unwind },
|
||||
except{},
|
||||
bvalid{ false },
|
||||
@ -99,8 +107,8 @@ pull_coroutine< T >::control_block::control_block( context::preallocated palloc,
|
||||
template< typename T >
|
||||
pull_coroutine< T >::control_block::control_block( typename push_coroutine< T >::control_block * cb,
|
||||
boost::context::execution_context const& ctx_) noexcept :
|
||||
other{ cb },
|
||||
ctx{ ctx_ },
|
||||
other{ cb },
|
||||
state{ state_t::none },
|
||||
except{},
|
||||
bvalid{ false },
|
||||
@ -120,6 +128,14 @@ pull_coroutine< T >::control_block::~control_block() {
|
||||
}
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
void
|
||||
pull_coroutine< T >::control_block::deallocate() noexcept {
|
||||
if ( state_t::none != ( state & state_t::unwind) ) {
|
||||
destroy( this);
|
||||
}
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
void
|
||||
pull_coroutine< T >::control_block::resume() {
|
||||
@ -160,11 +176,18 @@ pull_coroutine< T >::control_block::valid() const noexcept {
|
||||
|
||||
// pull_coroutine< T & >
|
||||
|
||||
template< typename T >
|
||||
void
|
||||
pull_coroutine< T & >::control_block::destroy( control_block * cb) noexcept {
|
||||
boost::context::execution_context ctx = cb->ctx;
|
||||
// destroy control structure
|
||||
cb->~control_block();
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
template< typename StackAllocator, typename Fn >
|
||||
pull_coroutine< T & >::control_block::control_block( context::preallocated palloc, StackAllocator salloc,
|
||||
Fn && fn) :
|
||||
other{ nullptr },
|
||||
#if defined(BOOST_NO_CXX14_GENERIC_LAMBDAS)
|
||||
ctx{ std::allocator_arg, palloc, salloc,
|
||||
std::move(
|
||||
@ -217,6 +240,7 @@ pull_coroutine< T & >::control_block::control_block( context::preallocated pallo
|
||||
BOOST_ASSERT_MSG( false, "pull_coroutine is complete");
|
||||
}},
|
||||
#endif
|
||||
other{ nullptr },
|
||||
state{ state_t::unwind },
|
||||
except{},
|
||||
t{ nullptr } {
|
||||
@ -227,15 +251,15 @@ pull_coroutine< T & >::control_block::control_block( context::preallocated pallo
|
||||
template< typename T >
|
||||
pull_coroutine< T & >::control_block::control_block( typename push_coroutine< T & >::control_block * cb,
|
||||
boost::context::execution_context const& ctx_) noexcept :
|
||||
other{ cb },
|
||||
ctx{ ctx_ },
|
||||
other{ cb },
|
||||
state{ state_t::none },
|
||||
except{},
|
||||
t( nullptr) {
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
pull_coroutine< T & >::control_block::~control_block() noexcept {
|
||||
pull_coroutine< T & >::control_block::~control_block() {
|
||||
if ( state_t::none == ( state & state_t::complete) &&
|
||||
state_t::none != ( state & state_t::unwind) ) {
|
||||
// unwind coroutine stack
|
||||
@ -243,6 +267,14 @@ pull_coroutine< T & >::control_block::~control_block() noexcept {
|
||||
}
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
void
|
||||
pull_coroutine< T & >::control_block::deallocate() noexcept {
|
||||
if ( state_t::none != ( state & state_t::unwind) ) {
|
||||
destroy( this);
|
||||
}
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
void
|
||||
pull_coroutine< T & >::control_block::resume() {
|
||||
@ -268,10 +300,17 @@ pull_coroutine< T & >::control_block::valid() const noexcept {
|
||||
|
||||
// pull_coroutine< void >
|
||||
|
||||
inline
|
||||
void
|
||||
pull_coroutine< void >::control_block::destroy( control_block * cb) noexcept {
|
||||
boost::context::execution_context ctx = cb->ctx;
|
||||
// destroy control structure
|
||||
cb->~control_block();
|
||||
}
|
||||
|
||||
template< typename StackAllocator, typename Fn >
|
||||
pull_coroutine< void >::control_block::control_block( context::preallocated palloc, StackAllocator salloc,
|
||||
Fn && fn) :
|
||||
other{ nullptr },
|
||||
#if defined(BOOST_NO_CXX14_GENERIC_LAMBDAS)
|
||||
ctx{ std::allocator_arg, palloc, salloc,
|
||||
std::move(
|
||||
@ -324,6 +363,7 @@ pull_coroutine< void >::control_block::control_block( context::preallocated pall
|
||||
BOOST_ASSERT_MSG( false, "pull_coroutine is complete");
|
||||
}},
|
||||
#endif
|
||||
other{ nullptr },
|
||||
state{ state_t::unwind },
|
||||
except{} {
|
||||
// enter coroutine-fn in order to have first value available after ctor returns
|
||||
@ -333,14 +373,14 @@ pull_coroutine< void >::control_block::control_block( context::preallocated pall
|
||||
inline
|
||||
pull_coroutine< void >::control_block::control_block( push_coroutine< void >::control_block * cb,
|
||||
boost::context::execution_context const& ctx_) noexcept :
|
||||
other{ cb },
|
||||
ctx{ ctx_ },
|
||||
other{ cb },
|
||||
state{ state_t::none },
|
||||
except{} {
|
||||
}
|
||||
|
||||
inline
|
||||
pull_coroutine< void >::control_block::~control_block() noexcept {
|
||||
pull_coroutine< void >::control_block::~control_block() {
|
||||
if ( state_t::none == ( state & state_t::complete) &&
|
||||
state_t::none != ( state & state_t::unwind) ) {
|
||||
// unwind coroutine stack
|
||||
@ -348,6 +388,14 @@ pull_coroutine< void >::control_block::~control_block() noexcept {
|
||||
}
|
||||
}
|
||||
|
||||
inline
|
||||
void
|
||||
pull_coroutine< void >::control_block::deallocate() noexcept {
|
||||
if ( state_t::none != ( state & state_t::unwind) ) {
|
||||
destroy( this);
|
||||
}
|
||||
}
|
||||
|
||||
inline
|
||||
void
|
||||
pull_coroutine< void >::control_block::resume() {
|
||||
|
@ -53,7 +53,7 @@ template< typename StackAllocator, typename Fn >
|
||||
pull_coroutine< T >::pull_coroutine( StackAllocator salloc, Fn && fn) :
|
||||
cb_{ create_control_block< control_block >( salloc, std::forward< Fn >( fn) ) } {
|
||||
if ( ! cb_->valid() ) {
|
||||
cb_->~control_block();
|
||||
cb_->deallocate();
|
||||
cb_ = nullptr;
|
||||
}
|
||||
}
|
||||
@ -61,7 +61,7 @@ pull_coroutine< T >::pull_coroutine( StackAllocator salloc, Fn && fn) :
|
||||
template< typename T >
|
||||
pull_coroutine< T >::~pull_coroutine() noexcept {
|
||||
if ( nullptr != cb_) {
|
||||
cb_->~control_block();
|
||||
cb_->deallocate();
|
||||
}
|
||||
}
|
||||
|
||||
@ -122,7 +122,7 @@ template< typename StackAllocator, typename Fn >
|
||||
pull_coroutine< T & >::pull_coroutine( StackAllocator salloc, Fn && fn) :
|
||||
cb_{ create_control_block< control_block >( salloc, std::forward< Fn >( fn) ) } {
|
||||
if ( ! cb_->valid() ) {
|
||||
cb_->~control_block();
|
||||
cb_->deallocate();
|
||||
cb_ = nullptr;
|
||||
}
|
||||
}
|
||||
@ -130,7 +130,7 @@ pull_coroutine< T & >::pull_coroutine( StackAllocator salloc, Fn && fn) :
|
||||
template< typename T >
|
||||
pull_coroutine< T & >::~pull_coroutine() noexcept {
|
||||
if ( nullptr != cb_) {
|
||||
cb_->~control_block();
|
||||
cb_->deallocate();
|
||||
}
|
||||
}
|
||||
|
||||
@ -183,7 +183,7 @@ template< typename StackAllocator, typename Fn >
|
||||
pull_coroutine< void >::pull_coroutine( StackAllocator salloc, Fn && fn) :
|
||||
cb_{ create_control_block< control_block >( salloc, std::forward< Fn >( fn) ) } {
|
||||
if ( ! cb_->valid() ) {
|
||||
cb_->~control_block();
|
||||
cb_->deallocate();
|
||||
cb_ = nullptr;
|
||||
}
|
||||
}
|
||||
@ -191,7 +191,7 @@ pull_coroutine< void >::pull_coroutine( StackAllocator salloc, Fn && fn) :
|
||||
inline
|
||||
pull_coroutine< void >::~pull_coroutine() noexcept {
|
||||
if ( nullptr != cb_) {
|
||||
cb_->~control_block();
|
||||
cb_->deallocate();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -24,21 +24,23 @@ namespace detail {
|
||||
|
||||
template< typename T >
|
||||
struct push_coroutine< T >::control_block {
|
||||
typename pull_coroutine< T >::control_block * other;
|
||||
boost::context::captured_context ctx;
|
||||
typename pull_coroutine< T >::control_block * other;
|
||||
state_t state;
|
||||
std::exception_ptr except;
|
||||
|
||||
static void destroy( control_block * cb) noexcept;
|
||||
|
||||
template< typename StackAllocator, typename Fn >
|
||||
control_block( context::preallocated, StackAllocator, Fn &&);
|
||||
|
||||
control_block( typename pull_coroutine< T >::control_block *, boost::context::captured_context &) noexcept;
|
||||
|
||||
~control_block();
|
||||
|
||||
control_block( control_block &) = delete;
|
||||
control_block & operator=( control_block &) = delete;
|
||||
|
||||
void deallocate() noexcept;
|
||||
|
||||
void resume( T const&);
|
||||
|
||||
void resume( T &&);
|
||||
@ -48,42 +50,46 @@ struct push_coroutine< T >::control_block {
|
||||
|
||||
template< typename T >
|
||||
struct push_coroutine< T & >::control_block {
|
||||
typename pull_coroutine< T & >::control_block * other;
|
||||
boost::context::captured_context ctx;
|
||||
typename pull_coroutine< T & >::control_block * other;
|
||||
state_t state;
|
||||
std::exception_ptr except;
|
||||
|
||||
static void destroy( control_block * cb) noexcept;
|
||||
|
||||
template< typename StackAllocator, typename Fn >
|
||||
control_block( context::preallocated, StackAllocator, Fn &&);
|
||||
|
||||
control_block( typename pull_coroutine< T & >::control_block *, boost::context::captured_context &) noexcept;
|
||||
|
||||
~control_block();
|
||||
|
||||
control_block( control_block &) = delete;
|
||||
control_block & operator=( control_block &) = delete;
|
||||
|
||||
void deallocate() noexcept;
|
||||
|
||||
void resume( T &);
|
||||
|
||||
bool valid() const noexcept;
|
||||
};
|
||||
|
||||
struct push_coroutine< void >::control_block {
|
||||
pull_coroutine< void >::control_block * other;
|
||||
boost::context::captured_context ctx;
|
||||
pull_coroutine< void >::control_block * other;
|
||||
state_t state;
|
||||
std::exception_ptr except;
|
||||
|
||||
static void destroy( control_block * cb) noexcept;
|
||||
|
||||
template< typename StackAllocator, typename Fn >
|
||||
control_block( context::preallocated, StackAllocator, Fn &&);
|
||||
|
||||
control_block( pull_coroutine< void >::control_block *, boost::context::captured_context &) noexcept;
|
||||
|
||||
~control_block();
|
||||
|
||||
control_block( control_block &) = delete;
|
||||
control_block & operator=( control_block &) = delete;
|
||||
|
||||
void deallocate() noexcept;
|
||||
|
||||
void resume();
|
||||
|
||||
bool valid() const noexcept;
|
||||
|
@ -29,11 +29,20 @@ namespace detail {
|
||||
|
||||
// push_coroutine< T >
|
||||
|
||||
template< typename T >
|
||||
void
|
||||
push_coroutine< T >::control_block::destroy( control_block * cb) noexcept {
|
||||
boost::context::captured_context ctx = std::move( cb->ctx);
|
||||
// destroy control structure
|
||||
cb->~control_block();
|
||||
// destroy coroutine's stack
|
||||
ctx();
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
template< typename StackAllocator, typename Fn >
|
||||
push_coroutine< T >::control_block::control_block( context::preallocated palloc, StackAllocator salloc,
|
||||
Fn && fn) :
|
||||
other{ nullptr },
|
||||
#if defined(BOOST_NO_CXX14_GENERIC_LAMBDAS)
|
||||
ctx{ std::allocator_arg, palloc, salloc,
|
||||
std::move(
|
||||
@ -92,6 +101,7 @@ push_coroutine< T >::control_block::control_block( context::preallocated palloc,
|
||||
return std::move( other->ctx);
|
||||
}},
|
||||
#endif
|
||||
other{ nullptr },
|
||||
state{ state_t::unwind },
|
||||
except{} {
|
||||
}
|
||||
@ -99,17 +109,17 @@ push_coroutine< T >::control_block::control_block( context::preallocated palloc,
|
||||
template< typename T >
|
||||
push_coroutine< T >::control_block::control_block( typename pull_coroutine< T >::control_block * cb,
|
||||
boost::context::captured_context & ctx_) noexcept :
|
||||
other{ cb },
|
||||
ctx{ std::move( ctx_) },
|
||||
other{ cb },
|
||||
state{ state_t::none },
|
||||
except{} {
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
push_coroutine< T >::control_block::~control_block() {
|
||||
void
|
||||
push_coroutine< T >::control_block::deallocate() noexcept {
|
||||
if ( state_t::none != ( state & state_t::unwind) ) {
|
||||
// unwind coroutine stack
|
||||
ctx();
|
||||
destroy( this);
|
||||
}
|
||||
}
|
||||
|
||||
@ -144,11 +154,20 @@ push_coroutine< T >::control_block::valid() const noexcept {
|
||||
|
||||
// push_coroutine< T & >
|
||||
|
||||
template< typename T >
|
||||
void
|
||||
push_coroutine< T & >::control_block::destroy( control_block * cb) noexcept {
|
||||
boost::context::captured_context ctx = std::move( cb->ctx);
|
||||
// destroy control structure
|
||||
cb->~control_block();
|
||||
// destroy coroutine's stack
|
||||
ctx();
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
template< typename StackAllocator, typename Fn >
|
||||
push_coroutine< T & >::control_block::control_block( context::preallocated palloc, StackAllocator salloc,
|
||||
Fn && fn) :
|
||||
other{ nullptr },
|
||||
#if defined(BOOST_NO_CXX14_GENERIC_LAMBDAS)
|
||||
ctx{ std::allocator_arg, palloc, salloc,
|
||||
std::move(
|
||||
@ -207,6 +226,7 @@ push_coroutine< T & >::control_block::control_block( context::preallocated pallo
|
||||
return std::move( other->ctx);
|
||||
}},
|
||||
#endif
|
||||
other{ nullptr },
|
||||
state{ state_t::unwind },
|
||||
except{} {
|
||||
}
|
||||
@ -214,17 +234,17 @@ push_coroutine< T & >::control_block::control_block( context::preallocated pallo
|
||||
template< typename T >
|
||||
push_coroutine< T & >::control_block::control_block( typename pull_coroutine< T & >::control_block * cb,
|
||||
boost::context::captured_context & ctx_) noexcept :
|
||||
other{ cb },
|
||||
ctx{ std::move( ctx_) },
|
||||
other{ cb },
|
||||
state{ state_t::none },
|
||||
except{} {
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
push_coroutine< T & >::control_block::~control_block() {
|
||||
void
|
||||
push_coroutine< T & >::control_block::deallocate() noexcept {
|
||||
if ( state_t::none != ( state & state_t::unwind) ) {
|
||||
// unwind coroutine stack
|
||||
ctx();
|
||||
destroy( this);
|
||||
}
|
||||
}
|
||||
|
||||
@ -248,9 +268,18 @@ push_coroutine< T & >::control_block::valid() const noexcept {
|
||||
|
||||
// push_coroutine< void >
|
||||
|
||||
inline
|
||||
void
|
||||
push_coroutine< void >::control_block::destroy( control_block * cb) noexcept {
|
||||
boost::context::captured_context ctx = std::move( cb->ctx);
|
||||
// destroy control structure
|
||||
cb->~control_block();
|
||||
// destroy coroutine's stack
|
||||
ctx();
|
||||
}
|
||||
|
||||
template< typename StackAllocator, typename Fn >
|
||||
push_coroutine< void >::control_block::control_block( context::preallocated palloc, StackAllocator salloc, Fn && fn) :
|
||||
other{ nullptr },
|
||||
#if defined(BOOST_NO_CXX14_GENERIC_LAMBDAS)
|
||||
ctx{ std::allocator_arg, palloc, salloc,
|
||||
std::move(
|
||||
@ -305,6 +334,7 @@ push_coroutine< void >::control_block::control_block( context::preallocated pall
|
||||
return std::move( other->ctx);
|
||||
}},
|
||||
#endif
|
||||
other{ nullptr },
|
||||
state{ state_t::unwind },
|
||||
except{} {
|
||||
}
|
||||
@ -312,17 +342,17 @@ push_coroutine< void >::control_block::control_block( context::preallocated pall
|
||||
inline
|
||||
push_coroutine< void >::control_block::control_block( pull_coroutine< void >::control_block * cb,
|
||||
boost::context::captured_context & ctx_) noexcept :
|
||||
other{ cb },
|
||||
ctx{ std::move( ctx_) },
|
||||
other{ cb },
|
||||
state{ state_t::none },
|
||||
except{} {
|
||||
}
|
||||
|
||||
inline
|
||||
push_coroutine< void >::control_block::~control_block() {
|
||||
void
|
||||
push_coroutine< void >::control_block::deallocate() noexcept {
|
||||
if ( state_t::none != ( state & state_t::unwind) ) {
|
||||
// unwind coroutine stack
|
||||
ctx();
|
||||
destroy( this);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -25,21 +25,25 @@ namespace detail {
|
||||
|
||||
template< typename T >
|
||||
struct push_coroutine< T >::control_block {
|
||||
typename pull_coroutine< T >::control_block * other;
|
||||
boost::context::execution_context ctx;
|
||||
typename pull_coroutine< T >::control_block * other;
|
||||
state_t state;
|
||||
std::exception_ptr except;
|
||||
|
||||
static void destroy( control_block * cb) noexcept;
|
||||
|
||||
template< typename StackAllocator, typename Fn >
|
||||
control_block( context::preallocated, StackAllocator, Fn &&);
|
||||
|
||||
control_block( typename pull_coroutine< T >::control_block *, boost::context::execution_context const&) noexcept;
|
||||
|
||||
~control_block() noexcept;
|
||||
~control_block();
|
||||
|
||||
control_block( control_block &) = delete;
|
||||
control_block & operator=( control_block &) = delete;
|
||||
|
||||
void deallocate() noexcept;
|
||||
|
||||
void resume( T const&);
|
||||
|
||||
void resume( T &&);
|
||||
@ -49,42 +53,50 @@ 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 ctx;
|
||||
typename pull_coroutine< T & >::control_block * other;
|
||||
state_t state;
|
||||
std::exception_ptr except;
|
||||
|
||||
static void destroy( control_block * cb) noexcept;
|
||||
|
||||
template< typename StackAllocator, typename Fn >
|
||||
control_block( context::preallocated, StackAllocator, Fn &&);
|
||||
|
||||
control_block( typename pull_coroutine< T & >::control_block *, boost::context::execution_context const&) noexcept;
|
||||
|
||||
~control_block() noexcept;
|
||||
~control_block();
|
||||
|
||||
control_block( control_block &) = delete;
|
||||
control_block & operator=( control_block &) = delete;
|
||||
|
||||
void deallocate() noexcept;
|
||||
|
||||
void resume( T &);
|
||||
|
||||
bool valid() const noexcept;
|
||||
};
|
||||
|
||||
struct push_coroutine< void >::control_block {
|
||||
pull_coroutine< void >::control_block * other;
|
||||
boost::context::execution_context ctx;
|
||||
pull_coroutine< void >::control_block * other;
|
||||
state_t state;
|
||||
std::exception_ptr except;
|
||||
|
||||
static void destroy( control_block * cb) noexcept;
|
||||
|
||||
template< typename StackAllocator, typename Fn >
|
||||
control_block( context::preallocated, StackAllocator, Fn &&);
|
||||
|
||||
control_block( pull_coroutine< void >::control_block *, boost::context::execution_context const&) noexcept;
|
||||
|
||||
~control_block() noexcept;
|
||||
~control_block();
|
||||
|
||||
control_block( control_block &) = delete;
|
||||
control_block & operator=( control_block &) = delete;
|
||||
|
||||
void deallocate() noexcept;
|
||||
|
||||
void resume();
|
||||
|
||||
bool valid() const noexcept;
|
||||
|
@ -32,11 +32,18 @@ namespace detail {
|
||||
|
||||
// push_coroutine< T >
|
||||
|
||||
template< typename T >
|
||||
void
|
||||
push_coroutine< T >::control_block::destroy( control_block * cb) noexcept {
|
||||
boost::context::execution_context ctx = cb->ctx;
|
||||
// destroy control structure
|
||||
cb->~control_block();
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
template< typename StackAllocator, typename Fn >
|
||||
push_coroutine< T >::control_block::control_block( context::preallocated palloc, StackAllocator salloc,
|
||||
Fn && fn) :
|
||||
other{ nullptr },
|
||||
#if defined(BOOST_NO_CXX14_GENERIC_LAMBDAS)
|
||||
ctx{ std::allocator_arg, palloc, salloc,
|
||||
std::move(
|
||||
@ -97,6 +104,7 @@ push_coroutine< T >::control_block::control_block( context::preallocated palloc,
|
||||
BOOST_ASSERT_MSG( false, "push_coroutine is complete");
|
||||
}},
|
||||
#endif
|
||||
other{ nullptr },
|
||||
state{ state_t::unwind },
|
||||
except{} {
|
||||
// enter coroutine-fn in order to get other set
|
||||
@ -106,14 +114,14 @@ push_coroutine< T >::control_block::control_block( context::preallocated palloc,
|
||||
template< typename T >
|
||||
push_coroutine< T >::control_block::control_block( typename pull_coroutine< T >::control_block * cb,
|
||||
boost::context::execution_context const& ctx_) noexcept :
|
||||
other{ cb },
|
||||
ctx{ ctx_ },
|
||||
other{ cb },
|
||||
state{ state_t::none },
|
||||
except{} {
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
push_coroutine< T >::control_block::~control_block() noexcept {
|
||||
push_coroutine< T >::control_block::~control_block() {
|
||||
if ( state_t::none == ( state & state_t::complete) &&
|
||||
state_t::none != ( state & state_t::unwind) ) {
|
||||
// unwind coroutine stack
|
||||
@ -121,6 +129,14 @@ push_coroutine< T >::control_block::~control_block() noexcept {
|
||||
}
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
void
|
||||
push_coroutine< T >::control_block::deallocate() noexcept {
|
||||
if ( state_t::none != ( state & state_t::unwind) ) {
|
||||
destroy( this);
|
||||
}
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
void
|
||||
push_coroutine< T >::control_block::resume( T const& t) {
|
||||
@ -152,11 +168,18 @@ push_coroutine< T >::control_block::valid() const noexcept {
|
||||
|
||||
// push_coroutine< T & >
|
||||
|
||||
template< typename T >
|
||||
void
|
||||
push_coroutine< T & >::control_block::destroy( control_block * cb) noexcept {
|
||||
boost::context::execution_context ctx = cb->ctx;
|
||||
// destroy control structure
|
||||
cb->~control_block();
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
template< typename StackAllocator, typename Fn >
|
||||
push_coroutine< T & >::control_block::control_block( context::preallocated palloc, StackAllocator salloc,
|
||||
Fn && fn) :
|
||||
other{ nullptr },
|
||||
#if defined(BOOST_NO_CXX14_GENERIC_LAMBDAS)
|
||||
ctx{ std::allocator_arg, palloc, salloc,
|
||||
std::move(
|
||||
@ -217,6 +240,7 @@ push_coroutine< T & >::control_block::control_block( context::preallocated pallo
|
||||
BOOST_ASSERT_MSG( false, "push_coroutine is complete");
|
||||
}},
|
||||
#endif
|
||||
other{ nullptr },
|
||||
state{ state_t::unwind },
|
||||
except{} {
|
||||
// enter coroutine-fn in order to get other set
|
||||
@ -226,14 +250,14 @@ push_coroutine< T & >::control_block::control_block( context::preallocated pallo
|
||||
template< typename T >
|
||||
push_coroutine< T & >::control_block::control_block( typename pull_coroutine< T & >::control_block * cb,
|
||||
boost::context::execution_context const& ctx_) noexcept :
|
||||
other{ cb },
|
||||
ctx{ ctx_ },
|
||||
other{ cb },
|
||||
state{ state_t::none },
|
||||
except{} {
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
push_coroutine< T & >::control_block::~control_block() noexcept {
|
||||
push_coroutine< T & >::control_block::~control_block() {
|
||||
if ( state_t::none == ( state & state_t::complete) &&
|
||||
state_t::none != ( state & state_t::unwind) ) {
|
||||
// unwind coroutine stack
|
||||
@ -241,6 +265,14 @@ push_coroutine< T & >::control_block::~control_block() noexcept {
|
||||
}
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
void
|
||||
push_coroutine< T & >::control_block::deallocate() noexcept {
|
||||
if ( state_t::none != ( state & state_t::unwind) ) {
|
||||
destroy( this);
|
||||
}
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
void
|
||||
push_coroutine< T & >::control_block::resume( T & t) {
|
||||
@ -261,9 +293,16 @@ push_coroutine< T & >::control_block::valid() const noexcept {
|
||||
|
||||
// push_coroutine< void >
|
||||
|
||||
inline
|
||||
void
|
||||
push_coroutine< void >::control_block::destroy( control_block * cb) noexcept {
|
||||
boost::context::execution_context ctx = cb->ctx;
|
||||
// destroy control structure
|
||||
cb->~control_block();
|
||||
}
|
||||
|
||||
template< typename StackAllocator, typename Fn >
|
||||
push_coroutine< void >::control_block::control_block( context::preallocated palloc, StackAllocator salloc, Fn && fn) :
|
||||
other{ nullptr },
|
||||
#if defined(BOOST_NO_CXX14_GENERIC_LAMBDAS)
|
||||
ctx{ std::allocator_arg, palloc, salloc,
|
||||
std::move(
|
||||
@ -321,6 +360,7 @@ push_coroutine< void >::control_block::control_block( context::preallocated pall
|
||||
BOOST_ASSERT_MSG( false, "push_coroutine is complete");
|
||||
}},
|
||||
#endif
|
||||
other{ nullptr },
|
||||
state{ state_t::unwind },
|
||||
except{} {
|
||||
// enter coroutine-fn in order to get other set
|
||||
@ -330,14 +370,14 @@ push_coroutine< void >::control_block::control_block( context::preallocated pall
|
||||
inline
|
||||
push_coroutine< void >::control_block::control_block( pull_coroutine< void >::control_block * cb,
|
||||
boost::context::execution_context const& ctx_) noexcept :
|
||||
other{ cb },
|
||||
ctx{ ctx_ },
|
||||
other{ cb },
|
||||
state{ state_t::none },
|
||||
except{} {
|
||||
}
|
||||
|
||||
inline
|
||||
push_coroutine< void >::control_block::~control_block() noexcept {
|
||||
push_coroutine< void >::control_block::~control_block() {
|
||||
if ( state_t::none == ( state & state_t::complete) &&
|
||||
state_t::none != ( state & state_t::unwind) ) {
|
||||
// unwind coroutine stack
|
||||
@ -345,6 +385,14 @@ push_coroutine< void >::control_block::~control_block() noexcept {
|
||||
}
|
||||
}
|
||||
|
||||
inline
|
||||
void
|
||||
push_coroutine< void >::control_block::deallocate() noexcept {
|
||||
if ( state_t::none != ( state & state_t::unwind) ) {
|
||||
destroy( this);
|
||||
}
|
||||
}
|
||||
|
||||
inline
|
||||
void
|
||||
push_coroutine< void >::control_block::resume() {
|
||||
|
@ -50,7 +50,7 @@ push_coroutine< T >::push_coroutine( StackAllocator salloc, Fn && fn) :
|
||||
template< typename T >
|
||||
push_coroutine< T >::~push_coroutine() noexcept {
|
||||
if ( nullptr != cb_) {
|
||||
cb_->~control_block();
|
||||
cb_->deallocate();
|
||||
}
|
||||
}
|
||||
|
||||
@ -110,7 +110,7 @@ push_coroutine< T & >::push_coroutine( StackAllocator salloc, Fn && fn) :
|
||||
template< typename T >
|
||||
push_coroutine< T & >::~push_coroutine() noexcept {
|
||||
if ( nullptr != cb_) {
|
||||
cb_->~control_block();
|
||||
cb_->deallocate();
|
||||
}
|
||||
}
|
||||
|
||||
@ -161,7 +161,7 @@ push_coroutine< void >::push_coroutine( StackAllocator salloc, Fn && fn) :
|
||||
inline
|
||||
push_coroutine< void >::~push_coroutine() noexcept {
|
||||
if ( nullptr != cb_) {
|
||||
cb_->~control_block();
|
||||
cb_->deallocate();
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user