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