mirror of
https://github.com/boostorg/coroutine2.git
synced 2025-05-11 13:34:08 +00:00
use of captured_context
This commit is contained in:
parent
37222c014a
commit
6796caa2c7
@ -13,7 +13,8 @@
|
|||||||
|
|
||||||
#include <boost/coroutine2/all.hpp>
|
#include <boost/coroutine2/all.hpp>
|
||||||
|
|
||||||
struct node {
|
struct node
|
||||||
|
{
|
||||||
typedef std::shared_ptr< node > ptr_t;
|
typedef std::shared_ptr< node > ptr_t;
|
||||||
|
|
||||||
// Each tree node has an optional left subtree, an optional right subtree
|
// Each tree node has an optional left subtree, an optional right subtree
|
||||||
@ -24,24 +25,26 @@ struct node {
|
|||||||
|
|
||||||
// construct leaf
|
// construct leaf
|
||||||
node(const std::string& v):
|
node(const std::string& v):
|
||||||
left(),right(),value(v) {
|
left(),right(),value(v)
|
||||||
}
|
{}
|
||||||
|
|
||||||
// construct nonleaf
|
// construct nonleaf
|
||||||
node(ptr_t l, const std::string& v, ptr_t r):
|
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));
|
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));
|
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
|
root
|
||||||
/ \
|
/ \
|
||||||
@ -59,7 +62,8 @@ node::ptr_t create_left_tree_from(const std::string& root) {
|
|||||||
node::create("e"));
|
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
|
root
|
||||||
/ \
|
/ \
|
||||||
@ -78,7 +82,8 @@ node::ptr_t create_right_tree_from(const std::string& root) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// recursively walk the tree, delivering values in order
|
// 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)
|
if (n->left)
|
||||||
traverse(n->left,out);
|
traverse(n->left,out);
|
||||||
out(n->value);
|
out(n->value);
|
||||||
@ -86,81 +91,92 @@ void traverse(node::ptr_t n, boost::coroutines2::coroutine<std::string>::push_ty
|
|||||||
traverse(n->right,out);
|
traverse(n->right,out);
|
||||||
}
|
}
|
||||||
|
|
||||||
int main() {
|
int main()
|
||||||
|
{
|
||||||
{
|
{
|
||||||
node::ptr_t left_d(create_left_tree_from("d"));
|
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"));
|
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"));
|
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) {
|
boost::coroutines2::coroutine<std::string>::pull_type left_d_reader(
|
||||||
traverse(right_x,out);
|
[&]( boost::coroutines2::coroutine<std::string>::push_type & out) {
|
||||||
});
|
traverse(left_d,out);
|
||||||
std::cout << "right tree from x:\n";
|
});
|
||||||
std::copy(begin(right_x_reader),
|
std::cout << "left tree from d:\n";
|
||||||
end(right_x_reader),
|
std::copy(begin(left_d_reader),
|
||||||
std::ostream_iterator<std::string>(std::cout, " "));
|
end(left_d_reader),
|
||||||
std::cout << std::endl;
|
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"));
|
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"));
|
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) {
|
boost::coroutines2::coroutine<std::string>::pull_type left_d_reader(
|
||||||
traverse(right_b,out);
|
[&]( boost::coroutines2::coroutine<std::string>::push_type & out) {
|
||||||
});
|
traverse(left_d,out);
|
||||||
|
});
|
||||||
|
|
||||||
std::cout << "left tree from d == right tree from b? "
|
boost::coroutines2::coroutine<std::string>::pull_type right_b_reader(
|
||||||
<< std::boolalpha
|
[&]( boost::coroutines2::coroutine<std::string>::push_type & out) {
|
||||||
<< std::equal(begin(left_d_reader),
|
traverse(right_b,out);
|
||||||
end(left_d_reader),
|
});
|
||||||
begin(right_b_reader))
|
|
||||||
<< std::endl;
|
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"));
|
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"));
|
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) {
|
boost::coroutines2::coroutine<std::string>::pull_type left_d_reader(
|
||||||
traverse(right_x,out);
|
[&]( boost::coroutines2::coroutine<std::string>::push_type & out) {
|
||||||
});
|
traverse(left_d,out);
|
||||||
|
});
|
||||||
|
|
||||||
std::cout << "left tree from d == right tree from x? "
|
boost::coroutines2::coroutine<std::string>::pull_type right_x_reader(
|
||||||
<< std::boolalpha
|
[&]( boost::coroutines2::coroutine<std::string>::push_type & out) {
|
||||||
<< std::equal(begin(left_d_reader),
|
traverse(right_x,out);
|
||||||
end(left_d_reader),
|
});
|
||||||
begin(right_x_reader))
|
|
||||||
<< std::endl;
|
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;
|
std::cout << "Done" << std::endl;
|
||||||
|
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
@ -28,14 +28,24 @@ class push_coroutine;
|
|||||||
#include <boost/coroutine2/detail/pull_coroutine.hpp>
|
#include <boost/coroutine2/detail/pull_coroutine.hpp>
|
||||||
#include <boost/coroutine2/detail/push_coroutine.hpp>
|
#include <boost/coroutine2/detail/push_coroutine.hpp>
|
||||||
|
|
||||||
#include <boost/coroutine2/detail/pull_control_block.hpp>
|
#if ! defined(BOOST_USE_SEGMENTED_STACKS)
|
||||||
#include <boost/coroutine2/detail/push_control_block.hpp>
|
#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/pull_coroutine.ipp>
|
||||||
#include <boost/coroutine2/detail/push_coroutine.ipp>
|
#include <boost/coroutine2/detail/push_coroutine.ipp>
|
||||||
|
|
||||||
#include <boost/coroutine2/detail/pull_control_block.ipp>
|
#if ! defined(BOOST_USE_SEGMENTED_STACKS)
|
||||||
#include <boost/coroutine2/detail/push_control_block.ipp>
|
#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
|
#ifdef BOOST_HAS_ABI_HEADERS
|
||||||
# include BOOST_ABI_SUFFIX
|
# include BOOST_ABI_SUFFIX
|
||||||
|
@ -24,6 +24,12 @@ namespace detail {
|
|||||||
|
|
||||||
struct forced_unwind {};
|
struct forced_unwind {};
|
||||||
|
|
||||||
|
inline
|
||||||
|
void * unwind_coroutine( void * data) {
|
||||||
|
throw forced_unwind{};
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
}}}
|
}}}
|
||||||
|
|
||||||
#ifdef BOOST_HAS_ABI_HEADERS
|
#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( typename push_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;
|
||||||
@ -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( typename push_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;
|
||||||
@ -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( push_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;
|
@ -108,12 +108,11 @@ pull_coroutine< T >::control_block::control_block( typename push_coroutine< T >:
|
|||||||
}
|
}
|
||||||
|
|
||||||
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) ) {
|
||||||
// set early-exit flag
|
// unwind coroutine stack
|
||||||
state |= state_t::early_exit;
|
ctx( context::exec_ontop_arg, unwind_coroutine);
|
||||||
ctx();
|
|
||||||
}
|
}
|
||||||
// destroy data if it set
|
// destroy data if it set
|
||||||
if ( bvalid) {
|
if ( bvalid) {
|
||||||
@ -129,10 +128,6 @@ pull_coroutine< T >::control_block::resume() {
|
|||||||
if ( except) {
|
if ( except) {
|
||||||
std::rethrow_exception( 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 >
|
template< typename T >
|
||||||
@ -243,9 +238,8 @@ template< typename T >
|
|||||||
pull_coroutine< T & >::control_block::~control_block() noexcept {
|
pull_coroutine< T & >::control_block::~control_block() noexcept {
|
||||||
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) ) {
|
||||||
// set early-exit flag
|
// unwind coroutine stack
|
||||||
state |= state_t::early_exit;
|
ctx( context::exec_ontop_arg, unwind_coroutine);
|
||||||
ctx();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -257,10 +251,6 @@ pull_coroutine< T & >::control_block::resume() {
|
|||||||
if ( except) {
|
if ( except) {
|
||||||
std::rethrow_exception( 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 >
|
template< typename T >
|
||||||
@ -353,9 +343,8 @@ inline
|
|||||||
pull_coroutine< void >::control_block::~control_block() noexcept {
|
pull_coroutine< void >::control_block::~control_block() noexcept {
|
||||||
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) ) {
|
||||||
// set early-exit flag
|
// unwind coroutine stack
|
||||||
state |= state_t::early_exit;
|
ctx( context::exec_ontop_arg, unwind_coroutine);
|
||||||
ctx();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -367,10 +356,6 @@ pull_coroutine< void >::control_block::resume() {
|
|||||||
if ( except) {
|
if ( except) {
|
||||||
std::rethrow_exception( except);
|
std::rethrow_exception( except);
|
||||||
}
|
}
|
||||||
// test early-exit-flag
|
|
||||||
if ( state_t::none != ( other->state & state_t::early_exit) ) {
|
|
||||||
throw forced_unwind();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline
|
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 {
|
push_coroutine< T >::control_block::~control_block() noexcept {
|
||||||
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) ) {
|
||||||
// set early-exit flag
|
// unwind coroutine stack
|
||||||
state |= state_t::early_exit;
|
ctx( context::exec_ontop_arg, unwind_coroutine);
|
||||||
ctx();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -131,10 +130,6 @@ push_coroutine< T >::control_block::resume( T const& t) {
|
|||||||
if ( except) {
|
if ( except) {
|
||||||
std::rethrow_exception( 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 >
|
template< typename T >
|
||||||
@ -146,10 +141,6 @@ push_coroutine< T >::control_block::resume( T && t) {
|
|||||||
if ( except) {
|
if ( except) {
|
||||||
std::rethrow_exception( 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 >
|
template< typename T >
|
||||||
@ -245,9 +236,8 @@ template< typename T >
|
|||||||
push_coroutine< T & >::control_block::~control_block() noexcept {
|
push_coroutine< T & >::control_block::~control_block() noexcept {
|
||||||
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) ) {
|
||||||
// set early-exit flag
|
// unwind coroutine stack
|
||||||
state |= state_t::early_exit;
|
ctx( context::exec_ontop_arg, unwind_coroutine);
|
||||||
ctx();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -260,10 +250,6 @@ push_coroutine< T & >::control_block::resume( T & t) {
|
|||||||
if ( except) {
|
if ( except) {
|
||||||
std::rethrow_exception( 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 >
|
template< typename T >
|
||||||
@ -354,9 +340,8 @@ inline
|
|||||||
push_coroutine< void >::control_block::~control_block() noexcept {
|
push_coroutine< void >::control_block::~control_block() noexcept {
|
||||||
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) ) {
|
||||||
// set early-exit flag
|
// unwind coroutine stack
|
||||||
state |= state_t::early_exit;
|
ctx( context::exec_ontop_arg, unwind_coroutine);
|
||||||
ctx();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -368,10 +353,6 @@ push_coroutine< void >::control_block::resume() {
|
|||||||
if ( except) {
|
if ( except) {
|
||||||
std::rethrow_exception( except);
|
std::rethrow_exception( except);
|
||||||
}
|
}
|
||||||
// test early-exit-flag
|
|
||||||
if ( state_t::none != ( other->state & state_t::early_exit) ) {
|
|
||||||
throw forced_unwind();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline
|
inline
|
@ -25,8 +25,7 @@ namespace detail {
|
|||||||
enum class state_t : unsigned int {
|
enum class state_t : unsigned int {
|
||||||
none = 0,
|
none = 0,
|
||||||
complete = 1 << 1,
|
complete = 1 << 1,
|
||||||
unwind = 1 << 2,
|
unwind = 1 << 2
|
||||||
early_exit = 1 << 3
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user