mirror of
https://github.com/boostorg/coroutine2.git
synced 2025-05-09 23:24:01 +00:00
use of captured_context
This commit is contained in:
parent
37222c014a
commit
6796caa2c7
@ -13,7 +13,8 @@
|
||||
|
||||
#include <boost/coroutine2/all.hpp>
|
||||
|
||||
struct node {
|
||||
struct node
|
||||
{
|
||||
typedef std::shared_ptr< node > ptr_t;
|
||||
|
||||
// Each tree node has an optional left subtree, an optional right subtree
|
||||
@ -24,24 +25,26 @@ struct node {
|
||||
|
||||
// construct leaf
|
||||
node(const std::string& v):
|
||||
left(),right(),value(v) {
|
||||
}
|
||||
|
||||
left(),right(),value(v)
|
||||
{}
|
||||
// construct nonleaf
|
||||
node(ptr_t l, const std::string& v, ptr_t r):
|
||||
left(l),right(r),value(v) {
|
||||
}
|
||||
left(l),right(r),value(v)
|
||||
{}
|
||||
|
||||
static ptr_t create(const std::string& v) {
|
||||
static ptr_t create(const std::string& v)
|
||||
{
|
||||
return ptr_t(new node(v));
|
||||
}
|
||||
|
||||
static ptr_t create(ptr_t l, const std::string& v, ptr_t r) {
|
||||
static ptr_t create(ptr_t l, const std::string& v, ptr_t r)
|
||||
{
|
||||
return ptr_t(new node(l, v, r));
|
||||
}
|
||||
};
|
||||
|
||||
node::ptr_t create_left_tree_from(const std::string& root) {
|
||||
node::ptr_t create_left_tree_from(const std::string& root)
|
||||
{
|
||||
/* --------
|
||||
root
|
||||
/ \
|
||||
@ -59,7 +62,8 @@ node::ptr_t create_left_tree_from(const std::string& root) {
|
||||
node::create("e"));
|
||||
}
|
||||
|
||||
node::ptr_t create_right_tree_from(const std::string& root) {
|
||||
node::ptr_t create_right_tree_from(const std::string& root)
|
||||
{
|
||||
/* --------
|
||||
root
|
||||
/ \
|
||||
@ -78,7 +82,8 @@ node::ptr_t create_right_tree_from(const std::string& root) {
|
||||
}
|
||||
|
||||
// recursively walk the tree, delivering values in order
|
||||
void traverse(node::ptr_t n, boost::coroutines2::coroutine<std::string>::push_type& out) {
|
||||
void traverse(node::ptr_t n, boost::coroutines2::coroutine<std::string>::push_type& out)
|
||||
{
|
||||
if (n->left)
|
||||
traverse(n->left,out);
|
||||
out(n->value);
|
||||
@ -86,81 +91,92 @@ void traverse(node::ptr_t n, boost::coroutines2::coroutine<std::string>::push_ty
|
||||
traverse(n->right,out);
|
||||
}
|
||||
|
||||
int main() {
|
||||
int main()
|
||||
{
|
||||
{
|
||||
node::ptr_t left_d(create_left_tree_from("d"));
|
||||
boost::coroutines2::coroutine<std::string>::pull_type left_d_reader(
|
||||
[&]( boost::coroutines2::coroutine<std::string>::push_type & out) {
|
||||
traverse(left_d,out);
|
||||
});
|
||||
std::cout << "left tree from d:\n";
|
||||
std::copy(begin(left_d_reader),
|
||||
end(left_d_reader),
|
||||
std::ostream_iterator<std::string>(std::cout, " "));
|
||||
std::cout << std::endl;
|
||||
|
||||
node::ptr_t right_b(create_right_tree_from("b"));
|
||||
boost::coroutines2::coroutine<std::string>::pull_type right_b_reader(
|
||||
[&]( boost::coroutines2::coroutine<std::string>::push_type & out) {
|
||||
traverse(right_b,out);
|
||||
});
|
||||
std::cout << "right tree from b:\n";
|
||||
std::copy(begin(right_b_reader),
|
||||
end(right_b_reader),
|
||||
std::ostream_iterator<std::string>(std::cout, " "));
|
||||
std::cout << std::endl;
|
||||
|
||||
node::ptr_t right_x(create_right_tree_from("x"));
|
||||
boost::coroutines2::coroutine<std::string>::pull_type right_x_reader(
|
||||
[&]( boost::coroutines2::coroutine<std::string>::push_type & out) {
|
||||
traverse(right_x,out);
|
||||
});
|
||||
std::cout << "right tree from x:\n";
|
||||
std::copy(begin(right_x_reader),
|
||||
end(right_x_reader),
|
||||
std::ostream_iterator<std::string>(std::cout, " "));
|
||||
std::cout << std::endl;
|
||||
{
|
||||
boost::coroutines2::coroutine<std::string>::pull_type left_d_reader(
|
||||
[&]( boost::coroutines2::coroutine<std::string>::push_type & out) {
|
||||
traverse(left_d,out);
|
||||
});
|
||||
std::cout << "left tree from d:\n";
|
||||
std::copy(begin(left_d_reader),
|
||||
end(left_d_reader),
|
||||
std::ostream_iterator<std::string>(std::cout, " "));
|
||||
std::cout << std::endl;
|
||||
|
||||
boost::coroutines2::coroutine<std::string>::pull_type right_b_reader(
|
||||
[&]( boost::coroutines2::coroutine<std::string>::push_type & out) {
|
||||
traverse(right_b,out);
|
||||
});
|
||||
std::cout << "right tree from b:\n";
|
||||
std::copy(begin(right_b_reader),
|
||||
end(right_b_reader),
|
||||
std::ostream_iterator<std::string>(std::cout, " "));
|
||||
std::cout << std::endl;
|
||||
|
||||
boost::coroutines2::coroutine<std::string>::pull_type right_x_reader(
|
||||
[&]( boost::coroutines2::coroutine<std::string>::push_type & out) {
|
||||
traverse(right_x,out);
|
||||
});
|
||||
std::cout << "right tree from x:\n";
|
||||
std::copy(begin(right_x_reader),
|
||||
end(right_x_reader),
|
||||
std::ostream_iterator<std::string>(std::cout, " "));
|
||||
std::cout << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
node::ptr_t left_d(create_left_tree_from("d"));
|
||||
boost::coroutines2::coroutine<std::string>::pull_type left_d_reader(
|
||||
[&]( boost::coroutines2::coroutine<std::string>::push_type & out) {
|
||||
traverse(left_d,out);
|
||||
});
|
||||
|
||||
node::ptr_t right_b(create_right_tree_from("b"));
|
||||
boost::coroutines2::coroutine<std::string>::pull_type right_b_reader(
|
||||
[&]( boost::coroutines2::coroutine<std::string>::push_type & out) {
|
||||
traverse(right_b,out);
|
||||
});
|
||||
{
|
||||
boost::coroutines2::coroutine<std::string>::pull_type left_d_reader(
|
||||
[&]( boost::coroutines2::coroutine<std::string>::push_type & out) {
|
||||
traverse(left_d,out);
|
||||
});
|
||||
|
||||
std::cout << "left tree from d == right tree from b? "
|
||||
<< std::boolalpha
|
||||
<< std::equal(begin(left_d_reader),
|
||||
end(left_d_reader),
|
||||
begin(right_b_reader))
|
||||
<< std::endl;
|
||||
boost::coroutines2::coroutine<std::string>::pull_type right_b_reader(
|
||||
[&]( boost::coroutines2::coroutine<std::string>::push_type & out) {
|
||||
traverse(right_b,out);
|
||||
});
|
||||
|
||||
std::cout << "left tree from d == right tree from b? "
|
||||
<< std::boolalpha
|
||||
<< std::equal(begin(left_d_reader),
|
||||
end(left_d_reader),
|
||||
begin(right_b_reader))
|
||||
<< std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
node::ptr_t left_d(create_left_tree_from("d"));
|
||||
boost::coroutines2::coroutine<std::string>::pull_type left_d_reader(
|
||||
[&]( boost::coroutines2::coroutine<std::string>::push_type & out) {
|
||||
traverse(left_d,out);
|
||||
});
|
||||
|
||||
node::ptr_t right_x(create_right_tree_from("x"));
|
||||
boost::coroutines2::coroutine<std::string>::pull_type right_x_reader(
|
||||
[&]( boost::coroutines2::coroutine<std::string>::push_type & out) {
|
||||
traverse(right_x,out);
|
||||
});
|
||||
{
|
||||
boost::coroutines2::coroutine<std::string>::pull_type left_d_reader(
|
||||
[&]( boost::coroutines2::coroutine<std::string>::push_type & out) {
|
||||
traverse(left_d,out);
|
||||
});
|
||||
|
||||
std::cout << "left tree from d == right tree from x? "
|
||||
<< std::boolalpha
|
||||
<< std::equal(begin(left_d_reader),
|
||||
end(left_d_reader),
|
||||
begin(right_x_reader))
|
||||
<< std::endl;
|
||||
boost::coroutines2::coroutine<std::string>::pull_type right_x_reader(
|
||||
[&]( boost::coroutines2::coroutine<std::string>::push_type & out) {
|
||||
traverse(right_x,out);
|
||||
});
|
||||
|
||||
std::cout << "left tree from d == right tree from x? "
|
||||
<< std::boolalpha
|
||||
<< std::equal(begin(left_d_reader),
|
||||
end(left_d_reader),
|
||||
begin(right_x_reader))
|
||||
<< std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
std::cout << "Done" << std::endl;
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
@ -28,14 +28,24 @@ class push_coroutine;
|
||||
#include <boost/coroutine2/detail/pull_coroutine.hpp>
|
||||
#include <boost/coroutine2/detail/push_coroutine.hpp>
|
||||
|
||||
#include <boost/coroutine2/detail/pull_control_block.hpp>
|
||||
#include <boost/coroutine2/detail/push_control_block.hpp>
|
||||
#if ! defined(BOOST_USE_SEGMENTED_STACKS)
|
||||
#include <boost/coroutine2/detail/pull_control_block_cc.hpp>
|
||||
#include <boost/coroutine2/detail/push_control_block_cc.hpp>
|
||||
#else
|
||||
#include <boost/coroutine2/detail/pull_control_block_ec.hpp>
|
||||
#include <boost/coroutine2/detail/push_control_block_ec.hpp>
|
||||
#endif
|
||||
|
||||
#include <boost/coroutine2/detail/pull_coroutine.ipp>
|
||||
#include <boost/coroutine2/detail/push_coroutine.ipp>
|
||||
|
||||
#include <boost/coroutine2/detail/pull_control_block.ipp>
|
||||
#include <boost/coroutine2/detail/push_control_block.ipp>
|
||||
#if ! defined(BOOST_USE_SEGMENTED_STACKS)
|
||||
#include <boost/coroutine2/detail/pull_control_block_cc.ipp>
|
||||
#include <boost/coroutine2/detail/push_control_block_cc.ipp>
|
||||
#else
|
||||
#include <boost/coroutine2/detail/pull_control_block_ec.ipp>
|
||||
#include <boost/coroutine2/detail/push_control_block_ec.ipp>
|
||||
#endif
|
||||
|
||||
#ifdef BOOST_HAS_ABI_HEADERS
|
||||
# include BOOST_ABI_SUFFIX
|
||||
|
@ -24,6 +24,12 @@ namespace detail {
|
||||
|
||||
struct forced_unwind {};
|
||||
|
||||
inline
|
||||
void * unwind_coroutine( void * data) {
|
||||
throw forced_unwind{};
|
||||
return data;
|
||||
}
|
||||
|
||||
}}}
|
||||
|
||||
#ifdef BOOST_HAS_ABI_HEADERS
|
||||
|
98
include/boost/coroutine2/detail/pull_control_block_cc.hpp
Normal file
98
include/boost/coroutine2/detail/pull_control_block_cc.hpp
Normal file
@ -0,0 +1,98 @@
|
||||
|
||||
// Copyright Oliver Kowalke 2014.
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_COROUTINES2_DETAIL_PULL_CONTROL_BLOCK_HPP
|
||||
#define BOOST_COROUTINES2_DETAIL_PULL_CONTROL_BLOCK_HPP
|
||||
|
||||
#include <exception>
|
||||
#include <type_traits>
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/context/captured_context.hpp>
|
||||
|
||||
|
||||
#ifdef BOOST_HAS_ABI_HEADERS
|
||||
# include BOOST_ABI_PREFIX
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
namespace coroutines2 {
|
||||
namespace detail {
|
||||
|
||||
template< typename T >
|
||||
struct pull_coroutine< T >::control_block {
|
||||
typename push_coroutine< T >::control_block * other;
|
||||
boost::context::captured_context ctx;
|
||||
std::exception_ptr except;
|
||||
bool bvalid;
|
||||
typename std::aligned_storage< sizeof( T), alignof( T) >::type storage;
|
||||
|
||||
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 resume();
|
||||
|
||||
void set( T *);
|
||||
|
||||
T & get() noexcept;
|
||||
|
||||
bool valid() const noexcept;
|
||||
};
|
||||
|
||||
template< typename T >
|
||||
struct pull_coroutine< T & >::control_block {
|
||||
typename push_coroutine< T & >::control_block * other;
|
||||
boost::context::captured_context ctx;
|
||||
std::exception_ptr except;
|
||||
T * t;
|
||||
|
||||
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 &) = delete;
|
||||
control_block & operator=( control_block &) = delete;
|
||||
|
||||
void resume();
|
||||
|
||||
T & get() noexcept;
|
||||
|
||||
bool valid() const noexcept;
|
||||
};
|
||||
|
||||
struct pull_coroutine< void >::control_block {
|
||||
push_coroutine< void >::control_block * other;
|
||||
boost::context::captured_context ctx;
|
||||
std::exception_ptr except;
|
||||
|
||||
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 &) = delete;
|
||||
control_block & operator=( control_block &) = delete;
|
||||
|
||||
void resume();
|
||||
|
||||
bool valid() const noexcept;
|
||||
};
|
||||
|
||||
}}}
|
||||
|
||||
#ifdef BOOST_HAS_ABI_HEADERS
|
||||
# include BOOST_ABI_SUFFIX
|
||||
#endif
|
||||
|
||||
#endif // BOOST_COROUTINES2_DETAIL_PULL_CONTROL_BLOCK_HPP
|
332
include/boost/coroutine2/detail/pull_control_block_cc.ipp
Normal file
332
include/boost/coroutine2/detail/pull_control_block_cc.ipp
Normal file
@ -0,0 +1,332 @@
|
||||
|
||||
// Copyright Oliver Kowalke 2014.
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_COROUTINES2_DETAIL_PULL_CONTROL_BLOCK_IPP
|
||||
#define BOOST_COROUTINES2_DETAIL_PULL_CONTROL_BLOCK_IPP
|
||||
|
||||
#include <algorithm>
|
||||
#include <exception>
|
||||
#include <memory>
|
||||
#include <tuple>
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/config.hpp>
|
||||
|
||||
#include <boost/context/captured_context.hpp>
|
||||
|
||||
#include <boost/coroutine2/detail/config.hpp>
|
||||
#include <boost/coroutine2/detail/forced_unwind.hpp>
|
||||
|
||||
#ifdef BOOST_HAS_ABI_HEADERS
|
||||
# include BOOST_ABI_PREFIX
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
namespace coroutines2 {
|
||||
namespace detail {
|
||||
|
||||
// pull_coroutine< T >
|
||||
|
||||
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(
|
||||
std::bind(
|
||||
[this]( typename std::decay< Fn >::type & fn_, boost::context::captured_context ctx, void *) mutable {
|
||||
// create synthesized push_coroutine< T >
|
||||
typename push_coroutine< T >::control_block synthesized_cb{ this, ctx };
|
||||
push_coroutine< T > synthesized{ & synthesized_cb };
|
||||
other = & synthesized_cb;
|
||||
try {
|
||||
auto fn = std::move( fn_);
|
||||
// call coroutine-fn with synthesized push_coroutine as argument
|
||||
fn( synthesized);
|
||||
} catch ( boost::context::detail::forced_unwind const&) {
|
||||
throw;
|
||||
} catch (...) {
|
||||
// store other exceptions in exception-pointer
|
||||
except = std::current_exception();
|
||||
}
|
||||
// jump back to ctx
|
||||
return std::move( other->ctx);
|
||||
},
|
||||
std::forward< Fn >( fn),
|
||||
std::placeholders::_1,
|
||||
std::placeholders::_2))},
|
||||
#else
|
||||
ctx{ std::allocator_arg, palloc, salloc,
|
||||
[this,fn_=std::forward< Fn >( fn)]( boost::context::captured_context ctx, void *) mutable {
|
||||
// create synthesized push_coroutine< T >
|
||||
typename push_coroutine< T >::control_block synthesized_cb{ this, ctx };
|
||||
push_coroutine< T > synthesized{ & synthesized_cb };
|
||||
other = & synthesized_cb;
|
||||
try {
|
||||
auto fn = std::move( fn_);
|
||||
// call coroutine-fn with synthesized push_coroutine as argument
|
||||
fn( synthesized);
|
||||
} catch ( boost::context::detail::forced_unwind const&) {
|
||||
throw;
|
||||
} catch (...) {
|
||||
// store other exceptions in exception-pointer
|
||||
except = std::current_exception();
|
||||
}
|
||||
// jump back to ctx
|
||||
return std::move( other->ctx);
|
||||
}},
|
||||
#endif
|
||||
except{},
|
||||
bvalid{ false },
|
||||
storage{} {
|
||||
// enter coroutine-fn in order to have first value available after ctor (of `*this`) returns
|
||||
void * data = nullptr;
|
||||
std::tie( ctx, data) = ctx();
|
||||
set( static_cast< T * >( data) );
|
||||
}
|
||||
|
||||
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_) },
|
||||
except{},
|
||||
bvalid{ false },
|
||||
storage{} {
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
pull_coroutine< T >::control_block::~control_block() {
|
||||
// destroy data if set
|
||||
if ( bvalid) {
|
||||
reinterpret_cast< T * >( std::addressof( storage) )->~T();
|
||||
}
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
void
|
||||
pull_coroutine< T >::control_block::resume() {
|
||||
void * data;
|
||||
std::tie( ctx, data) = ctx();
|
||||
set( static_cast< T * >( data) );
|
||||
if ( except) {
|
||||
std::rethrow_exception( except);
|
||||
}
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
void
|
||||
pull_coroutine< T >::control_block::set( T * t) {
|
||||
// destroy data if set
|
||||
if ( bvalid) {
|
||||
reinterpret_cast< T * >( std::addressof( storage) )->~T();
|
||||
}
|
||||
if ( nullptr != t) {
|
||||
::new ( static_cast< void * >( std::addressof( storage) ) ) T( std::move( * t) );
|
||||
bvalid = true;
|
||||
} else {
|
||||
bvalid = false;
|
||||
}
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
T &
|
||||
pull_coroutine< T >::control_block::get() noexcept {
|
||||
return * reinterpret_cast< T * >( std::addressof( storage) );
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
bool
|
||||
pull_coroutine< T >::control_block::valid() const noexcept {
|
||||
return nullptr != other && ctx && bvalid;
|
||||
}
|
||||
|
||||
|
||||
// pull_coroutine< T & >
|
||||
|
||||
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(
|
||||
std::bind(
|
||||
[this]( typename std::decay< Fn >::type & fn_, boost::context::captured_context ctx, void *) mutable {
|
||||
// create synthesized push_coroutine< T >
|
||||
typename push_coroutine< T & >::control_block synthesized_cb{ this, ctx };
|
||||
push_coroutine< T & > synthesized{ & synthesized_cb };
|
||||
other = & synthesized_cb;
|
||||
try {
|
||||
auto fn = std::move( fn_);
|
||||
// call coroutine-fn with synthesized push_coroutine as argument
|
||||
fn( synthesized);
|
||||
} catch ( boost::context::detail::forced_unwind const&) {
|
||||
throw;
|
||||
} catch (...) {
|
||||
// store other exceptions in exception-pointer
|
||||
except = std::current_exception();
|
||||
}
|
||||
// jump back to ctx
|
||||
return std::move( other->ctx);
|
||||
},
|
||||
std::forward< Fn >( fn),
|
||||
std::placeholders::_1,
|
||||
std::placeholders::_2))},
|
||||
#else
|
||||
ctx{ std::allocator_arg, palloc, salloc,
|
||||
[this,fn_=std::forward< Fn >( fn)]( boost::context::captured_context ctx, void *) mutable {
|
||||
// create synthesized push_coroutine< T >
|
||||
typename push_coroutine< T & >::control_block synthesized_cb{ this, ctx };
|
||||
push_coroutine< T & > synthesized{ & synthesized_cb };
|
||||
other = & synthesized_cb;
|
||||
try {
|
||||
auto fn = std::move( fn_);
|
||||
// call coroutine-fn with synthesized push_coroutine as argument
|
||||
fn( synthesized);
|
||||
} catch ( boost::context::detail::forced_unwind const&) {
|
||||
throw;
|
||||
} catch (...) {
|
||||
// store other exceptions in exception-pointer
|
||||
except = std::current_exception();
|
||||
}
|
||||
// jump back to ctx
|
||||
return std::move( other->ctx);
|
||||
}},
|
||||
#endif
|
||||
except{},
|
||||
t{ nullptr } {
|
||||
// enter coroutine-fn in order to have first value available after ctor (of `*this`) returns
|
||||
void * data = nullptr;
|
||||
std::tie( ctx, data) = ctx();
|
||||
t = static_cast< T * >( data);
|
||||
}
|
||||
|
||||
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_) },
|
||||
except{},
|
||||
t{ nullptr } {
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
void
|
||||
pull_coroutine< T & >::control_block::resume() {
|
||||
void * data;
|
||||
std::tie( ctx, data) = ctx();
|
||||
t = static_cast< T * >( data);
|
||||
if ( except) {
|
||||
std::rethrow_exception( except);
|
||||
}
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
T &
|
||||
pull_coroutine< T & >::control_block::get() noexcept {
|
||||
return * static_cast< T * >( t);
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
bool
|
||||
pull_coroutine< T & >::control_block::valid() const noexcept {
|
||||
return nullptr != other && ctx && nullptr != t;
|
||||
}
|
||||
|
||||
|
||||
// pull_coroutine< void >
|
||||
|
||||
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(
|
||||
std::bind(
|
||||
[this]( typename std::decay< Fn >::type & fn_, boost::context::captured_context ctx, void *) mutable {
|
||||
// create synthesized push_coroutine< T >
|
||||
typename push_coroutine< void >::control_block synthesized_cb{ this, ctx };
|
||||
push_coroutine< void > synthesized{ & synthesized_cb };
|
||||
other = & synthesized_cb;
|
||||
try {
|
||||
auto fn = std::move( fn_);
|
||||
// call coroutine-fn with synthesized push_coroutine as argument
|
||||
fn( synthesized);
|
||||
} catch ( boost::context::detail::forced_unwind const&) {
|
||||
throw;
|
||||
} catch (...) {
|
||||
// store other exceptions in exception-pointer
|
||||
except = std::current_exception();
|
||||
}
|
||||
// jump back to ctx
|
||||
return std::move( other->ctx);
|
||||
},
|
||||
std::forward< Fn >( fn),
|
||||
std::placeholders::_1,
|
||||
std::placeholders::_2))},
|
||||
#else
|
||||
ctx{ std::allocator_arg, palloc, salloc,
|
||||
[this,fn_=std::forward< Fn >( fn)]( boost::context::captured_context ctx, void *) mutable {
|
||||
// create synthesized push_coroutine< T >
|
||||
typename push_coroutine< void >::control_block synthesized_cb{ this, ctx };
|
||||
push_coroutine< void > synthesized{ & synthesized_cb };
|
||||
other = & synthesized_cb;
|
||||
try {
|
||||
auto fn = std::move( fn_);
|
||||
// call coroutine-fn with synthesized push_coroutine as argument
|
||||
fn( synthesized);
|
||||
} catch ( boost::context::detail::forced_unwind const&) {
|
||||
throw;
|
||||
} catch (...) {
|
||||
// store other exceptions in exception-pointer
|
||||
except = std::current_exception();
|
||||
}
|
||||
// jump back to ctx
|
||||
return std::move( other->ctx);
|
||||
}},
|
||||
#endif
|
||||
except{} {
|
||||
// enter coroutine-fn in order to have first value available after ctor (of `*this`) returns
|
||||
void * ignored = nullptr;
|
||||
std::tie( ctx, ignored) = ctx();
|
||||
}
|
||||
|
||||
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_) },
|
||||
except{} {
|
||||
}
|
||||
|
||||
inline
|
||||
void
|
||||
pull_coroutine< void >::control_block::resume() {
|
||||
void * ignored;
|
||||
std::tie( ctx, ignored) = ctx();
|
||||
if ( except) {
|
||||
std::rethrow_exception( except);
|
||||
}
|
||||
}
|
||||
|
||||
inline
|
||||
bool
|
||||
pull_coroutine< void >::control_block::valid() const noexcept {
|
||||
return nullptr != other && ctx;
|
||||
}
|
||||
|
||||
}}}
|
||||
|
||||
#ifdef BOOST_HAS_ABI_HEADERS
|
||||
# include BOOST_ABI_SUFFIX
|
||||
#endif
|
||||
|
||||
#endif // BOOST_COROUTINES2_DETAIL_PULL_CONTROL_BLOCK_IPP
|
@ -38,7 +38,7 @@ struct pull_coroutine< T >::control_block {
|
||||
|
||||
control_block( typename push_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;
|
||||
@ -65,7 +65,7 @@ struct pull_coroutine< T & >::control_block {
|
||||
|
||||
control_block( typename push_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;
|
||||
@ -88,7 +88,7 @@ struct pull_coroutine< void >::control_block {
|
||||
|
||||
control_block( push_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;
|
@ -108,12 +108,11 @@ pull_coroutine< T >::control_block::control_block( typename push_coroutine< 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) &&
|
||||
state_t::none != ( state & state_t::unwind) ) {
|
||||
// set early-exit flag
|
||||
state |= state_t::early_exit;
|
||||
ctx();
|
||||
// unwind coroutine stack
|
||||
ctx( context::exec_ontop_arg, unwind_coroutine);
|
||||
}
|
||||
// destroy data if it set
|
||||
if ( bvalid) {
|
||||
@ -129,10 +128,6 @@ pull_coroutine< T >::control_block::resume() {
|
||||
if ( except) {
|
||||
std::rethrow_exception( except);
|
||||
}
|
||||
// test early-exit-flag
|
||||
if ( state_t::none != ( other->state & state_t::early_exit) ) {
|
||||
throw forced_unwind();
|
||||
}
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
@ -243,9 +238,8 @@ template< typename T >
|
||||
pull_coroutine< T & >::control_block::~control_block() noexcept {
|
||||
if ( state_t::none == ( state & state_t::complete) &&
|
||||
state_t::none != ( state & state_t::unwind) ) {
|
||||
// set early-exit flag
|
||||
state |= state_t::early_exit;
|
||||
ctx();
|
||||
// unwind coroutine stack
|
||||
ctx( context::exec_ontop_arg, unwind_coroutine);
|
||||
}
|
||||
}
|
||||
|
||||
@ -257,10 +251,6 @@ pull_coroutine< T & >::control_block::resume() {
|
||||
if ( except) {
|
||||
std::rethrow_exception( except);
|
||||
}
|
||||
// test early-exit-flag
|
||||
if ( state_t::none != ( other->state & state_t::early_exit) ) {
|
||||
throw forced_unwind();
|
||||
}
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
@ -353,9 +343,8 @@ inline
|
||||
pull_coroutine< void >::control_block::~control_block() noexcept {
|
||||
if ( state_t::none == ( state & state_t::complete) &&
|
||||
state_t::none != ( state & state_t::unwind) ) {
|
||||
// set early-exit flag
|
||||
state |= state_t::early_exit;
|
||||
ctx();
|
||||
// unwind coroutine stack
|
||||
ctx( context::exec_ontop_arg, unwind_coroutine);
|
||||
}
|
||||
}
|
||||
|
||||
@ -367,10 +356,6 @@ pull_coroutine< void >::control_block::resume() {
|
||||
if ( except) {
|
||||
std::rethrow_exception( except);
|
||||
}
|
||||
// test early-exit-flag
|
||||
if ( state_t::none != ( other->state & state_t::early_exit) ) {
|
||||
throw forced_unwind();
|
||||
}
|
||||
}
|
||||
|
||||
inline
|
88
include/boost/coroutine2/detail/push_control_block_cc.hpp
Normal file
88
include/boost/coroutine2/detail/push_control_block_cc.hpp
Normal file
@ -0,0 +1,88 @@
|
||||
|
||||
// Copyright Oliver Kowalke 2014.
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_COROUTINES2_DETAIL_PUSH_CONTROL_BLOCK_HPP
|
||||
#define BOOST_COROUTINES2_DETAIL_PUSH_CONTROL_BLOCK_HPP
|
||||
|
||||
#include <exception>
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/context/captured_context.hpp>
|
||||
|
||||
|
||||
#ifdef BOOST_HAS_ABI_HEADERS
|
||||
# include BOOST_ABI_PREFIX
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
namespace coroutines2 {
|
||||
namespace detail {
|
||||
|
||||
template< typename T >
|
||||
struct push_coroutine< T >::control_block {
|
||||
typename pull_coroutine< T >::control_block * other;
|
||||
boost::context::captured_context ctx;
|
||||
std::exception_ptr except;
|
||||
|
||||
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 &) = delete;
|
||||
control_block & operator=( control_block &) = delete;
|
||||
|
||||
void resume( T const&);
|
||||
|
||||
void resume( T &&);
|
||||
|
||||
bool valid() const noexcept;
|
||||
};
|
||||
|
||||
template< typename T >
|
||||
struct push_coroutine< T & >::control_block {
|
||||
typename pull_coroutine< T & >::control_block * other;
|
||||
boost::context::captured_context ctx;
|
||||
std::exception_ptr except;
|
||||
|
||||
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 &) = delete;
|
||||
control_block & operator=( control_block &) = delete;
|
||||
|
||||
void resume( T &);
|
||||
|
||||
bool valid() const noexcept;
|
||||
};
|
||||
|
||||
struct push_coroutine< void >::control_block {
|
||||
pull_coroutine< void >::control_block * other;
|
||||
boost::context::captured_context ctx;
|
||||
std::exception_ptr except;
|
||||
|
||||
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 &) = delete;
|
||||
control_block & operator=( control_block &) = delete;
|
||||
|
||||
void resume();
|
||||
|
||||
bool valid() const noexcept;
|
||||
};
|
||||
|
||||
}}}
|
||||
|
||||
#ifdef BOOST_HAS_ABI_HEADERS
|
||||
# include BOOST_ABI_SUFFIX
|
||||
#endif
|
||||
|
||||
#endif // BOOST_COROUTINES2_DETAIL_PUSH_CONTROL_BLOCK_HPP
|
297
include/boost/coroutine2/detail/push_control_block_cc.ipp
Normal file
297
include/boost/coroutine2/detail/push_control_block_cc.ipp
Normal file
@ -0,0 +1,297 @@
|
||||
|
||||
// Copyright Oliver Kowalke 2014.
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_COROUTINES2_DETAIL_PUSH_CONTROL_BLOCK_IPP
|
||||
#define BOOST_COROUTINES2_DETAIL_PUSH_CONTROL_BLOCK_IPP
|
||||
|
||||
#include <algorithm>
|
||||
#include <exception>
|
||||
#include <memory>
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/config.hpp>
|
||||
|
||||
#include <boost/context/captured_context.hpp>
|
||||
|
||||
#include <boost/coroutine2/detail/config.hpp>
|
||||
#include <boost/coroutine2/detail/forced_unwind.hpp>
|
||||
|
||||
#ifdef BOOST_HAS_ABI_HEADERS
|
||||
# include BOOST_ABI_PREFIX
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
namespace coroutines2 {
|
||||
namespace detail {
|
||||
|
||||
// push_coroutine< T >
|
||||
|
||||
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(
|
||||
std::bind(
|
||||
[this]( typename std::decay< Fn >::type & fn_, boost::context::captured_context ctx, void * data) mutable {
|
||||
// create synthesized pull_coroutine< T >
|
||||
typename pull_coroutine< T >::control_block synthesized_cb{ this, ctx };
|
||||
pull_coroutine< T > synthesized{ & synthesized_cb };
|
||||
other = & synthesized_cb;
|
||||
// set transferred value
|
||||
synthesized_cb.set( static_cast< T * >( data) );
|
||||
try {
|
||||
auto fn = std::move( fn_);
|
||||
// call coroutine-fn with synthesized pull_coroutine as argument
|
||||
fn( synthesized);
|
||||
} catch ( boost::context::detail::forced_unwind const&) {
|
||||
throw;
|
||||
} catch (...) {
|
||||
// store other exceptions in exception-pointer
|
||||
except = std::current_exception();
|
||||
}
|
||||
// jump back to ctx
|
||||
return std::move( other->ctx);
|
||||
},
|
||||
std::forward< Fn >( fn),
|
||||
std::placeholders::_1,
|
||||
std::placeholders::_2))},
|
||||
#else
|
||||
ctx{ std::allocator_arg, palloc, salloc,
|
||||
[this,fn_=std::forward< Fn >( fn)]( boost::context::captured_context ctx, void * data) mutable {
|
||||
// create synthesized pull_coroutine< T >
|
||||
typename pull_coroutine< T >::control_block synthesized_cb{ this, ctx };
|
||||
pull_coroutine< T > synthesized{ & synthesized_cb };
|
||||
other = & synthesized_cb;
|
||||
// set transferred value
|
||||
synthesized_cb.set( static_cast< T * >( data) );
|
||||
try {
|
||||
auto fn = std::move( fn_);
|
||||
// call coroutine-fn with synthesized pull_coroutine as argument
|
||||
fn( synthesized);
|
||||
} catch ( boost::context::detail::forced_unwind const&) {
|
||||
throw;
|
||||
} catch (...) {
|
||||
// store other exceptions in exception-pointer
|
||||
except = std::current_exception();
|
||||
}
|
||||
// jump back to ctx
|
||||
return std::move( other->ctx);
|
||||
}},
|
||||
#endif
|
||||
except{} {
|
||||
}
|
||||
|
||||
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_) },
|
||||
except{} {
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
void
|
||||
push_coroutine< T >::control_block::resume( T const& data) {
|
||||
// pass an pointer to other context
|
||||
void * ignored;
|
||||
std::tie( ctx, ignored) = ctx( const_cast< T * >( & data) );
|
||||
if ( except) {
|
||||
std::rethrow_exception( except);
|
||||
}
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
void
|
||||
push_coroutine< T >::control_block::resume( T && data) {
|
||||
// pass an pointer to other context
|
||||
void * ignored;
|
||||
std::tie( ctx, ignored) = ctx( std::addressof( data) );
|
||||
if ( except) {
|
||||
std::rethrow_exception( except);
|
||||
}
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
bool
|
||||
push_coroutine< T >::control_block::valid() const noexcept {
|
||||
return ctx ? true : false;
|
||||
}
|
||||
|
||||
|
||||
// push_coroutine< T & >
|
||||
|
||||
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(
|
||||
std::bind(
|
||||
[this]( typename std::decay< Fn >::type & fn_, boost::context::captured_context ctx, void * data) mutable {
|
||||
// create synthesized pull_coroutine< T >
|
||||
typename pull_coroutine< T & >::control_block synthesized_cb{ this, ctx };
|
||||
pull_coroutine< T & > synthesized{ & synthesized_cb };
|
||||
other = & synthesized_cb;
|
||||
// set transferred value
|
||||
synthesized_cb.t = static_cast< T * >( data);
|
||||
try {
|
||||
auto fn = std::move( fn_);
|
||||
// call coroutine-fn with synthesized pull_coroutine as argument
|
||||
fn( synthesized);
|
||||
} catch ( boost::context::detail::forced_unwind const&) {
|
||||
throw;
|
||||
} catch (...) {
|
||||
// store other exceptions in exception-pointer
|
||||
except = std::current_exception();
|
||||
}
|
||||
// jump back to ctx
|
||||
return std::move( other->ctx);
|
||||
},
|
||||
std::forward< Fn >( fn),
|
||||
std::placeholders::_1,
|
||||
std::placeholders::_2))},
|
||||
#else
|
||||
ctx{ std::allocator_arg, palloc, salloc,
|
||||
[this,fn_=std::forward< Fn >( fn)]( boost::context::captured_context ctx, void * data) mutable {
|
||||
// create synthesized pull_coroutine< T >
|
||||
typename pull_coroutine< T & >::control_block synthesized_cb{ this, ctx };
|
||||
pull_coroutine< T & > synthesized{ & synthesized_cb };
|
||||
other = & synthesized_cb;
|
||||
// set transferred value
|
||||
synthesized_cb.t = static_cast< T * >( data);
|
||||
try {
|
||||
auto fn = std::move( fn_);
|
||||
// call coroutine-fn with synthesized pull_coroutine as argument
|
||||
fn( synthesized);
|
||||
} catch ( boost::context::detail::forced_unwind const&) {
|
||||
throw;
|
||||
} catch (...) {
|
||||
// store other exceptions in exception-pointer
|
||||
except = std::current_exception();
|
||||
}
|
||||
// jump back to ctx
|
||||
return std::move( other->ctx);
|
||||
}},
|
||||
#endif
|
||||
except{} {
|
||||
}
|
||||
|
||||
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_) },
|
||||
except{} {
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
void
|
||||
push_coroutine< T & >::control_block::resume( T & t) {
|
||||
// pass an pointer to other context
|
||||
void * ignored;
|
||||
std::tie( ctx, ignored) = ctx( const_cast< typename std::remove_const< T >::type * >( std::addressof( t) ) );
|
||||
if ( except) {
|
||||
std::rethrow_exception( except);
|
||||
}
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
bool
|
||||
push_coroutine< T & >::control_block::valid() const noexcept {
|
||||
return ctx ? true : false;
|
||||
}
|
||||
|
||||
|
||||
// push_coroutine< void >
|
||||
|
||||
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(
|
||||
std::bind(
|
||||
[this]( typename std::decay< Fn >::type & fn_, boost::context::captured_context ctx, void *) mutable {
|
||||
// create synthesized pull_coroutine< T >
|
||||
typename pull_coroutine< void >::control_block synthesized_cb{ this, ctx };
|
||||
pull_coroutine< void > synthesized{ & synthesized_cb };
|
||||
other = & synthesized_cb;
|
||||
try {
|
||||
auto fn = std::move( fn_);
|
||||
// call coroutine-fn with synthesized pull_coroutine as argument
|
||||
fn( synthesized);
|
||||
} catch ( boost::context::detail::forced_unwind const&) {
|
||||
throw;
|
||||
} catch (...) {
|
||||
// store other exceptions in exception-pointer
|
||||
except = std::current_exception();
|
||||
}
|
||||
// jump back to ctx
|
||||
return std::move( other->ctx);
|
||||
},
|
||||
std::forward< Fn >( fn),
|
||||
std::placeholders::_1,
|
||||
std::placeholders::_2))},
|
||||
#else
|
||||
ctx{ std::allocator_arg, palloc, salloc,
|
||||
[this,fn_=std::forward< Fn >( fn)]( boost::context::captured_context ctx, void *) mutable {
|
||||
// create synthesized pull_coroutine< T >
|
||||
typename pull_coroutine< void >::control_block synthesized_cb{ this, ctx};
|
||||
pull_coroutine< void > synthesized{ & synthesized_cb };
|
||||
other = & synthesized_cb;
|
||||
try {
|
||||
auto fn = std::move( fn_);
|
||||
// call coroutine-fn with synthesized pull_coroutine as argument
|
||||
fn( synthesized);
|
||||
} catch ( boost::context::detail::forced_unwind const&) {
|
||||
throw;
|
||||
} catch (...) {
|
||||
// store other exceptions in exception-pointer
|
||||
except = std::current_exception();
|
||||
}
|
||||
// jump back to ctx
|
||||
return std::move( other->ctx);
|
||||
}},
|
||||
#endif
|
||||
except{} {
|
||||
}
|
||||
|
||||
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_) },
|
||||
except{} {
|
||||
}
|
||||
|
||||
inline
|
||||
void
|
||||
push_coroutine< void >::control_block::resume() {
|
||||
void * ignored;
|
||||
std::tie( ctx, ignored) = ctx();
|
||||
if ( except) {
|
||||
std::rethrow_exception( except);
|
||||
}
|
||||
}
|
||||
|
||||
inline
|
||||
bool
|
||||
push_coroutine< void >::control_block::valid() const noexcept {
|
||||
return ctx ? true : false;
|
||||
}
|
||||
|
||||
}}}
|
||||
|
||||
#ifdef BOOST_HAS_ABI_HEADERS
|
||||
# include BOOST_ABI_SUFFIX
|
||||
#endif
|
||||
|
||||
#endif // BOOST_COROUTINES2_DETAIL_PUSH_CONTROL_BLOCK_IPP
|
@ -116,9 +116,8 @@ template< typename T >
|
||||
push_coroutine< T >::control_block::~control_block() noexcept {
|
||||
if ( state_t::none == ( state & state_t::complete) &&
|
||||
state_t::none != ( state & state_t::unwind) ) {
|
||||
// set early-exit flag
|
||||
state |= state_t::early_exit;
|
||||
ctx();
|
||||
// unwind coroutine stack
|
||||
ctx( context::exec_ontop_arg, unwind_coroutine);
|
||||
}
|
||||
}
|
||||
|
||||
@ -131,10 +130,6 @@ push_coroutine< T >::control_block::resume( T const& t) {
|
||||
if ( except) {
|
||||
std::rethrow_exception( except);
|
||||
}
|
||||
// test early-exit-flag
|
||||
if ( state_t::none != ( other->state & state_t::early_exit) ) {
|
||||
throw forced_unwind();
|
||||
}
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
@ -146,10 +141,6 @@ push_coroutine< T >::control_block::resume( T && t) {
|
||||
if ( except) {
|
||||
std::rethrow_exception( except);
|
||||
}
|
||||
// test early-exit-flag
|
||||
if ( state_t::none != ( other->state & state_t::early_exit) ) {
|
||||
throw forced_unwind();
|
||||
}
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
@ -245,9 +236,8 @@ template< typename T >
|
||||
push_coroutine< T & >::control_block::~control_block() noexcept {
|
||||
if ( state_t::none == ( state & state_t::complete) &&
|
||||
state_t::none != ( state & state_t::unwind) ) {
|
||||
// set early-exit flag
|
||||
state |= state_t::early_exit;
|
||||
ctx();
|
||||
// unwind coroutine stack
|
||||
ctx( context::exec_ontop_arg, unwind_coroutine);
|
||||
}
|
||||
}
|
||||
|
||||
@ -260,10 +250,6 @@ push_coroutine< T & >::control_block::resume( T & t) {
|
||||
if ( except) {
|
||||
std::rethrow_exception( except);
|
||||
}
|
||||
// test early-exit-flag
|
||||
if ( state_t::none != ( other->state & state_t::early_exit) ) {
|
||||
throw forced_unwind();
|
||||
}
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
@ -354,9 +340,8 @@ inline
|
||||
push_coroutine< void >::control_block::~control_block() noexcept {
|
||||
if ( state_t::none == ( state & state_t::complete) &&
|
||||
state_t::none != ( state & state_t::unwind) ) {
|
||||
// set early-exit flag
|
||||
state |= state_t::early_exit;
|
||||
ctx();
|
||||
// unwind coroutine stack
|
||||
ctx( context::exec_ontop_arg, unwind_coroutine);
|
||||
}
|
||||
}
|
||||
|
||||
@ -368,10 +353,6 @@ push_coroutine< void >::control_block::resume() {
|
||||
if ( except) {
|
||||
std::rethrow_exception( except);
|
||||
}
|
||||
// test early-exit-flag
|
||||
if ( state_t::none != ( other->state & state_t::early_exit) ) {
|
||||
throw forced_unwind();
|
||||
}
|
||||
}
|
||||
|
||||
inline
|
@ -25,8 +25,7 @@ namespace detail {
|
||||
enum class state_t : unsigned int {
|
||||
none = 0,
|
||||
complete = 1 << 1,
|
||||
unwind = 1 << 2,
|
||||
early_exit = 1 << 3
|
||||
unwind = 1 << 2
|
||||
};
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user