fix deallocation

- ~control_block() must be run before coroutine's
  stack is destroyed
This commit is contained in:
Oliver Kowalke 2016-01-03 20:38:31 +01:00
parent 302e484e8e
commit 3d76707ea1
10 changed files with 278 additions and 80 deletions

View File

@ -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;

View File

@ -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);
}
}

View File

@ -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;

View File

@ -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() {

View File

@ -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();
}
}

View File

@ -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;

View File

@ -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);
}
}

View File

@ -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;

View File

@ -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() {

View File

@ -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();
}
}