mirror of
https://github.com/boostorg/coroutine2.git
synced 2025-05-11 13:34:08 +00:00
adapt new execution_context API
This commit is contained in:
parent
fe869dd847
commit
4bb8f7585f
@ -9,26 +9,22 @@
|
|||||||
|
|
||||||
#include <boost/coroutine2/all.hpp>
|
#include <boost/coroutine2/all.hpp>
|
||||||
|
|
||||||
int main()
|
int main() {
|
||||||
{
|
|
||||||
boost::coroutines2::coroutine< int >::pull_type source(
|
boost::coroutines2::coroutine< int >::pull_type source(
|
||||||
[&]( boost::coroutines2::coroutine< int >::push_type & sink) {
|
[]( boost::coroutines2::coroutine< int >::push_type & sink) {
|
||||||
int first = 1, second = 1;
|
int first = 1, second = 1;
|
||||||
sink( first);
|
sink( first);
|
||||||
sink( second);
|
sink( second);
|
||||||
for ( int i = 0; i < 8; ++i)
|
for ( int i = 0; i < 8; ++i) {
|
||||||
{
|
|
||||||
int third = first + second;
|
int third = first + second;
|
||||||
first = second;
|
first = second;
|
||||||
second = third;
|
second = third;
|
||||||
sink( third);
|
sink( third);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
for ( auto i : source) {
|
||||||
for ( auto i : source)
|
|
||||||
std::cout << i << " ";
|
std::cout << i << " ";
|
||||||
|
}
|
||||||
std::cout << "\nDone" << std::endl;
|
std::cout << "\nDone" << std::endl;
|
||||||
|
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
@ -21,13 +21,11 @@ struct FinalEOL{
|
|||||||
int main(int argc,char* argv[]){
|
int main(int argc,char* argv[]){
|
||||||
using std::begin;
|
using std::begin;
|
||||||
using std::end;
|
using std::end;
|
||||||
|
|
||||||
std::vector<std::string> words{
|
std::vector<std::string> words{
|
||||||
"peas", "porridge", "hot", "peas",
|
"peas", "porridge", "hot", "peas",
|
||||||
"porridge", "cold", "peas", "porridge",
|
"porridge", "cold", "peas", "porridge",
|
||||||
"in", "the", "pot", "nine",
|
"in", "the", "pot", "nine",
|
||||||
"days", "old" };
|
"days", "old" };
|
||||||
|
|
||||||
int num=5,width=15;
|
int num=5,width=15;
|
||||||
boost::coroutines2::coroutine<std::string>::push_type writer(
|
boost::coroutines2::coroutine<std::string>::push_type writer(
|
||||||
[&](boost::coroutines2::coroutine<std::string>::pull_type& in){
|
[&](boost::coroutines2::coroutine<std::string>::pull_type& in){
|
||||||
@ -46,10 +44,7 @@ int main(int argc,char* argv[]){
|
|||||||
std::cout << std::endl;
|
std::cout << std::endl;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
std::copy(begin(words),end(words),begin(writer));
|
std::copy(begin(words),end(words),begin(writer));
|
||||||
|
std::cout << "\nDone";
|
||||||
std::cout << "\nDone" << std::endl;
|
return EXIT_SUCCESS;
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
@ -108,14 +108,11 @@ int main() {
|
|||||||
});
|
});
|
||||||
p.run();
|
p.run();
|
||||||
});
|
});
|
||||||
|
|
||||||
// user-code pulls parsed data from parser
|
// user-code pulls parsed data from parser
|
||||||
for(char c:seq){
|
for(char c:seq){
|
||||||
printf("Parsed: %c\n",c);
|
printf("Parsed: %c\n",c);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::cout << "\nDone" << std::endl;
|
std::cout << "\nDone" << std::endl;
|
||||||
|
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
} catch ( std::exception const& ex) {
|
} catch ( std::exception const& ex) {
|
||||||
std::cerr << "exception: " << ex.what() << std::endl;
|
std::cerr << "exception: " << ex.what() << std::endl;
|
||||||
|
@ -13,8 +13,7 @@
|
|||||||
|
|
||||||
#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
|
||||||
@ -25,26 +24,24 @@ 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
|
||||||
/ \
|
/ \
|
||||||
@ -62,8 +59,7 @@ 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
|
||||||
/ \
|
/ \
|
||||||
@ -82,8 +78,7 @@ 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);
|
||||||
@ -91,8 +86,7 @@ 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>::pull_type left_d_reader(
|
||||||
@ -127,7 +121,6 @@ int main()
|
|||||||
std::ostream_iterator<std::string>(std::cout, " "));
|
std::ostream_iterator<std::string>(std::cout, " "));
|
||||||
std::cout << std::endl;
|
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>::pull_type left_d_reader(
|
||||||
@ -148,7 +141,6 @@ int main()
|
|||||||
begin(right_b_reader))
|
begin(right_b_reader))
|
||||||
<< std::endl;
|
<< 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>::pull_type left_d_reader(
|
||||||
@ -169,8 +161,6 @@ int main()
|
|||||||
begin(right_x_reader))
|
begin(right_x_reader))
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::cout << "Done" << std::endl;
|
std::cout << "Done" << std::endl;
|
||||||
|
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
@ -54,7 +54,7 @@ int main() {
|
|||||||
|
|
||||||
sink();
|
sink();
|
||||||
|
|
||||||
std::cout << "main: done" << std::endl;
|
std::cout << "main: Done" << std::endl;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -9,15 +9,12 @@
|
|||||||
|
|
||||||
#include <boost/coroutine2/all.hpp>
|
#include <boost/coroutine2/all.hpp>
|
||||||
|
|
||||||
int main()
|
int main() {
|
||||||
{
|
|
||||||
boost::coroutines2::coroutine< void >::push_type sink(
|
boost::coroutines2::coroutine< void >::push_type sink(
|
||||||
[&]( boost::coroutines2::coroutine< void >::pull_type & source) {
|
[]( boost::coroutines2::coroutine< void >::pull_type & source) {
|
||||||
std::cout << "inside coroutine-fn" << std::endl;
|
std::cout << "inside coroutine-fn" << std::endl;
|
||||||
});
|
});
|
||||||
sink();
|
sink();
|
||||||
|
|
||||||
std::cout << "Done" << std::endl;
|
std::cout << "Done" << std::endl;
|
||||||
|
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
60
include/boost/coroutine2/detail/create_control_block.ipp
Normal file
60
include/boost/coroutine2/detail/create_control_block.ipp
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
|
||||||
|
// 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_CREATE_CONTROLBLOCK_IPP
|
||||||
|
#define BOOST_COROUTINES2_DETAIL_CREATE_CONTROLBLOCK_IPP
|
||||||
|
|
||||||
|
#include <cstddef>
|
||||||
|
#include <memory>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
#include <boost/assert.hpp>
|
||||||
|
#include <boost/config.hpp>
|
||||||
|
|
||||||
|
#include <boost/context/preallocated.hpp>
|
||||||
|
#include <boost/context/stack_context.hpp>
|
||||||
|
|
||||||
|
#include <boost/coroutine2/detail/config.hpp>
|
||||||
|
|
||||||
|
#ifdef BOOST_HAS_ABI_HEADERS
|
||||||
|
# include BOOST_ABI_PREFIX
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace boost {
|
||||||
|
namespace coroutines2 {
|
||||||
|
namespace detail {
|
||||||
|
|
||||||
|
template< typename ControlBlock, typename StackAllocator, typename Fn >
|
||||||
|
ControlBlock * create_control_block( StackAllocator salloc, Fn && fn) {
|
||||||
|
auto sctx = salloc.allocate();
|
||||||
|
// reserve space for control structure
|
||||||
|
#if defined(BOOST_NO_CXX14_CONSTEXPR) || defined(BOOST_NO_CXX11_STD_ALIGN)
|
||||||
|
void * sp = static_cast< char * >( sctx.sp) - sizeof( ControlBlock);
|
||||||
|
std::size_t size = sctx.size - sizeof( ControlBlock);
|
||||||
|
#else
|
||||||
|
constexpr std::size_t func_alignment = 64; // alignof( ControlBlock);
|
||||||
|
constexpr std::size_t func_size = sizeof( ControlBlock);
|
||||||
|
// reserve space on stack
|
||||||
|
void * sp = static_cast< char * >( sctx.sp) - func_size - func_alignment;
|
||||||
|
// align sp pointer
|
||||||
|
std::size_t space = func_size + func_alignment;
|
||||||
|
sp = std::align( func_alignment, func_size, sp, space);
|
||||||
|
BOOST_ASSERT( nullptr != sp);
|
||||||
|
// calculate remaining size
|
||||||
|
std::size_t size = sctx.size - ( static_cast< char * >( sctx.sp) - static_cast< char * >( sp) );
|
||||||
|
#endif
|
||||||
|
// placment new for control structure on coroutine stack
|
||||||
|
return new ( sp) ControlBlock{ context::preallocated( sp, size, sctx),
|
||||||
|
salloc, std::forward< Fn >( fn) };
|
||||||
|
}
|
||||||
|
|
||||||
|
}}}
|
||||||
|
|
||||||
|
#ifdef BOOST_HAS_ABI_HEADERS
|
||||||
|
# include BOOST_ABI_SUFFIX
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // BOOST_COROUTINES2_DETAIL_CREATE_CONTROLBLOCK_IPP
|
@ -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
|
||||||
|
@ -13,6 +13,8 @@
|
|||||||
#include <boost/config.hpp>
|
#include <boost/config.hpp>
|
||||||
#include <boost/context/execution_context.hpp>
|
#include <boost/context/execution_context.hpp>
|
||||||
|
|
||||||
|
#include <boost/coroutine2/detail/state.hpp>
|
||||||
|
|
||||||
#ifdef BOOST_HAS_ABI_HEADERS
|
#ifdef BOOST_HAS_ABI_HEADERS
|
||||||
# include BOOST_ABI_PREFIX
|
# include BOOST_ABI_PREFIX
|
||||||
#endif
|
#endif
|
||||||
@ -25,18 +27,17 @@ template< typename T >
|
|||||||
struct pull_coroutine< T >::control_block {
|
struct pull_coroutine< T >::control_block {
|
||||||
typename push_coroutine< T >::control_block * other;
|
typename push_coroutine< T >::control_block * other;
|
||||||
boost::context::execution_context ctx;
|
boost::context::execution_context ctx;
|
||||||
bool preserve_fpu;
|
state_t state;
|
||||||
int state;
|
|
||||||
std::exception_ptr except;
|
std::exception_ptr except;
|
||||||
bool bvalid;
|
bool bvalid;
|
||||||
typename std::aligned_storage< sizeof( T), alignof( T) >::type storage[1];
|
typename std::aligned_storage< sizeof( T), alignof( T) >::type storage[1];
|
||||||
|
|
||||||
template< typename StackAllocator, typename Fn >
|
template< typename StackAllocator, typename Fn >
|
||||||
control_block( context::preallocated, StackAllocator, Fn &&, bool);
|
control_block( context::preallocated, StackAllocator, Fn &&);
|
||||||
|
|
||||||
explicit control_block( typename push_coroutine< T >::control_block *, boost::context::execution_context const&);
|
control_block( typename push_coroutine< T >::control_block *, boost::context::execution_context const&) noexcept;
|
||||||
|
|
||||||
~control_block();
|
~control_block() noexcept;
|
||||||
|
|
||||||
control_block( control_block &) = delete;
|
control_block( control_block &) = delete;
|
||||||
control_block & operator=( control_block &) = delete;
|
control_block & operator=( control_block &) = delete;
|
||||||
@ -45,7 +46,7 @@ struct pull_coroutine< T >::control_block {
|
|||||||
|
|
||||||
void set( T *);
|
void set( T *);
|
||||||
|
|
||||||
T & get();
|
T & get() noexcept;
|
||||||
|
|
||||||
bool valid() const noexcept;
|
bool valid() const noexcept;
|
||||||
};
|
};
|
||||||
@ -54,24 +55,23 @@ template< typename T >
|
|||||||
struct pull_coroutine< T & >::control_block {
|
struct pull_coroutine< T & >::control_block {
|
||||||
typename push_coroutine< T & >::control_block * other;
|
typename push_coroutine< T & >::control_block * other;
|
||||||
boost::context::execution_context ctx;
|
boost::context::execution_context ctx;
|
||||||
bool preserve_fpu;
|
state_t state;
|
||||||
int state;
|
|
||||||
std::exception_ptr except;
|
std::exception_ptr except;
|
||||||
T * t;
|
T * t;
|
||||||
|
|
||||||
template< typename StackAllocator, typename Fn >
|
template< typename StackAllocator, typename Fn >
|
||||||
control_block( context::preallocated, StackAllocator, Fn &&, bool);
|
control_block( context::preallocated, StackAllocator, Fn &&);
|
||||||
|
|
||||||
explicit control_block( typename push_coroutine< T & >::control_block *, boost::context::execution_context const&);
|
control_block( typename push_coroutine< T & >::control_block *, boost::context::execution_context const&) noexcept;
|
||||||
|
|
||||||
~control_block();
|
~control_block() noexcept;
|
||||||
|
|
||||||
control_block( control_block &) = delete;
|
control_block( control_block &) = delete;
|
||||||
control_block & operator=( control_block &) = delete;
|
control_block & operator=( control_block &) = delete;
|
||||||
|
|
||||||
void resume();
|
void resume();
|
||||||
|
|
||||||
T & get();
|
T & get() noexcept;
|
||||||
|
|
||||||
bool valid() const noexcept;
|
bool valid() const noexcept;
|
||||||
};
|
};
|
||||||
@ -79,16 +79,15 @@ struct pull_coroutine< T & >::control_block {
|
|||||||
struct pull_coroutine< void >::control_block {
|
struct pull_coroutine< void >::control_block {
|
||||||
push_coroutine< void >::control_block * other;
|
push_coroutine< void >::control_block * other;
|
||||||
boost::context::execution_context ctx;
|
boost::context::execution_context ctx;
|
||||||
bool preserve_fpu;
|
state_t state;
|
||||||
int state;
|
|
||||||
std::exception_ptr except;
|
std::exception_ptr except;
|
||||||
|
|
||||||
template< typename StackAllocator, typename Fn >
|
template< typename StackAllocator, typename Fn >
|
||||||
control_block( context::preallocated, StackAllocator, Fn &&, bool);
|
control_block( context::preallocated, StackAllocator, Fn &&);
|
||||||
|
|
||||||
explicit control_block( push_coroutine< void >::control_block *, boost::context::execution_context const&);
|
control_block( push_coroutine< void >::control_block *, boost::context::execution_context const&) noexcept;
|
||||||
|
|
||||||
~control_block();
|
~control_block() noexcept;
|
||||||
|
|
||||||
control_block( control_block &) = delete;
|
control_block( control_block &) = delete;
|
||||||
control_block & operator=( control_block &) = delete;
|
control_block & operator=( control_block &) = delete;
|
||||||
|
@ -32,13 +32,13 @@ namespace detail {
|
|||||||
template< typename T >
|
template< typename T >
|
||||||
template< typename StackAllocator, typename Fn >
|
template< typename StackAllocator, typename Fn >
|
||||||
pull_coroutine< T >::control_block::control_block( context::preallocated palloc, StackAllocator salloc,
|
pull_coroutine< T >::control_block::control_block( context::preallocated palloc, StackAllocator salloc,
|
||||||
Fn && fn_, bool preserve_fpu_) :
|
Fn && fn_) :
|
||||||
other( nullptr),
|
other{ nullptr },
|
||||||
ctx( std::allocator_arg, palloc, salloc,
|
ctx{ std::allocator_arg, palloc, salloc,
|
||||||
[=,fn=std::forward< Fn >( fn_),ctx=boost::context::execution_context::current()] (void *) mutable -> void {
|
[this,fn=std::forward< Fn >( fn_),ctx=boost::context::execution_context::current()] (void *) mutable noexcept {
|
||||||
// create synthesized push_coroutine< T >
|
// create synthesized push_coroutine< T >
|
||||||
typename push_coroutine< T >::control_block synthesized_cb( this, ctx);
|
typename push_coroutine< T >::control_block synthesized_cb{ this, ctx };
|
||||||
push_coroutine< T > synthesized( & synthesized_cb);
|
push_coroutine< T > synthesized{ & synthesized_cb };
|
||||||
other = & synthesized_cb;
|
other = & synthesized_cb;
|
||||||
try {
|
try {
|
||||||
// call coroutine-fn with synthesized push_coroutine as argument
|
// call coroutine-fn with synthesized push_coroutine as argument
|
||||||
@ -50,39 +50,37 @@ pull_coroutine< T >::control_block::control_block( context::preallocated palloc,
|
|||||||
except = std::current_exception();
|
except = std::current_exception();
|
||||||
}
|
}
|
||||||
// set termination flags
|
// set termination flags
|
||||||
state |= static_cast< int >( state_t::complete);
|
state |= state_t::complete;
|
||||||
// jump back to ctx
|
// jump back to ctx
|
||||||
other->ctx( nullptr, preserve_fpu);
|
other->ctx();
|
||||||
BOOST_ASSERT_MSG( false, "pull_coroutine is complete");
|
BOOST_ASSERT_MSG( false, "pull_coroutine is complete");
|
||||||
}),
|
}},
|
||||||
preserve_fpu( preserve_fpu_),
|
state{ state_t::unwind },
|
||||||
state( static_cast< int >( state_t::unwind) ),
|
except{},
|
||||||
except(),
|
bvalid{ false },
|
||||||
bvalid( false),
|
storage{} {
|
||||||
storage() {
|
|
||||||
// enter coroutine-fn in order to have first value available after ctor (of `*this`) returns
|
// enter coroutine-fn in order to have first value available after ctor (of `*this`) returns
|
||||||
set( reinterpret_cast< T * >( ctx( nullptr, preserve_fpu) ) );
|
set( static_cast< T * >( ctx() ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
template< typename T >
|
template< typename T >
|
||||||
pull_coroutine< T >::control_block::control_block( typename push_coroutine< T >::control_block * cb,
|
pull_coroutine< T >::control_block::control_block( typename push_coroutine< T >::control_block * cb,
|
||||||
boost::context::execution_context const& ctx_) :
|
boost::context::execution_context const& ctx_) noexcept :
|
||||||
other( cb),
|
other{ cb },
|
||||||
ctx( ctx_),
|
ctx{ ctx_ },
|
||||||
preserve_fpu( other->preserve_fpu),
|
state{ state_t::none },
|
||||||
state( 0),
|
except{},
|
||||||
except(),
|
bvalid{ false },
|
||||||
bvalid( false),
|
storage{} {
|
||||||
storage() {
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template< typename T >
|
template< typename T >
|
||||||
pull_coroutine< T >::control_block::~control_block() {
|
pull_coroutine< T >::control_block::~control_block() noexcept {
|
||||||
if ( 0 == ( state & static_cast< int >( state_t::complete ) ) &&
|
if ( state_t::none == ( state & state_t::complete) &&
|
||||||
0 != ( state & static_cast< int >( state_t::unwind) ) ) {
|
state_t::none != ( state & state_t::unwind) ) {
|
||||||
// set early-exit flag
|
// set early-exit flag
|
||||||
state |= static_cast< int >( state_t::early_exit);
|
state |= state_t::early_exit;
|
||||||
ctx( nullptr, preserve_fpu);
|
ctx();
|
||||||
}
|
}
|
||||||
// destroy data if it set
|
// destroy data if it set
|
||||||
if ( bvalid) {
|
if ( bvalid) {
|
||||||
@ -94,12 +92,12 @@ template< typename T >
|
|||||||
void
|
void
|
||||||
pull_coroutine< T >::control_block::resume() {
|
pull_coroutine< T >::control_block::resume() {
|
||||||
other->ctx = boost::context::execution_context::current();
|
other->ctx = boost::context::execution_context::current();
|
||||||
set( reinterpret_cast< T * >( ctx( nullptr, preserve_fpu) ) );
|
set( static_cast< T * >( ctx() ) );
|
||||||
if ( except) {
|
if ( except) {
|
||||||
std::rethrow_exception( except);
|
std::rethrow_exception( except);
|
||||||
}
|
}
|
||||||
// test early-exit-flag
|
// test early-exit-flag
|
||||||
if ( 0 != ( ( other->state) & static_cast< int >( state_t::early_exit) ) ) {
|
if ( state_t::none != ( other->state & state_t::early_exit) ) {
|
||||||
throw forced_unwind();
|
throw forced_unwind();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -121,14 +119,14 @@ pull_coroutine< T >::control_block::set( T * t) {
|
|||||||
|
|
||||||
template< typename T >
|
template< typename T >
|
||||||
T &
|
T &
|
||||||
pull_coroutine< T >::control_block::get() {
|
pull_coroutine< T >::control_block::get() noexcept {
|
||||||
return * reinterpret_cast< T * >( storage);
|
return * reinterpret_cast< T * >( storage);
|
||||||
}
|
}
|
||||||
|
|
||||||
template< typename T >
|
template< typename T >
|
||||||
bool
|
bool
|
||||||
pull_coroutine< T >::control_block::valid() const noexcept {
|
pull_coroutine< T >::control_block::valid() const noexcept {
|
||||||
return nullptr != other && 0 == ( state & static_cast< int >( state_t::complete) ) && bvalid;
|
return nullptr != other && state_t::none == ( state & state_t::complete) && bvalid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -137,13 +135,13 @@ pull_coroutine< T >::control_block::valid() const noexcept {
|
|||||||
template< typename T >
|
template< typename T >
|
||||||
template< typename StackAllocator, typename Fn >
|
template< typename StackAllocator, typename Fn >
|
||||||
pull_coroutine< T & >::control_block::control_block( context::preallocated palloc, StackAllocator salloc,
|
pull_coroutine< T & >::control_block::control_block( context::preallocated palloc, StackAllocator salloc,
|
||||||
Fn && fn_, bool preserve_fpu_) :
|
Fn && fn_) :
|
||||||
other( nullptr),
|
other{ nullptr },
|
||||||
ctx( std::allocator_arg, palloc, salloc,
|
ctx{ std::allocator_arg, palloc, salloc,
|
||||||
[=,fn=std::forward< Fn >( fn_),ctx=boost::context::execution_context::current()] (void *) mutable -> void {
|
[this,fn=std::forward< Fn >( fn_),ctx=boost::context::execution_context::current()] (void *) mutable noexcept {
|
||||||
// create synthesized push_coroutine< T >
|
// create synthesized push_coroutine< T >
|
||||||
typename push_coroutine< T & >::control_block synthesized_cb( this, ctx);
|
typename push_coroutine< T & >::control_block synthesized_cb{ this, ctx };
|
||||||
push_coroutine< T & > synthesized( & synthesized_cb);
|
push_coroutine< T & > synthesized{ & synthesized_cb };
|
||||||
other = & synthesized_cb;
|
other = & synthesized_cb;
|
||||||
try {
|
try {
|
||||||
// call coroutine-fn with synthesized push_coroutine as argument
|
// call coroutine-fn with synthesized push_coroutine as argument
|
||||||
@ -155,37 +153,35 @@ pull_coroutine< T & >::control_block::control_block( context::preallocated pallo
|
|||||||
except = std::current_exception();
|
except = std::current_exception();
|
||||||
}
|
}
|
||||||
// set termination flags
|
// set termination flags
|
||||||
state |= static_cast< int >( state_t::complete);
|
state |= state_t::complete;
|
||||||
// jump back to ctx
|
// jump back to ctx
|
||||||
other->ctx( nullptr, preserve_fpu);
|
other->ctx();
|
||||||
BOOST_ASSERT_MSG( false, "pull_coroutine is complete");
|
BOOST_ASSERT_MSG( false, "pull_coroutine is complete");
|
||||||
}),
|
}},
|
||||||
preserve_fpu( preserve_fpu_),
|
state{ state_t::unwind },
|
||||||
state( static_cast< int >( state_t::unwind) ),
|
except{},
|
||||||
except(),
|
|
||||||
t( nullptr) {
|
t( nullptr) {
|
||||||
// enter coroutine-fn in order to have first value available after ctor (of `*this`) returns
|
// enter coroutine-fn in order to have first value available after ctor (of `*this`) returns
|
||||||
t = reinterpret_cast< T * >( ctx( nullptr, preserve_fpu) );
|
t = static_cast< T * >( ctx() );
|
||||||
}
|
}
|
||||||
|
|
||||||
template< typename T >
|
template< typename T >
|
||||||
pull_coroutine< T & >::control_block::control_block( typename push_coroutine< T & >::control_block * cb,
|
pull_coroutine< T & >::control_block::control_block( typename push_coroutine< T & >::control_block * cb,
|
||||||
boost::context::execution_context const& ctx_) :
|
boost::context::execution_context const& ctx_) noexcept :
|
||||||
other( cb),
|
other{ cb },
|
||||||
ctx( ctx_),
|
ctx{ ctx_ },
|
||||||
preserve_fpu( other->preserve_fpu),
|
state{ state_t::none },
|
||||||
state( 0),
|
except{},
|
||||||
except(),
|
|
||||||
t( nullptr) {
|
t( nullptr) {
|
||||||
}
|
}
|
||||||
|
|
||||||
template< typename T >
|
template< typename T >
|
||||||
pull_coroutine< T & >::control_block::~control_block() {
|
pull_coroutine< T & >::control_block::~control_block() noexcept {
|
||||||
if ( 0 == ( state & static_cast< int >( state_t::complete ) ) &&
|
if ( state_t::none == ( state & state_t::complete) &&
|
||||||
0 != ( state & static_cast< int >( state_t::unwind) ) ) {
|
state_t::none != ( state & state_t::unwind) ) {
|
||||||
// set early-exit flag
|
// set early-exit flag
|
||||||
state |= static_cast< int >( state_t::early_exit);
|
state |= state_t::early_exit;
|
||||||
ctx( nullptr, preserve_fpu);
|
ctx();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -193,26 +189,26 @@ template< typename T >
|
|||||||
void
|
void
|
||||||
pull_coroutine< T & >::control_block::resume() {
|
pull_coroutine< T & >::control_block::resume() {
|
||||||
other->ctx = boost::context::execution_context::current();
|
other->ctx = boost::context::execution_context::current();
|
||||||
t = reinterpret_cast< T * >( ctx( nullptr, preserve_fpu) );
|
t = static_cast< T * >( ctx() );
|
||||||
if ( except) {
|
if ( except) {
|
||||||
std::rethrow_exception( except);
|
std::rethrow_exception( except);
|
||||||
}
|
}
|
||||||
// test early-exit-flag
|
// test early-exit-flag
|
||||||
if ( 0 != ( ( other->state) & static_cast< int >( state_t::early_exit) ) ) {
|
if ( state_t::none != ( other->state & state_t::early_exit) ) {
|
||||||
throw forced_unwind();
|
throw forced_unwind();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template< typename T >
|
template< typename T >
|
||||||
T &
|
T &
|
||||||
pull_coroutine< T & >::control_block::get() {
|
pull_coroutine< T & >::control_block::get() noexcept {
|
||||||
return * reinterpret_cast< T * >( t);
|
return * static_cast< T * >( t);
|
||||||
}
|
}
|
||||||
|
|
||||||
template< typename T >
|
template< typename T >
|
||||||
bool
|
bool
|
||||||
pull_coroutine< T & >::control_block::valid() const noexcept {
|
pull_coroutine< T & >::control_block::valid() const noexcept {
|
||||||
return nullptr != other && 0 == ( state & static_cast< int >( state_t::complete) ) && nullptr != t;
|
return nullptr != other && state_t::none == ( state & state_t::complete) && nullptr != t;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -220,13 +216,13 @@ pull_coroutine< T & >::control_block::valid() const noexcept {
|
|||||||
|
|
||||||
template< typename StackAllocator, typename Fn >
|
template< typename StackAllocator, typename Fn >
|
||||||
pull_coroutine< void >::control_block::control_block( context::preallocated palloc, StackAllocator salloc,
|
pull_coroutine< void >::control_block::control_block( context::preallocated palloc, StackAllocator salloc,
|
||||||
Fn && fn_, bool preserve_fpu_) :
|
Fn && fn_) :
|
||||||
other( nullptr),
|
other{ nullptr },
|
||||||
ctx( std::allocator_arg, palloc, salloc,
|
ctx{ std::allocator_arg, palloc, salloc,
|
||||||
[=,fn=std::forward< Fn >( fn_),ctx=boost::context::execution_context::current()] (void *) mutable -> void {
|
[this,fn=std::forward< Fn >( fn_),ctx=boost::context::execution_context::current()] (void *) mutable noexcept {
|
||||||
// create synthesized push_coroutine< T >
|
// create synthesized push_coroutine< T >
|
||||||
typename push_coroutine< void >::control_block synthesized_cb( this, ctx);
|
typename push_coroutine< void >::control_block synthesized_cb{ this, ctx };
|
||||||
push_coroutine< void > synthesized( & synthesized_cb);
|
push_coroutine< void > synthesized{ & synthesized_cb };
|
||||||
other = & synthesized_cb;
|
other = & synthesized_cb;
|
||||||
try {
|
try {
|
||||||
// call coroutine-fn with synthesized push_coroutine as argument
|
// call coroutine-fn with synthesized push_coroutine as argument
|
||||||
@ -238,35 +234,33 @@ pull_coroutine< void >::control_block::control_block( context::preallocated pall
|
|||||||
except = std::current_exception();
|
except = std::current_exception();
|
||||||
}
|
}
|
||||||
// set termination flags
|
// set termination flags
|
||||||
state |= static_cast< int >( state_t::complete);
|
state |= state_t::complete;
|
||||||
// jump back to ctx
|
// jump back to ctx
|
||||||
other->ctx( nullptr, preserve_fpu);
|
other->ctx();
|
||||||
BOOST_ASSERT_MSG( false, "pull_coroutine is complete");
|
BOOST_ASSERT_MSG( false, "pull_coroutine is complete");
|
||||||
}),
|
}},
|
||||||
preserve_fpu( preserve_fpu_),
|
state{ state_t::unwind },
|
||||||
state( static_cast< int >( state_t::unwind) ),
|
except{} {
|
||||||
except() {
|
|
||||||
// enter coroutine-fn in order to have first value available after ctor returns
|
// enter coroutine-fn in order to have first value available after ctor returns
|
||||||
ctx( nullptr, preserve_fpu);
|
ctx();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline
|
inline
|
||||||
pull_coroutine< void >::control_block::control_block( push_coroutine< void >::control_block * cb,
|
pull_coroutine< void >::control_block::control_block( push_coroutine< void >::control_block * cb,
|
||||||
boost::context::execution_context const& ctx_) :
|
boost::context::execution_context const& ctx_) noexcept :
|
||||||
other( cb),
|
other{ cb },
|
||||||
ctx( ctx_),
|
ctx{ ctx_ },
|
||||||
preserve_fpu( other->preserve_fpu),
|
state{ state_t::none },
|
||||||
state( 0),
|
except{} {
|
||||||
except() {
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline
|
inline
|
||||||
pull_coroutine< void >::control_block::~control_block() {
|
pull_coroutine< void >::control_block::~control_block() noexcept {
|
||||||
if ( 0 == ( state & static_cast< int >( state_t::complete ) ) &&
|
if ( state_t::none == ( state & state_t::complete) &&
|
||||||
0 != ( state & static_cast< int >( state_t::unwind) ) ) {
|
state_t::none != ( state & state_t::unwind) ) {
|
||||||
// set early-exit flag
|
// set early-exit flag
|
||||||
state |= static_cast< int >( state_t::early_exit);
|
state |= state_t::early_exit;
|
||||||
ctx( nullptr, preserve_fpu);
|
ctx();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -274,12 +268,12 @@ inline
|
|||||||
void
|
void
|
||||||
pull_coroutine< void >::control_block::resume() {
|
pull_coroutine< void >::control_block::resume() {
|
||||||
other->ctx = boost::context::execution_context::current();
|
other->ctx = boost::context::execution_context::current();
|
||||||
ctx( nullptr, preserve_fpu);
|
ctx();
|
||||||
if ( except) {
|
if ( except) {
|
||||||
std::rethrow_exception( except);
|
std::rethrow_exception( except);
|
||||||
}
|
}
|
||||||
// test early-exit-flag
|
// test early-exit-flag
|
||||||
if ( 0 != ( ( other->state) & static_cast< int >( state_t::early_exit) ) ) {
|
if ( state_t::none != ( other->state & state_t::early_exit) ) {
|
||||||
throw forced_unwind();
|
throw forced_unwind();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -287,7 +281,7 @@ pull_coroutine< void >::control_block::resume() {
|
|||||||
inline
|
inline
|
||||||
bool
|
bool
|
||||||
pull_coroutine< void >::control_block::valid() const noexcept {
|
pull_coroutine< void >::control_block::valid() const noexcept {
|
||||||
return nullptr != other && 0 == ( state & static_cast< int >( state_t::complete) );
|
return nullptr != other && state_t::none == ( state & state_t::complete);
|
||||||
}
|
}
|
||||||
|
|
||||||
}}}
|
}}}
|
||||||
|
@ -12,7 +12,6 @@
|
|||||||
|
|
||||||
#include <boost/assert.hpp>
|
#include <boost/assert.hpp>
|
||||||
#include <boost/config.hpp>
|
#include <boost/config.hpp>
|
||||||
#include <boost/context/execution_context.hpp>
|
|
||||||
|
|
||||||
#include <boost/coroutine2/detail/config.hpp>
|
#include <boost/coroutine2/detail/config.hpp>
|
||||||
|
|
||||||
@ -34,25 +33,25 @@ private:
|
|||||||
|
|
||||||
control_block * cb_;
|
control_block * cb_;
|
||||||
|
|
||||||
explicit pull_coroutine( control_block *);
|
explicit pull_coroutine( control_block *) noexcept;
|
||||||
|
|
||||||
bool has_result_() const;
|
bool has_result_() const noexcept;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
template< typename Fn >
|
template< typename Fn >
|
||||||
explicit pull_coroutine( Fn &&, bool = false);
|
explicit pull_coroutine( Fn &&);
|
||||||
|
|
||||||
template< typename StackAllocator, typename Fn >
|
template< typename StackAllocator, typename Fn >
|
||||||
explicit pull_coroutine( StackAllocator, Fn &&, bool = false);
|
pull_coroutine( StackAllocator, Fn &&);
|
||||||
|
|
||||||
~pull_coroutine();
|
~pull_coroutine() noexcept;
|
||||||
|
|
||||||
pull_coroutine( pull_coroutine const&) = delete;
|
pull_coroutine( pull_coroutine const&) = delete;
|
||||||
pull_coroutine & operator=( pull_coroutine const&) = delete;
|
pull_coroutine & operator=( pull_coroutine const&) = delete;
|
||||||
|
|
||||||
pull_coroutine( pull_coroutine &&);
|
pull_coroutine( pull_coroutine &&) noexcept;
|
||||||
|
|
||||||
pull_coroutine & operator=( pull_coroutine && other) {
|
pull_coroutine & operator=( pull_coroutine && other) noexcept {
|
||||||
if ( this != & other) {
|
if ( this != & other) {
|
||||||
cb_ = other.cb_;
|
cb_ = other.cb_;
|
||||||
other.cb_ = nullptr;
|
other.cb_ = nullptr;
|
||||||
@ -66,7 +65,7 @@ public:
|
|||||||
|
|
||||||
bool operator!() const noexcept;
|
bool operator!() const noexcept;
|
||||||
|
|
||||||
T get();
|
T get() noexcept;
|
||||||
|
|
||||||
class iterator : public std::iterator< std::input_iterator_tag, typename std::remove_reference< T >::type > {
|
class iterator : public std::iterator< std::input_iterator_tag, typename std::remove_reference< T >::type > {
|
||||||
private:
|
private:
|
||||||
@ -91,30 +90,31 @@ public:
|
|||||||
typedef typename iterator::pointer pointer_t;
|
typedef typename iterator::pointer pointer_t;
|
||||||
typedef typename iterator::reference reference_t;
|
typedef typename iterator::reference reference_t;
|
||||||
|
|
||||||
iterator() :
|
iterator() noexcept :
|
||||||
c_( nullptr) {
|
c_{ nullptr } {
|
||||||
}
|
}
|
||||||
|
|
||||||
explicit iterator( pull_coroutine< T > * c) :
|
explicit iterator( pull_coroutine< T > * c) :
|
||||||
c_( c) {
|
c_{ c } {
|
||||||
fetch_();
|
fetch_();
|
||||||
}
|
}
|
||||||
|
|
||||||
iterator( iterator const& other) :
|
iterator( iterator const& other) noexcept :
|
||||||
c_( other.c_) {
|
c_{ other.c_ } {
|
||||||
}
|
}
|
||||||
|
|
||||||
iterator & operator=( iterator const& other) {
|
iterator & operator=( iterator const& other) noexcept {
|
||||||
if ( this == & other) return * this;
|
if ( this != & other) {
|
||||||
c_ = other.c_;
|
c_ = other.c_;
|
||||||
|
}
|
||||||
return * this;
|
return * this;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator==( iterator const& other) const {
|
bool operator==( iterator const& other) const noexcept {
|
||||||
return other.c_ == c_;
|
return other.c_ == c_;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator!=( iterator const& other) const {
|
bool operator!=( iterator const& other) const noexcept {
|
||||||
return other.c_ != c_;
|
return other.c_ != c_;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -125,11 +125,11 @@ public:
|
|||||||
|
|
||||||
iterator operator++( int) = delete;
|
iterator operator++( int) = delete;
|
||||||
|
|
||||||
reference_t operator*() const {
|
reference_t operator*() const noexcept {
|
||||||
return c_->cb_->get();
|
return c_->cb_->get();
|
||||||
}
|
}
|
||||||
|
|
||||||
pointer_t operator->() const {
|
pointer_t operator->() const noexcept {
|
||||||
return std::addressof( c_->cb_->get() );
|
return std::addressof( c_->cb_->get() );
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -147,25 +147,25 @@ private:
|
|||||||
|
|
||||||
control_block * cb_;
|
control_block * cb_;
|
||||||
|
|
||||||
explicit pull_coroutine( control_block *);
|
explicit pull_coroutine( control_block *) noexcept;
|
||||||
|
|
||||||
bool has_result_() const;
|
bool has_result_() const noexcept;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
template< typename Fn >
|
template< typename Fn >
|
||||||
explicit pull_coroutine( Fn &&, bool = false);
|
explicit pull_coroutine( Fn &&);
|
||||||
|
|
||||||
template< typename StackAllocator, typename Fn >
|
template< typename StackAllocator, typename Fn >
|
||||||
explicit pull_coroutine( StackAllocator, Fn &&, bool = false);
|
pull_coroutine( StackAllocator, Fn &&);
|
||||||
|
|
||||||
~pull_coroutine();
|
~pull_coroutine() noexcept;
|
||||||
|
|
||||||
pull_coroutine( pull_coroutine const&) = delete;
|
pull_coroutine( pull_coroutine const&) = delete;
|
||||||
pull_coroutine & operator=( pull_coroutine const&) = delete;
|
pull_coroutine & operator=( pull_coroutine const&) = delete;
|
||||||
|
|
||||||
pull_coroutine( pull_coroutine &&);
|
pull_coroutine( pull_coroutine &&) noexcept;
|
||||||
|
|
||||||
pull_coroutine & operator=( pull_coroutine && other) {
|
pull_coroutine & operator=( pull_coroutine && other) noexcept {
|
||||||
if ( this != & other) {
|
if ( this != & other) {
|
||||||
cb_ = other.cb_;
|
cb_ = other.cb_;
|
||||||
other.cb_ = nullptr;
|
other.cb_ = nullptr;
|
||||||
@ -179,7 +179,7 @@ public:
|
|||||||
|
|
||||||
bool operator!() const noexcept;
|
bool operator!() const noexcept;
|
||||||
|
|
||||||
T & get();
|
T & get() noexcept;
|
||||||
|
|
||||||
class iterator : public std::iterator< std::input_iterator_tag, typename std::remove_reference< T >::type > {
|
class iterator : public std::iterator< std::input_iterator_tag, typename std::remove_reference< T >::type > {
|
||||||
private:
|
private:
|
||||||
@ -204,30 +204,31 @@ public:
|
|||||||
typedef typename iterator::pointer pointer_t;
|
typedef typename iterator::pointer pointer_t;
|
||||||
typedef typename iterator::reference reference_t;
|
typedef typename iterator::reference reference_t;
|
||||||
|
|
||||||
iterator() :
|
iterator() noexcept :
|
||||||
c_( nullptr) {
|
c_{ nullptr } {
|
||||||
}
|
}
|
||||||
|
|
||||||
explicit iterator( pull_coroutine< T & > * c) :
|
explicit iterator( pull_coroutine< T & > * c) :
|
||||||
c_( c) {
|
c_{ c } {
|
||||||
fetch_();
|
fetch_();
|
||||||
}
|
}
|
||||||
|
|
||||||
iterator( iterator const& other) :
|
iterator( iterator const& other) noexcept :
|
||||||
c_( other.c_) {
|
c_{ other.c_ } {
|
||||||
}
|
}
|
||||||
|
|
||||||
iterator & operator=( iterator const& other) {
|
iterator & operator=( iterator const& other) noexcept {
|
||||||
if ( this == & other) return * this;
|
if ( this != & other) {
|
||||||
c_ = other.c_;
|
c_ = other.c_;
|
||||||
|
}
|
||||||
return * this;
|
return * this;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator==( iterator const& other) const {
|
bool operator==( iterator const& other) const noexcept {
|
||||||
return other.c_ == c_;
|
return other.c_ == c_;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator!=( iterator const& other) const {
|
bool operator!=( iterator const& other) const noexcept {
|
||||||
return other.c_ != c_;
|
return other.c_ != c_;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -238,11 +239,11 @@ public:
|
|||||||
|
|
||||||
iterator operator++( int) = delete;
|
iterator operator++( int) = delete;
|
||||||
|
|
||||||
reference_t operator*() const {
|
reference_t operator*() const noexcept {
|
||||||
return c_->cb_->get();
|
return c_->cb_->get();
|
||||||
}
|
}
|
||||||
|
|
||||||
pointer_t operator->() const {
|
pointer_t operator->() const noexcept {
|
||||||
return std::addressof( c_->cb_->get() );
|
return std::addressof( c_->cb_->get() );
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -260,23 +261,23 @@ private:
|
|||||||
|
|
||||||
control_block * cb_;
|
control_block * cb_;
|
||||||
|
|
||||||
explicit pull_coroutine( control_block *);
|
explicit pull_coroutine( control_block *) noexcept;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
template< typename Fn >
|
template< typename Fn >
|
||||||
explicit pull_coroutine( Fn &&, bool = false);
|
explicit pull_coroutine( Fn &&);
|
||||||
|
|
||||||
template< typename StackAllocator, typename Fn >
|
template< typename StackAllocator, typename Fn >
|
||||||
explicit pull_coroutine( StackAllocator, Fn &&, bool = false);
|
pull_coroutine( StackAllocator, Fn &&);
|
||||||
|
|
||||||
~pull_coroutine();
|
~pull_coroutine() noexcept;
|
||||||
|
|
||||||
pull_coroutine( pull_coroutine const&) = delete;
|
pull_coroutine( pull_coroutine const&) = delete;
|
||||||
pull_coroutine & operator=( pull_coroutine const&) = delete;
|
pull_coroutine & operator=( pull_coroutine const&) = delete;
|
||||||
|
|
||||||
pull_coroutine( pull_coroutine &&);
|
pull_coroutine( pull_coroutine &&) noexcept;
|
||||||
|
|
||||||
pull_coroutine & operator=( pull_coroutine && other) {
|
pull_coroutine & operator=( pull_coroutine && other) noexcept {
|
||||||
if ( this != & other) {
|
if ( this != & other) {
|
||||||
cb_ = other.cb_;
|
cb_ = other.cb_;
|
||||||
other.cb_ = nullptr;
|
other.cb_ = nullptr;
|
||||||
|
@ -8,16 +8,13 @@
|
|||||||
#define BOOST_COROUTINES2_DETAIL_PULL_COROUTINE_IPP
|
#define BOOST_COROUTINES2_DETAIL_PULL_COROUTINE_IPP
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <memory>
|
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
#include <boost/assert.hpp>
|
#include <boost/assert.hpp>
|
||||||
#include <boost/config.hpp>
|
#include <boost/config.hpp>
|
||||||
|
|
||||||
#include <boost/context/execution_context.hpp>
|
|
||||||
#include <boost/context/stack_context.hpp>
|
|
||||||
|
|
||||||
#include <boost/coroutine2/detail/config.hpp>
|
#include <boost/coroutine2/detail/config.hpp>
|
||||||
|
#include <boost/coroutine2/detail/create_control_block.ipp>
|
||||||
#include <boost/coroutine2/fixedsize_stack.hpp>
|
#include <boost/coroutine2/fixedsize_stack.hpp>
|
||||||
#include <boost/coroutine2/segmented_stack.hpp>
|
#include <boost/coroutine2/segmented_stack.hpp>
|
||||||
|
|
||||||
@ -32,57 +29,41 @@ namespace detail {
|
|||||||
// pull_coroutine< T >
|
// pull_coroutine< T >
|
||||||
|
|
||||||
template< typename T >
|
template< typename T >
|
||||||
pull_coroutine< T >::pull_coroutine( control_block * cb) :
|
pull_coroutine< T >::pull_coroutine( control_block * cb) noexcept :
|
||||||
cb_( cb) {
|
cb_{ cb } {
|
||||||
}
|
}
|
||||||
|
|
||||||
template< typename T >
|
template< typename T >
|
||||||
bool
|
bool
|
||||||
pull_coroutine< T >::has_result_() const {
|
pull_coroutine< T >::has_result_() const noexcept {
|
||||||
return nullptr != cb_->other->t;
|
return nullptr != cb_->other->t;
|
||||||
}
|
}
|
||||||
|
|
||||||
template< typename T >
|
template< typename T >
|
||||||
template< typename Fn >
|
template< typename Fn >
|
||||||
pull_coroutine< T >::pull_coroutine( Fn && fn, bool preserve_fpu) :
|
pull_coroutine< T >::pull_coroutine( Fn && fn) :
|
||||||
pull_coroutine( default_stack(), std::forward< Fn >( fn), preserve_fpu) {
|
pull_coroutine{ default_stack(), std::forward< Fn >( fn) } {
|
||||||
}
|
}
|
||||||
|
|
||||||
template< typename T >
|
template< typename T >
|
||||||
template< typename StackAllocator, typename Fn >
|
template< typename StackAllocator, typename Fn >
|
||||||
pull_coroutine< T >::pull_coroutine( StackAllocator salloc, Fn && fn, bool preserve_fpu) :
|
pull_coroutine< T >::pull_coroutine( StackAllocator salloc, Fn && fn) :
|
||||||
cb_( nullptr) {
|
cb_{ create_control_block< control_block >( salloc, std::forward< Fn >( fn) ) } {
|
||||||
context::stack_context sctx( salloc.allocate() );
|
if ( ! cb_->valid() ) {
|
||||||
// reserve space for control structure
|
cb_->~control_block();
|
||||||
#if defined(BOOST_NO_CXX14_CONSTEXPR) || defined(BOOST_NO_CXX11_STD_ALIGN)
|
cb_ = nullptr;
|
||||||
void * sp = static_cast< char * >( sctx.sp) - sizeof( control_block);
|
}
|
||||||
std::size_t size = sctx.size - sizeof( control_block);
|
|
||||||
#else
|
|
||||||
constexpr std::size_t func_alignment = 64; // alignof( control_block);
|
|
||||||
constexpr std::size_t func_size = sizeof( control_block);
|
|
||||||
// reserve space on stack
|
|
||||||
void * sp = static_cast< char * >( sctx.sp) - func_size - func_alignment;
|
|
||||||
// align sp pointer
|
|
||||||
std::size_t space = func_size + func_alignment;
|
|
||||||
sp = std::align( func_alignment, func_size, sp, space);
|
|
||||||
BOOST_ASSERT( nullptr != sp);
|
|
||||||
// calculate remaining size
|
|
||||||
std::size_t size = sctx.size - ( static_cast< char * >( sctx.sp) - static_cast< char * >( sp) );
|
|
||||||
#endif
|
|
||||||
// placment new for control structure on coroutine stack
|
|
||||||
cb_ = new ( sp) control_block( context::preallocated( sp, size, sctx),
|
|
||||||
salloc, std::forward< Fn >( fn), preserve_fpu);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template< typename T >
|
template< typename T >
|
||||||
pull_coroutine< T >::~pull_coroutine() {
|
pull_coroutine< T >::~pull_coroutine() noexcept {
|
||||||
if ( nullptr != cb_) {
|
if ( nullptr != cb_) {
|
||||||
cb_->~control_block();
|
cb_->~control_block();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template< typename T >
|
template< typename T >
|
||||||
pull_coroutine< T >::pull_coroutine( pull_coroutine && other) :
|
pull_coroutine< T >::pull_coroutine( pull_coroutine && other) noexcept :
|
||||||
cb_( other.cb_) {
|
cb_( other.cb_) {
|
||||||
other.cb_ = nullptr;
|
other.cb_ = nullptr;
|
||||||
}
|
}
|
||||||
@ -107,7 +88,7 @@ pull_coroutine< T >::operator!() const noexcept {
|
|||||||
|
|
||||||
template< typename T >
|
template< typename T >
|
||||||
T
|
T
|
||||||
pull_coroutine< T >::get() {
|
pull_coroutine< T >::get() noexcept {
|
||||||
return std::move( cb_->get() );
|
return std::move( cb_->get() );
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -115,57 +96,41 @@ pull_coroutine< T >::get() {
|
|||||||
// pull_coroutine< T & >
|
// pull_coroutine< T & >
|
||||||
|
|
||||||
template< typename T >
|
template< typename T >
|
||||||
pull_coroutine< T & >::pull_coroutine( control_block * cb) :
|
pull_coroutine< T & >::pull_coroutine( control_block * cb) noexcept :
|
||||||
cb_( cb) {
|
cb_( cb) {
|
||||||
}
|
}
|
||||||
|
|
||||||
template< typename T >
|
template< typename T >
|
||||||
bool
|
bool
|
||||||
pull_coroutine< T & >::has_result_() const {
|
pull_coroutine< T & >::has_result_() const noexcept {
|
||||||
return nullptr != cb_->other->t;
|
return nullptr != cb_->other->t;
|
||||||
}
|
}
|
||||||
|
|
||||||
template< typename T >
|
template< typename T >
|
||||||
template< typename Fn >
|
template< typename Fn >
|
||||||
pull_coroutine< T & >::pull_coroutine( Fn && fn, bool preserve_fpu) :
|
pull_coroutine< T & >::pull_coroutine( Fn && fn) :
|
||||||
pull_coroutine( default_stack(), std::forward< Fn >( fn), preserve_fpu) {
|
pull_coroutine{ default_stack(), std::forward< Fn >( fn) } {
|
||||||
}
|
}
|
||||||
|
|
||||||
template< typename T >
|
template< typename T >
|
||||||
template< typename StackAllocator, typename Fn >
|
template< typename StackAllocator, typename Fn >
|
||||||
pull_coroutine< T & >::pull_coroutine( StackAllocator salloc, Fn && fn, bool preserve_fpu) :
|
pull_coroutine< T & >::pull_coroutine( StackAllocator salloc, Fn && fn) :
|
||||||
cb_( nullptr) {
|
cb_{ create_control_block< control_block >( salloc, std::forward< Fn >( fn) ) } {
|
||||||
context::stack_context sctx( salloc.allocate() );
|
if ( ! cb_->valid() ) {
|
||||||
// reserve space for control structure
|
cb_->~control_block();
|
||||||
#if defined(BOOST_NO_CXX14_CONSTEXPR) || defined(BOOST_NO_CXX11_STD_ALIGN)
|
cb_ = nullptr;
|
||||||
void * sp = static_cast< char * >( sctx.sp) - sizeof( control_block);
|
}
|
||||||
std::size_t size = sctx.size - sizeof( control_block);
|
|
||||||
#else
|
|
||||||
constexpr std::size_t func_alignment = 64; // alignof( control_block);
|
|
||||||
constexpr std::size_t func_size = sizeof( control_block);
|
|
||||||
// reserve space on stack
|
|
||||||
void * sp = static_cast< char * >( sctx.sp) - func_size - func_alignment;
|
|
||||||
// align sp pointer
|
|
||||||
std::size_t space = func_size + func_alignment;
|
|
||||||
sp = std::align( func_alignment, func_size, sp, space);
|
|
||||||
BOOST_ASSERT( nullptr != sp);
|
|
||||||
// calculate remaining size
|
|
||||||
std::size_t size = sctx.size - ( static_cast< char * >( sctx.sp) - static_cast< char * >( sp) );
|
|
||||||
#endif
|
|
||||||
// placment new for control structure on coroutine stack
|
|
||||||
cb_ = new ( sp) control_block( context::preallocated( sp, size, sctx),
|
|
||||||
salloc, std::forward< Fn >( fn), preserve_fpu);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template< typename T >
|
template< typename T >
|
||||||
pull_coroutine< T & >::~pull_coroutine() {
|
pull_coroutine< T & >::~pull_coroutine() noexcept {
|
||||||
if ( nullptr != cb_) {
|
if ( nullptr != cb_) {
|
||||||
cb_->~control_block();
|
cb_->~control_block();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template< typename T >
|
template< typename T >
|
||||||
pull_coroutine< T & >::pull_coroutine( pull_coroutine && other) :
|
pull_coroutine< T & >::pull_coroutine( pull_coroutine && other) noexcept :
|
||||||
cb_( other.cb_) {
|
cb_( other.cb_) {
|
||||||
other.cb_ = nullptr;
|
other.cb_ = nullptr;
|
||||||
}
|
}
|
||||||
@ -190,7 +155,7 @@ pull_coroutine< T & >::operator!() const noexcept {
|
|||||||
|
|
||||||
template< typename T >
|
template< typename T >
|
||||||
T &
|
T &
|
||||||
pull_coroutine< T & >::get() {
|
pull_coroutine< T & >::get() noexcept {
|
||||||
return cb_->get();
|
return cb_->get();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -198,49 +163,33 @@ pull_coroutine< T & >::get() {
|
|||||||
// pull_coroutine< void >
|
// pull_coroutine< void >
|
||||||
|
|
||||||
inline
|
inline
|
||||||
pull_coroutine< void >::pull_coroutine( control_block * cb) :
|
pull_coroutine< void >::pull_coroutine( control_block * cb) noexcept :
|
||||||
cb_( cb) {
|
cb_( cb) {
|
||||||
}
|
}
|
||||||
|
|
||||||
template< typename Fn >
|
template< typename Fn >
|
||||||
pull_coroutine< void >::pull_coroutine( Fn && fn, bool preserve_fpu) :
|
pull_coroutine< void >::pull_coroutine( Fn && fn) :
|
||||||
pull_coroutine( default_stack(), std::forward< Fn >( fn), preserve_fpu) {
|
pull_coroutine{ default_stack(), std::forward< Fn >( fn) } {
|
||||||
}
|
}
|
||||||
|
|
||||||
template< typename StackAllocator, typename Fn >
|
template< typename StackAllocator, typename Fn >
|
||||||
pull_coroutine< void >::pull_coroutine( StackAllocator salloc, Fn && fn, bool preserve_fpu) :
|
pull_coroutine< void >::pull_coroutine( StackAllocator salloc, Fn && fn) :
|
||||||
cb_( nullptr) {
|
cb_{ create_control_block< control_block >( salloc, std::forward< Fn >( fn) ) } {
|
||||||
context::stack_context sctx( salloc.allocate() );
|
if ( ! cb_->valid() ) {
|
||||||
// reserve space for control structure
|
cb_->~control_block();
|
||||||
#if defined(BOOST_NO_CXX14_CONSTEXPR) || defined(BOOST_NO_CXX11_STD_ALIGN)
|
cb_ = nullptr;
|
||||||
void * sp = static_cast< char * >( sctx.sp) - sizeof( control_block);
|
}
|
||||||
std::size_t size = sctx.size - sizeof( control_block);
|
|
||||||
#else
|
|
||||||
constexpr std::size_t func_alignment = 64; // alignof( control_block);
|
|
||||||
constexpr std::size_t func_size = sizeof( control_block);
|
|
||||||
// reserve space on stack
|
|
||||||
void * sp = static_cast< char * >( sctx.sp) - func_size - func_alignment;
|
|
||||||
// align sp pointer
|
|
||||||
std::size_t space = func_size + func_alignment;
|
|
||||||
sp = std::align( func_alignment, func_size, sp, space);
|
|
||||||
BOOST_ASSERT( nullptr != sp);
|
|
||||||
// calculate remaining size
|
|
||||||
std::size_t size = sctx.size - ( static_cast< char * >( sctx.sp) - static_cast< char * >( sp) );
|
|
||||||
#endif
|
|
||||||
// placment new for control structure on coroutine stack
|
|
||||||
cb_ = new ( sp) control_block( context::preallocated( sp, size, sctx),
|
|
||||||
salloc, std::forward< Fn >( fn), preserve_fpu);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline
|
inline
|
||||||
pull_coroutine< void >::~pull_coroutine() {
|
pull_coroutine< void >::~pull_coroutine() noexcept {
|
||||||
if ( nullptr != cb_) {
|
if ( nullptr != cb_) {
|
||||||
cb_->~control_block();
|
cb_->~control_block();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline
|
inline
|
||||||
pull_coroutine< void >::pull_coroutine( pull_coroutine && other) :
|
pull_coroutine< void >::pull_coroutine( pull_coroutine && other) noexcept :
|
||||||
cb_( other.cb_) {
|
cb_( other.cb_) {
|
||||||
other.cb_ = nullptr;
|
other.cb_ = nullptr;
|
||||||
}
|
}
|
||||||
|
@ -12,6 +12,8 @@
|
|||||||
#include <boost/config.hpp>
|
#include <boost/config.hpp>
|
||||||
#include <boost/context/execution_context.hpp>
|
#include <boost/context/execution_context.hpp>
|
||||||
|
|
||||||
|
#include <boost/coroutine2/detail/state.hpp>
|
||||||
|
|
||||||
#ifdef BOOST_HAS_ABI_HEADERS
|
#ifdef BOOST_HAS_ABI_HEADERS
|
||||||
# include BOOST_ABI_PREFIX
|
# include BOOST_ABI_PREFIX
|
||||||
#endif
|
#endif
|
||||||
@ -24,16 +26,15 @@ template< typename T >
|
|||||||
struct push_coroutine< T >::control_block {
|
struct push_coroutine< T >::control_block {
|
||||||
typename pull_coroutine< T >::control_block * other;
|
typename pull_coroutine< T >::control_block * other;
|
||||||
boost::context::execution_context ctx;
|
boost::context::execution_context ctx;
|
||||||
bool preserve_fpu;
|
state_t state;
|
||||||
int state;
|
|
||||||
std::exception_ptr except;
|
std::exception_ptr except;
|
||||||
|
|
||||||
template< typename StackAllocator, typename Fn >
|
template< typename StackAllocator, typename Fn >
|
||||||
control_block( context::preallocated, StackAllocator, Fn &&, bool);
|
control_block( context::preallocated, StackAllocator, Fn &&);
|
||||||
|
|
||||||
explicit control_block( typename pull_coroutine< T >::control_block *, boost::context::execution_context const&);
|
control_block( typename pull_coroutine< T >::control_block *, boost::context::execution_context const&) noexcept;
|
||||||
|
|
||||||
~control_block();
|
~control_block() noexcept;
|
||||||
|
|
||||||
control_block( control_block &) = delete;
|
control_block( control_block &) = delete;
|
||||||
control_block & operator=( control_block &) = delete;
|
control_block & operator=( control_block &) = delete;
|
||||||
@ -49,16 +50,15 @@ template< typename T >
|
|||||||
struct push_coroutine< T & >::control_block {
|
struct push_coroutine< T & >::control_block {
|
||||||
typename pull_coroutine< T & >::control_block * other;
|
typename pull_coroutine< T & >::control_block * other;
|
||||||
boost::context::execution_context ctx;
|
boost::context::execution_context ctx;
|
||||||
bool preserve_fpu;
|
state_t state;
|
||||||
int state;
|
|
||||||
std::exception_ptr except;
|
std::exception_ptr except;
|
||||||
|
|
||||||
template< typename StackAllocator, typename Fn >
|
template< typename StackAllocator, typename Fn >
|
||||||
control_block( context::preallocated, StackAllocator, Fn &&, bool);
|
control_block( context::preallocated, StackAllocator, Fn &&);
|
||||||
|
|
||||||
explicit control_block( typename pull_coroutine< T & >::control_block *, boost::context::execution_context const&);
|
control_block( typename pull_coroutine< T & >::control_block *, boost::context::execution_context const&) noexcept;
|
||||||
|
|
||||||
~control_block();
|
~control_block() noexcept;
|
||||||
|
|
||||||
control_block( control_block &) = delete;
|
control_block( control_block &) = delete;
|
||||||
control_block & operator=( control_block &) = delete;
|
control_block & operator=( control_block &) = delete;
|
||||||
@ -71,16 +71,15 @@ struct push_coroutine< T & >::control_block {
|
|||||||
struct push_coroutine< void >::control_block {
|
struct push_coroutine< void >::control_block {
|
||||||
pull_coroutine< void >::control_block * other;
|
pull_coroutine< void >::control_block * other;
|
||||||
boost::context::execution_context ctx;
|
boost::context::execution_context ctx;
|
||||||
bool preserve_fpu;
|
state_t state;
|
||||||
int state;
|
|
||||||
std::exception_ptr except;
|
std::exception_ptr except;
|
||||||
|
|
||||||
template< typename StackAllocator, typename Fn >
|
template< typename StackAllocator, typename Fn >
|
||||||
control_block( context::preallocated, StackAllocator, Fn &&, bool);
|
control_block( context::preallocated, StackAllocator, Fn &&);
|
||||||
|
|
||||||
explicit control_block( pull_coroutine< void >::control_block *, boost::context::execution_context const&);
|
control_block( pull_coroutine< void >::control_block *, boost::context::execution_context const&) noexcept;
|
||||||
|
|
||||||
~control_block();
|
~control_block() noexcept;
|
||||||
|
|
||||||
control_block( control_block &) = delete;
|
control_block( control_block &) = delete;
|
||||||
control_block & operator=( control_block &) = delete;
|
control_block & operator=( control_block &) = delete;
|
||||||
|
@ -33,16 +33,16 @@ namespace detail {
|
|||||||
template< typename T >
|
template< typename T >
|
||||||
template< typename StackAllocator, typename Fn >
|
template< typename StackAllocator, typename Fn >
|
||||||
push_coroutine< T >::control_block::control_block( context::preallocated palloc, StackAllocator salloc,
|
push_coroutine< T >::control_block::control_block( context::preallocated palloc, StackAllocator salloc,
|
||||||
Fn && fn_, bool preserve_fpu_) :
|
Fn && fn_) :
|
||||||
other( nullptr),
|
other{ nullptr },
|
||||||
ctx( std::allocator_arg, palloc, salloc,
|
ctx{ std::allocator_arg, palloc, salloc,
|
||||||
[=,fn=std::forward< Fn >( fn_),ctx=boost::context::execution_context::current()] (void *) mutable -> void {
|
[this,fn=std::forward< Fn >( fn_),ctx=boost::context::execution_context::current()] (void *) mutable noexcept {
|
||||||
// create synthesized pull_coroutine< T >
|
// create synthesized pull_coroutine< T >
|
||||||
typename pull_coroutine< T >::control_block synthesized_cb( this, ctx);
|
typename pull_coroutine< T >::control_block synthesized_cb{ this, ctx };
|
||||||
pull_coroutine< T > synthesized( & synthesized_cb);
|
pull_coroutine< T > synthesized{ & synthesized_cb };
|
||||||
other = & synthesized_cb;
|
other = & synthesized_cb;
|
||||||
// jump back to ctor
|
// jump back to ctor
|
||||||
T * t = reinterpret_cast< T * >( ctx( nullptr, preserve_fpu) );
|
T * t = static_cast< T * >( ctx() );
|
||||||
// set transferred value
|
// set transferred value
|
||||||
synthesized_cb.set( t);
|
synthesized_cb.set( t);
|
||||||
try {
|
try {
|
||||||
@ -55,35 +55,33 @@ push_coroutine< T >::control_block::control_block( context::preallocated palloc,
|
|||||||
except = std::current_exception();
|
except = std::current_exception();
|
||||||
}
|
}
|
||||||
// set termination flags
|
// set termination flags
|
||||||
state |= static_cast< int >( state_t::complete);
|
state |= state_t::complete;
|
||||||
// jump back to ctx
|
// jump back to ctx
|
||||||
other->ctx( nullptr, preserve_fpu);
|
other->ctx();
|
||||||
BOOST_ASSERT_MSG( false, "push_coroutine is complete");
|
BOOST_ASSERT_MSG( false, "push_coroutine is complete");
|
||||||
}),
|
}},
|
||||||
preserve_fpu( preserve_fpu_),
|
state{ state_t::unwind },
|
||||||
state( static_cast< int >( state_t::unwind) ),
|
except{} {
|
||||||
except() {
|
|
||||||
// enter coroutine-fn in order to get other set
|
// enter coroutine-fn in order to get other set
|
||||||
ctx( nullptr, preserve_fpu);
|
ctx();
|
||||||
}
|
}
|
||||||
|
|
||||||
template< typename T >
|
template< typename T >
|
||||||
push_coroutine< T >::control_block::control_block( typename pull_coroutine< T >::control_block * cb,
|
push_coroutine< T >::control_block::control_block( typename pull_coroutine< T >::control_block * cb,
|
||||||
boost::context::execution_context const& ctx_) :
|
boost::context::execution_context const& ctx_) noexcept :
|
||||||
other( cb),
|
other{ cb },
|
||||||
ctx( ctx_),
|
ctx{ ctx_ },
|
||||||
preserve_fpu( other->preserve_fpu),
|
state{ state_t::none },
|
||||||
state( 0),
|
except{} {
|
||||||
except() {
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template< typename T >
|
template< typename T >
|
||||||
push_coroutine< T >::control_block::~control_block() {
|
push_coroutine< T >::control_block::~control_block() noexcept {
|
||||||
if ( 0 == ( state & static_cast< int >( state_t::complete ) ) &&
|
if ( state_t::none == ( state & state_t::complete) &&
|
||||||
0 != ( state & static_cast< int >( state_t::unwind) ) ) {
|
state_t::none != ( state & state_t::unwind) ) {
|
||||||
// set early-exit flag
|
// set early-exit flag
|
||||||
state |= static_cast< int >( state_t::early_exit);
|
state |= state_t::early_exit;
|
||||||
ctx( nullptr, preserve_fpu);
|
ctx();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -92,12 +90,12 @@ void
|
|||||||
push_coroutine< T >::control_block::resume( T const& t) {
|
push_coroutine< T >::control_block::resume( T const& t) {
|
||||||
other->ctx = boost::context::execution_context::current();
|
other->ctx = boost::context::execution_context::current();
|
||||||
// pass an pointer to other context
|
// pass an pointer to other context
|
||||||
ctx( const_cast< T * >( & t), preserve_fpu);
|
ctx( const_cast< T * >( & t) );
|
||||||
if ( except) {
|
if ( except) {
|
||||||
std::rethrow_exception( except);
|
std::rethrow_exception( except);
|
||||||
}
|
}
|
||||||
// test early-exit-flag
|
// test early-exit-flag
|
||||||
if ( 0 != ( ( other->state) & static_cast< int >( state_t::early_exit) ) ) {
|
if ( state_t::none != ( other->state & state_t::early_exit) ) {
|
||||||
throw forced_unwind();
|
throw forced_unwind();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -107,12 +105,12 @@ void
|
|||||||
push_coroutine< T >::control_block::resume( T && t) {
|
push_coroutine< T >::control_block::resume( T && t) {
|
||||||
other->ctx = boost::context::execution_context::current();
|
other->ctx = boost::context::execution_context::current();
|
||||||
// pass an pointer to other context
|
// pass an pointer to other context
|
||||||
ctx( std::addressof( t), preserve_fpu);
|
ctx( std::addressof( t) );
|
||||||
if ( except) {
|
if ( except) {
|
||||||
std::rethrow_exception( except);
|
std::rethrow_exception( except);
|
||||||
}
|
}
|
||||||
// test early-exit-flag
|
// test early-exit-flag
|
||||||
if ( 0 != ( ( other->state) & static_cast< int >( state_t::early_exit) ) ) {
|
if ( state_t::none != ( other->state & state_t::early_exit) ) {
|
||||||
throw forced_unwind();
|
throw forced_unwind();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -120,7 +118,7 @@ push_coroutine< T >::control_block::resume( T && t) {
|
|||||||
template< typename T >
|
template< typename T >
|
||||||
bool
|
bool
|
||||||
push_coroutine< T >::control_block::valid() const noexcept {
|
push_coroutine< T >::control_block::valid() const noexcept {
|
||||||
return 0 == ( state & static_cast< int >( state_t::complete) );
|
return state_t::none == ( state & state_t::complete );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -129,16 +127,16 @@ push_coroutine< T >::control_block::valid() const noexcept {
|
|||||||
template< typename T >
|
template< typename T >
|
||||||
template< typename StackAllocator, typename Fn >
|
template< typename StackAllocator, typename Fn >
|
||||||
push_coroutine< T & >::control_block::control_block( context::preallocated palloc, StackAllocator salloc,
|
push_coroutine< T & >::control_block::control_block( context::preallocated palloc, StackAllocator salloc,
|
||||||
Fn && fn_, bool preserve_fpu_) :
|
Fn && fn_) :
|
||||||
other( nullptr),
|
other{ nullptr },
|
||||||
ctx( std::allocator_arg, palloc, salloc,
|
ctx{ std::allocator_arg, palloc, salloc,
|
||||||
[=,fn=std::forward< Fn >( fn_),ctx=boost::context::execution_context::current()] (void *) mutable -> void {
|
[this,fn=std::forward< Fn >( fn_),ctx=boost::context::execution_context::current()] (void *) mutable noexcept {
|
||||||
// create synthesized pull_coroutine< T >
|
// create synthesized pull_coroutine< T >
|
||||||
typename pull_coroutine< T & >::control_block synthesized_cb( this, ctx);
|
typename pull_coroutine< T & >::control_block synthesized_cb{ this, ctx };
|
||||||
pull_coroutine< T & > synthesized( & synthesized_cb);
|
pull_coroutine< T & > synthesized{ & synthesized_cb };
|
||||||
other = & synthesized_cb;
|
other = & synthesized_cb;
|
||||||
// jump back to ctor
|
// jump back to ctor
|
||||||
T * t = reinterpret_cast< T * >( ctx( nullptr, preserve_fpu) );
|
T * t = static_cast< T * >( ctx() );
|
||||||
// set transferred value
|
// set transferred value
|
||||||
synthesized_cb.t = t;
|
synthesized_cb.t = t;
|
||||||
try {
|
try {
|
||||||
@ -151,35 +149,33 @@ push_coroutine< T & >::control_block::control_block( context::preallocated pallo
|
|||||||
except = std::current_exception();
|
except = std::current_exception();
|
||||||
}
|
}
|
||||||
// set termination flags
|
// set termination flags
|
||||||
state |= static_cast< int >( state_t::complete);
|
state |= state_t::complete;
|
||||||
// jump back to ctx
|
// jump back to ctx
|
||||||
other->ctx( nullptr, preserve_fpu);
|
other->ctx();
|
||||||
BOOST_ASSERT_MSG( false, "push_coroutine is complete");
|
BOOST_ASSERT_MSG( false, "push_coroutine is complete");
|
||||||
}),
|
}},
|
||||||
preserve_fpu( preserve_fpu_),
|
state{ state_t::unwind },
|
||||||
state( static_cast< int >( state_t::unwind) ),
|
except{} {
|
||||||
except() {
|
|
||||||
// enter coroutine-fn in order to get other set
|
// enter coroutine-fn in order to get other set
|
||||||
ctx( nullptr, preserve_fpu);
|
ctx();
|
||||||
}
|
}
|
||||||
|
|
||||||
template< typename T >
|
template< typename T >
|
||||||
push_coroutine< T & >::control_block::control_block( typename pull_coroutine< T & >::control_block * cb,
|
push_coroutine< T & >::control_block::control_block( typename pull_coroutine< T & >::control_block * cb,
|
||||||
boost::context::execution_context const& ctx_) :
|
boost::context::execution_context const& ctx_) noexcept :
|
||||||
other( cb),
|
other{ cb },
|
||||||
ctx( ctx_),
|
ctx{ ctx_ },
|
||||||
preserve_fpu( other->preserve_fpu),
|
state{ state_t::none },
|
||||||
state( 0),
|
except{} {
|
||||||
except() {
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template< typename T >
|
template< typename T >
|
||||||
push_coroutine< T & >::control_block::~control_block() {
|
push_coroutine< T & >::control_block::~control_block() noexcept {
|
||||||
if ( 0 == ( state & static_cast< int >( state_t::complete ) ) &&
|
if ( state_t::none == ( state & state_t::complete) &&
|
||||||
0 != ( state & static_cast< int >( state_t::unwind) ) ) {
|
state_t::none != ( state & state_t::unwind) ) {
|
||||||
// set early-exit flag
|
// set early-exit flag
|
||||||
state |= static_cast< int >( state_t::early_exit);
|
state |= state_t::early_exit;
|
||||||
ctx( nullptr, preserve_fpu);
|
ctx();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -188,12 +184,12 @@ void
|
|||||||
push_coroutine< T & >::control_block::resume( T & t) {
|
push_coroutine< T & >::control_block::resume( T & t) {
|
||||||
other->ctx = boost::context::execution_context::current();
|
other->ctx = boost::context::execution_context::current();
|
||||||
// pass an pointer to other context
|
// pass an pointer to other context
|
||||||
ctx( const_cast< typename std::remove_const< T >::type * >( std::addressof( t) ), preserve_fpu);
|
ctx( const_cast< typename std::remove_const< T >::type * >( std::addressof( t) ) );
|
||||||
if ( except) {
|
if ( except) {
|
||||||
std::rethrow_exception( except);
|
std::rethrow_exception( except);
|
||||||
}
|
}
|
||||||
// test early-exit-flag
|
// test early-exit-flag
|
||||||
if ( 0 != ( ( other->state) & static_cast< int >( state_t::early_exit) ) ) {
|
if ( state_t::none != ( other->state & state_t::early_exit) ) {
|
||||||
throw forced_unwind();
|
throw forced_unwind();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -201,23 +197,23 @@ push_coroutine< T & >::control_block::resume( T & t) {
|
|||||||
template< typename T >
|
template< typename T >
|
||||||
bool
|
bool
|
||||||
push_coroutine< T & >::control_block::valid() const noexcept {
|
push_coroutine< T & >::control_block::valid() const noexcept {
|
||||||
return 0 == ( state & static_cast< int >( state_t::complete) );
|
return state_t::none == ( state & state_t::complete );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// push_coroutine< void >
|
// push_coroutine< void >
|
||||||
|
|
||||||
template< typename StackAllocator, typename Fn >
|
template< typename StackAllocator, typename Fn >
|
||||||
push_coroutine< void >::control_block::control_block( context::preallocated palloc, StackAllocator salloc, Fn && fn_, bool preserve_fpu_) :
|
push_coroutine< void >::control_block::control_block( context::preallocated palloc, StackAllocator salloc, Fn && fn_) :
|
||||||
other( nullptr),
|
other{ nullptr },
|
||||||
ctx( std::allocator_arg, palloc, salloc,
|
ctx{ std::allocator_arg, palloc, salloc,
|
||||||
[=,fn=std::forward< Fn >( fn_),ctx=boost::context::execution_context::current()] (void *) mutable -> void {
|
[this,fn=std::forward< Fn >( fn_),ctx=boost::context::execution_context::current()] (void *) mutable noexcept {
|
||||||
// create synthesized pull_coroutine< T >
|
// create synthesized pull_coroutine< T >
|
||||||
typename pull_coroutine< void >::control_block synthesized_cb( this, ctx);
|
typename pull_coroutine< void >::control_block synthesized_cb{ this, ctx };
|
||||||
pull_coroutine< void > synthesized( & synthesized_cb);
|
pull_coroutine< void > synthesized{ & synthesized_cb };
|
||||||
other = & synthesized_cb;
|
other = & synthesized_cb;
|
||||||
// jump back to ctor
|
// jump back to ctor
|
||||||
ctx( nullptr, preserve_fpu);
|
ctx();
|
||||||
try {
|
try {
|
||||||
// call coroutine-fn with synthesized pull_coroutine as argument
|
// call coroutine-fn with synthesized pull_coroutine as argument
|
||||||
fn( synthesized);
|
fn( synthesized);
|
||||||
@ -228,35 +224,33 @@ push_coroutine< void >::control_block::control_block( context::preallocated pall
|
|||||||
except = std::current_exception();
|
except = std::current_exception();
|
||||||
}
|
}
|
||||||
// set termination flags
|
// set termination flags
|
||||||
state |= static_cast< int >( state_t::complete);
|
state |= state_t::complete;
|
||||||
// jump back to ctx
|
// jump back to ctx
|
||||||
other->ctx( nullptr, preserve_fpu);
|
other->ctx();
|
||||||
BOOST_ASSERT_MSG( false, "push_coroutine is complete");
|
BOOST_ASSERT_MSG( false, "push_coroutine is complete");
|
||||||
}),
|
}},
|
||||||
preserve_fpu( preserve_fpu_),
|
state{ state_t::unwind },
|
||||||
state( static_cast< int >( state_t::unwind) ),
|
except{} {
|
||||||
except() {
|
|
||||||
// enter coroutine-fn in order to get other set
|
// enter coroutine-fn in order to get other set
|
||||||
ctx( nullptr, preserve_fpu);
|
ctx();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline
|
inline
|
||||||
push_coroutine< void >::control_block::control_block( pull_coroutine< void >::control_block * cb,
|
push_coroutine< void >::control_block::control_block( pull_coroutine< void >::control_block * cb,
|
||||||
boost::context::execution_context const& ctx_) :
|
boost::context::execution_context const& ctx_) noexcept :
|
||||||
other( cb),
|
other{ cb },
|
||||||
ctx( ctx_),
|
ctx{ ctx_ },
|
||||||
preserve_fpu( other->preserve_fpu),
|
state{ state_t::none },
|
||||||
state( 0),
|
except{} {
|
||||||
except() {
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline
|
inline
|
||||||
push_coroutine< void >::control_block::~control_block() {
|
push_coroutine< void >::control_block::~control_block() noexcept {
|
||||||
if ( 0 == ( state & static_cast< int >( state_t::complete ) ) &&
|
if ( state_t::none == ( state & state_t::complete) &&
|
||||||
0 != ( state & static_cast< int >( state_t::unwind) ) ) {
|
state_t::none != ( state & state_t::unwind) ) {
|
||||||
// set early-exit flag
|
// set early-exit flag
|
||||||
state |= static_cast< int >( state_t::early_exit);
|
state |= state_t::early_exit;
|
||||||
ctx( nullptr, preserve_fpu);
|
ctx();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -264,12 +258,12 @@ inline
|
|||||||
void
|
void
|
||||||
push_coroutine< void >::control_block::resume() {
|
push_coroutine< void >::control_block::resume() {
|
||||||
other->ctx = boost::context::execution_context::current();
|
other->ctx = boost::context::execution_context::current();
|
||||||
ctx( nullptr, preserve_fpu);
|
ctx();
|
||||||
if ( except) {
|
if ( except) {
|
||||||
std::rethrow_exception( except);
|
std::rethrow_exception( except);
|
||||||
}
|
}
|
||||||
// test early-exit-flag
|
// test early-exit-flag
|
||||||
if ( 0 != ( ( other->state) & static_cast< int >( state_t::early_exit) ) ) {
|
if ( state_t::none != ( other->state & state_t::early_exit) ) {
|
||||||
throw forced_unwind();
|
throw forced_unwind();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -277,7 +271,7 @@ push_coroutine< void >::control_block::resume() {
|
|||||||
inline
|
inline
|
||||||
bool
|
bool
|
||||||
push_coroutine< void >::control_block::valid() const noexcept {
|
push_coroutine< void >::control_block::valid() const noexcept {
|
||||||
return 0 == ( state & static_cast< int >( state_t::complete) );
|
return state_t::none == ( state & state_t::complete );
|
||||||
}
|
}
|
||||||
|
|
||||||
}}}
|
}}}
|
||||||
|
@ -12,7 +12,6 @@
|
|||||||
|
|
||||||
#include <boost/assert.hpp>
|
#include <boost/assert.hpp>
|
||||||
#include <boost/config.hpp>
|
#include <boost/config.hpp>
|
||||||
#include <boost/context/execution_context.hpp>
|
|
||||||
|
|
||||||
#include <boost/coroutine2/detail/config.hpp>
|
#include <boost/coroutine2/detail/config.hpp>
|
||||||
|
|
||||||
@ -34,23 +33,23 @@ private:
|
|||||||
|
|
||||||
control_block * cb_;
|
control_block * cb_;
|
||||||
|
|
||||||
explicit push_coroutine( control_block *);
|
explicit push_coroutine( control_block *) noexcept;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
template< typename Fn >
|
template< typename Fn >
|
||||||
explicit push_coroutine( Fn &&, bool = false);
|
explicit push_coroutine( Fn &&);
|
||||||
|
|
||||||
template< typename StackAllocator, typename Fn >
|
template< typename StackAllocator, typename Fn >
|
||||||
explicit push_coroutine( StackAllocator, Fn &&, bool = false);
|
push_coroutine( StackAllocator, Fn &&);
|
||||||
|
|
||||||
~push_coroutine();
|
~push_coroutine() noexcept;
|
||||||
|
|
||||||
push_coroutine( push_coroutine const&) = delete;
|
push_coroutine( push_coroutine const&) = delete;
|
||||||
push_coroutine & operator=( push_coroutine const&) = delete;
|
push_coroutine & operator=( push_coroutine const&) = delete;
|
||||||
|
|
||||||
push_coroutine( push_coroutine &&);
|
push_coroutine( push_coroutine &&) noexcept;
|
||||||
|
|
||||||
push_coroutine & operator=( push_coroutine && other) {
|
push_coroutine & operator=( push_coroutine && other) noexcept {
|
||||||
if ( this != & other) {
|
if ( this != & other) {
|
||||||
cb_ = other.cb_;
|
cb_ = other.cb_;
|
||||||
other.cb_ = nullptr;
|
other.cb_ = nullptr;
|
||||||
@ -71,33 +70,35 @@ public:
|
|||||||
push_coroutine< T > * c_;
|
push_coroutine< T > * c_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
iterator() :
|
iterator() noexcept :
|
||||||
c_( nullptr) {
|
c_{ nullptr } {
|
||||||
}
|
}
|
||||||
|
|
||||||
explicit iterator( push_coroutine< T > * c) :
|
explicit iterator( push_coroutine< T > * c) noexcept :
|
||||||
c_( c) {
|
c_{ c } {
|
||||||
}
|
}
|
||||||
|
|
||||||
iterator & operator=( T t) {
|
iterator & operator=( T t) {
|
||||||
BOOST_ASSERT( c_);
|
BOOST_ASSERT( c_);
|
||||||
if ( ! ( * c_)( t) ) c_ = 0;
|
if ( ! ( * c_)( t) ) {
|
||||||
|
c_ = nullptr;
|
||||||
|
}
|
||||||
return * this;
|
return * this;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator==( iterator const& other) const {
|
bool operator==( iterator const& other) const noexcept {
|
||||||
return other.c_ == c_;
|
return other.c_ == c_;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator!=( iterator const& other) const {
|
bool operator!=( iterator const& other) const noexcept {
|
||||||
return other.c_ != c_;
|
return other.c_ != c_;
|
||||||
}
|
}
|
||||||
|
|
||||||
iterator & operator*() {
|
iterator & operator*() noexcept {
|
||||||
return * this;
|
return * this;
|
||||||
}
|
}
|
||||||
|
|
||||||
iterator & operator++() {
|
iterator & operator++() noexcept {
|
||||||
return * this;
|
return * this;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -113,23 +114,23 @@ private:
|
|||||||
|
|
||||||
control_block * cb_;
|
control_block * cb_;
|
||||||
|
|
||||||
explicit push_coroutine( control_block *);
|
explicit push_coroutine( control_block *) noexcept;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
template< typename Fn >
|
template< typename Fn >
|
||||||
explicit push_coroutine( Fn &&, bool = false);
|
explicit push_coroutine( Fn &&);
|
||||||
|
|
||||||
template< typename StackAllocator, typename Fn >
|
template< typename StackAllocator, typename Fn >
|
||||||
explicit push_coroutine( StackAllocator, Fn &&, bool = false);
|
push_coroutine( StackAllocator, Fn &&);
|
||||||
|
|
||||||
~push_coroutine();
|
~push_coroutine() noexcept;
|
||||||
|
|
||||||
push_coroutine( push_coroutine const&) = delete;
|
push_coroutine( push_coroutine const&) = delete;
|
||||||
push_coroutine & operator=( push_coroutine const&) = delete;
|
push_coroutine & operator=( push_coroutine const&) = delete;
|
||||||
|
|
||||||
push_coroutine( push_coroutine &&);
|
push_coroutine( push_coroutine &&) noexcept;
|
||||||
|
|
||||||
push_coroutine & operator=( push_coroutine && other) {
|
push_coroutine & operator=( push_coroutine && other) noexcept {
|
||||||
if ( this != & other) {
|
if ( this != & other) {
|
||||||
cb_ = other.cb_;
|
cb_ = other.cb_;
|
||||||
other.cb_ = nullptr;
|
other.cb_ = nullptr;
|
||||||
@ -148,33 +149,35 @@ public:
|
|||||||
push_coroutine< T & > * c_;
|
push_coroutine< T & > * c_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
iterator() :
|
iterator() noexcept :
|
||||||
c_( nullptr) {
|
c_{ nullptr } {
|
||||||
}
|
}
|
||||||
|
|
||||||
explicit iterator( push_coroutine< T & > * c) :
|
explicit iterator( push_coroutine< T & > * c) noexcept :
|
||||||
c_( c) {
|
c_{ c } {
|
||||||
}
|
}
|
||||||
|
|
||||||
iterator & operator=( T & t) {
|
iterator & operator=( T & t) {
|
||||||
BOOST_ASSERT( c_);
|
BOOST_ASSERT( c_);
|
||||||
if ( ! ( * c_)( t) ) c_ = 0;
|
if ( ! ( * c_)( t) ) {
|
||||||
|
c_ = nullptr;
|
||||||
|
}
|
||||||
return * this;
|
return * this;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator==( iterator const& other) const {
|
bool operator==( iterator const& other) const noexcept {
|
||||||
return other.c_ == c_;
|
return other.c_ == c_;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator!=( iterator const& other) const {
|
bool operator!=( iterator const& other) const noexcept {
|
||||||
return other.c_ != c_;
|
return other.c_ != c_;
|
||||||
}
|
}
|
||||||
|
|
||||||
iterator & operator*() {
|
iterator & operator*() noexcept {
|
||||||
return * this;
|
return * this;
|
||||||
}
|
}
|
||||||
|
|
||||||
iterator & operator++() {
|
iterator & operator++() noexcept {
|
||||||
return * this;
|
return * this;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -190,23 +193,23 @@ private:
|
|||||||
|
|
||||||
control_block * cb_;
|
control_block * cb_;
|
||||||
|
|
||||||
explicit push_coroutine( control_block *);
|
explicit push_coroutine( control_block *) noexcept;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
template< typename Fn >
|
template< typename Fn >
|
||||||
explicit push_coroutine( Fn &&, bool = false);
|
explicit push_coroutine( Fn &&);
|
||||||
|
|
||||||
template< typename StackAllocator, typename Fn >
|
template< typename StackAllocator, typename Fn >
|
||||||
explicit push_coroutine( StackAllocator, Fn &&, bool = false);
|
push_coroutine( StackAllocator, Fn &&);
|
||||||
|
|
||||||
~push_coroutine();
|
~push_coroutine() noexcept;
|
||||||
|
|
||||||
push_coroutine( push_coroutine const&) = delete;
|
push_coroutine( push_coroutine const&) = delete;
|
||||||
push_coroutine & operator=( push_coroutine const&) = delete;
|
push_coroutine & operator=( push_coroutine const&) = delete;
|
||||||
|
|
||||||
push_coroutine( push_coroutine &&);
|
push_coroutine( push_coroutine &&) noexcept;
|
||||||
|
|
||||||
push_coroutine & operator=( push_coroutine && other) {
|
push_coroutine & operator=( push_coroutine && other) noexcept {
|
||||||
if ( this != & other) {
|
if ( this != & other) {
|
||||||
cb_ = other.cb_;
|
cb_ = other.cb_;
|
||||||
other.cb_ = nullptr;
|
other.cb_ = nullptr;
|
||||||
|
@ -7,16 +7,13 @@
|
|||||||
#ifndef BOOST_COROUTINES2_DETAIL_PUSH_COROUTINE_IPP
|
#ifndef BOOST_COROUTINES2_DETAIL_PUSH_COROUTINE_IPP
|
||||||
#define BOOST_COROUTINES2_DETAIL_PUSH_COROUTINE_IPP
|
#define BOOST_COROUTINES2_DETAIL_PUSH_COROUTINE_IPP
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
#include <boost/assert.hpp>
|
#include <boost/assert.hpp>
|
||||||
#include <boost/config.hpp>
|
#include <boost/config.hpp>
|
||||||
|
|
||||||
#include <boost/context/execution_context.hpp>
|
|
||||||
#include <boost/context/stack_context.hpp>
|
|
||||||
|
|
||||||
#include <boost/coroutine2/detail/config.hpp>
|
#include <boost/coroutine2/detail/config.hpp>
|
||||||
|
#include <boost/coroutine2/detail/create_control_block.ipp>
|
||||||
#include <boost/coroutine2/fixedsize_stack.hpp>
|
#include <boost/coroutine2/fixedsize_stack.hpp>
|
||||||
#include <boost/coroutine2/segmented_stack.hpp>
|
#include <boost/coroutine2/segmented_stack.hpp>
|
||||||
|
|
||||||
@ -31,51 +28,31 @@ namespace detail {
|
|||||||
// push_coroutine< T >
|
// push_coroutine< T >
|
||||||
|
|
||||||
template< typename T >
|
template< typename T >
|
||||||
push_coroutine< T >::push_coroutine( control_block * cb) :
|
push_coroutine< T >::push_coroutine( control_block * cb) noexcept :
|
||||||
cb_( cb) {
|
cb_{ cb } {
|
||||||
}
|
}
|
||||||
|
|
||||||
template< typename T >
|
template< typename T >
|
||||||
template< typename Fn >
|
template< typename Fn >
|
||||||
push_coroutine< T >::push_coroutine( Fn && fn, bool preserve_fpu) :
|
push_coroutine< T >::push_coroutine( Fn && fn) :
|
||||||
push_coroutine( default_stack(), std::forward< Fn >( fn), preserve_fpu) {
|
push_coroutine{ default_stack(), std::forward< Fn >( fn) } {
|
||||||
}
|
}
|
||||||
|
|
||||||
template< typename T >
|
template< typename T >
|
||||||
template< typename StackAllocator, typename Fn >
|
template< typename StackAllocator, typename Fn >
|
||||||
push_coroutine< T >::push_coroutine( StackAllocator salloc, Fn && fn, bool preserve_fpu) :
|
push_coroutine< T >::push_coroutine( StackAllocator salloc, Fn && fn) :
|
||||||
cb_( nullptr) {
|
cb_{ create_control_block< control_block >( salloc, std::forward< Fn >( fn) ) } {
|
||||||
context::stack_context sctx( salloc.allocate() );
|
|
||||||
// reserve space for control structure
|
|
||||||
#if defined(BOOST_NO_CXX14_CONSTEXPR) || defined(BOOST_NO_CXX11_STD_ALIGN)
|
|
||||||
void * sp = static_cast< char * >( sctx.sp) - sizeof( control_block);
|
|
||||||
std::size_t size = sctx.size - sizeof( control_block);
|
|
||||||
#else
|
|
||||||
constexpr std::size_t func_alignment = 64; // alignof( control_block);
|
|
||||||
constexpr std::size_t func_size = sizeof( control_block);
|
|
||||||
// reserve space on stack
|
|
||||||
void * sp = static_cast< char * >( sctx.sp) - func_size - func_alignment;
|
|
||||||
// align sp pointer
|
|
||||||
std::size_t space = func_size + func_alignment;
|
|
||||||
sp = std::align( func_alignment, func_size, sp, space);
|
|
||||||
BOOST_ASSERT( nullptr != sp);
|
|
||||||
// calculate remaining size
|
|
||||||
std::size_t size = sctx.size - ( static_cast< char * >( sctx.sp) - static_cast< char * >( sp) );
|
|
||||||
#endif
|
|
||||||
// placment new for control structure on coroutine stack
|
|
||||||
cb_= new ( sp) control_block( context::preallocated( sp, size, sctx),
|
|
||||||
salloc, std::forward< Fn >( fn), preserve_fpu);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template< typename T >
|
template< typename T >
|
||||||
push_coroutine< T >::~push_coroutine() {
|
push_coroutine< T >::~push_coroutine() noexcept {
|
||||||
if ( nullptr != cb_) {
|
if ( nullptr != cb_) {
|
||||||
cb_->~control_block();
|
cb_->~control_block();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template< typename T >
|
template< typename T >
|
||||||
push_coroutine< T >::push_coroutine( push_coroutine && other) :
|
push_coroutine< T >::push_coroutine( push_coroutine && other) noexcept :
|
||||||
cb_( other.cb_) {
|
cb_( other.cb_) {
|
||||||
other.cb_ = nullptr;
|
other.cb_ = nullptr;
|
||||||
}
|
}
|
||||||
@ -109,51 +86,31 @@ push_coroutine< T >::operator!() const noexcept {
|
|||||||
// push_coroutine< T & >
|
// push_coroutine< T & >
|
||||||
|
|
||||||
template< typename T >
|
template< typename T >
|
||||||
push_coroutine< T & >::push_coroutine( control_block * cb) :
|
push_coroutine< T & >::push_coroutine( control_block * cb) noexcept :
|
||||||
cb_( cb) {
|
cb_{ cb } {
|
||||||
}
|
}
|
||||||
|
|
||||||
template< typename T >
|
template< typename T >
|
||||||
template< typename Fn >
|
template< typename Fn >
|
||||||
push_coroutine< T & >::push_coroutine( Fn && fn, bool preserve_fpu) :
|
push_coroutine< T & >::push_coroutine( Fn && fn) :
|
||||||
push_coroutine( default_stack(), std::forward< Fn >( fn), preserve_fpu) {
|
push_coroutine{ default_stack(), std::forward< Fn >( fn) } {
|
||||||
}
|
}
|
||||||
|
|
||||||
template< typename T >
|
template< typename T >
|
||||||
template< typename StackAllocator, typename Fn >
|
template< typename StackAllocator, typename Fn >
|
||||||
push_coroutine< T & >::push_coroutine( StackAllocator salloc, Fn && fn, bool preserve_fpu) :
|
push_coroutine< T & >::push_coroutine( StackAllocator salloc, Fn && fn) :
|
||||||
cb_( nullptr) {
|
cb_{ create_control_block< control_block >( salloc, std::forward< Fn >( fn) ) } {
|
||||||
context::stack_context sctx( salloc.allocate() );
|
|
||||||
// reserve space for control structure
|
|
||||||
#if defined(BOOST_NO_CXX14_CONSTEXPR) || defined(BOOST_NO_CXX11_STD_ALIGN)
|
|
||||||
void * sp = static_cast< char * >( sctx.sp) - sizeof( control_block);
|
|
||||||
std::size_t size = sctx.size - sizeof( control_block);
|
|
||||||
#else
|
|
||||||
constexpr std::size_t func_alignment = 64; // alignof( control_block);
|
|
||||||
constexpr std::size_t func_size = sizeof( control_block);
|
|
||||||
// reserve space on stack
|
|
||||||
void * sp = static_cast< char * >( sctx.sp) - func_size - func_alignment;
|
|
||||||
// align sp pointer
|
|
||||||
std::size_t space = func_size + func_alignment;
|
|
||||||
sp = std::align( func_alignment, func_size, sp, space);
|
|
||||||
BOOST_ASSERT( nullptr != sp);
|
|
||||||
// calculate remaining size
|
|
||||||
std::size_t size = sctx.size - ( static_cast< char * >( sctx.sp) - static_cast< char * >( sp) );
|
|
||||||
#endif
|
|
||||||
// placment new for control structure on coroutine stack
|
|
||||||
cb_ = new ( sp) control_block( context::preallocated( sp, size, sctx),
|
|
||||||
salloc, std::forward< Fn >( fn), preserve_fpu);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template< typename T >
|
template< typename T >
|
||||||
push_coroutine< T & >::~push_coroutine() {
|
push_coroutine< T & >::~push_coroutine() noexcept {
|
||||||
if ( nullptr != cb_) {
|
if ( nullptr != cb_) {
|
||||||
cb_->~control_block();
|
cb_->~control_block();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template< typename T >
|
template< typename T >
|
||||||
push_coroutine< T & >::push_coroutine( push_coroutine && other) :
|
push_coroutine< T & >::push_coroutine( push_coroutine && other) noexcept :
|
||||||
cb_( other.cb_) {
|
cb_( other.cb_) {
|
||||||
other.cb_ = nullptr;
|
other.cb_ = nullptr;
|
||||||
}
|
}
|
||||||
@ -180,49 +137,29 @@ push_coroutine< T & >::operator!() const noexcept {
|
|||||||
// push_coroutine< void >
|
// push_coroutine< void >
|
||||||
|
|
||||||
inline
|
inline
|
||||||
push_coroutine< void >::push_coroutine( control_block * cb) :
|
push_coroutine< void >::push_coroutine( control_block * cb) noexcept :
|
||||||
cb_( cb) {
|
cb_{ cb } {
|
||||||
}
|
}
|
||||||
|
|
||||||
template< typename Fn >
|
template< typename Fn >
|
||||||
push_coroutine< void >::push_coroutine( Fn && fn, bool preserve_fpu) :
|
push_coroutine< void >::push_coroutine( Fn && fn) :
|
||||||
push_coroutine( default_stack(), std::forward< Fn >( fn), preserve_fpu) {
|
push_coroutine{ default_stack(), std::forward< Fn >( fn) } {
|
||||||
}
|
}
|
||||||
|
|
||||||
template< typename StackAllocator, typename Fn >
|
template< typename StackAllocator, typename Fn >
|
||||||
push_coroutine< void >::push_coroutine( StackAllocator salloc, Fn && fn, bool preserve_fpu) :
|
push_coroutine< void >::push_coroutine( StackAllocator salloc, Fn && fn) :
|
||||||
cb_( nullptr) {
|
cb_{ create_control_block< control_block >( salloc, std::forward< Fn >( fn) ) } {
|
||||||
context::stack_context sctx( salloc.allocate() );
|
|
||||||
// reserve space for control structure
|
|
||||||
#if defined(BOOST_NO_CXX14_CONSTEXPR) || defined(BOOST_NO_CXX11_STD_ALIGN)
|
|
||||||
void * sp = static_cast< char * >( sctx.sp) - sizeof( control_block);
|
|
||||||
std::size_t size = sctx.size - sizeof( control_block);
|
|
||||||
#else
|
|
||||||
constexpr std::size_t func_alignment = 64; // alignof( control_block);
|
|
||||||
constexpr std::size_t func_size = sizeof( control_block);
|
|
||||||
// reserve space on stack
|
|
||||||
void * sp = static_cast< char * >( sctx.sp) - func_size - func_alignment;
|
|
||||||
// align sp pointer
|
|
||||||
std::size_t space = func_size + func_alignment;
|
|
||||||
sp = std::align( func_alignment, func_size, sp, space);
|
|
||||||
BOOST_ASSERT( nullptr != sp);
|
|
||||||
// calculate remaining size
|
|
||||||
std::size_t size = sctx.size - ( static_cast< char * >( sctx.sp) - static_cast< char * >( sp) );
|
|
||||||
#endif
|
|
||||||
// placment new for control structure on coroutine stack
|
|
||||||
cb_ = new ( sp) control_block( context::preallocated( sp, size, sctx),
|
|
||||||
salloc, std::forward< Fn >( fn), preserve_fpu);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline
|
inline
|
||||||
push_coroutine< void >::~push_coroutine() {
|
push_coroutine< void >::~push_coroutine() noexcept {
|
||||||
if ( nullptr != cb_) {
|
if ( nullptr != cb_) {
|
||||||
cb_->~control_block();
|
cb_->~control_block();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline
|
inline
|
||||||
push_coroutine< void >::push_coroutine( push_coroutine && other) :
|
push_coroutine< void >::push_coroutine( push_coroutine && other) noexcept :
|
||||||
cb_( other.cb_) {
|
cb_( other.cb_) {
|
||||||
other.cb_ = nullptr;
|
other.cb_ = nullptr;
|
||||||
}
|
}
|
||||||
|
@ -23,11 +23,61 @@ namespace coroutines2 {
|
|||||||
namespace detail {
|
namespace detail {
|
||||||
|
|
||||||
enum class state_t : unsigned int {
|
enum class state_t : unsigned int {
|
||||||
|
none = 0,
|
||||||
complete = 1 << 1,
|
complete = 1 << 1,
|
||||||
unwind = 1 << 2,
|
unwind = 1 << 2,
|
||||||
early_exit = 1 << 3
|
early_exit = 1 << 3
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
inline
|
||||||
|
constexpr state_t
|
||||||
|
operator&( state_t l, state_t r) {
|
||||||
|
return static_cast< state_t >(
|
||||||
|
static_cast< unsigned int >( l) & static_cast< unsigned int >( r) );
|
||||||
|
}
|
||||||
|
|
||||||
|
inline
|
||||||
|
constexpr state_t
|
||||||
|
operator|( state_t l, state_t r) {
|
||||||
|
return static_cast< state_t >(
|
||||||
|
static_cast< unsigned int >( l) | static_cast< unsigned int >( r) );
|
||||||
|
}
|
||||||
|
|
||||||
|
inline
|
||||||
|
constexpr state_t
|
||||||
|
operator^( state_t l, state_t r) {
|
||||||
|
return static_cast< state_t >(
|
||||||
|
static_cast< unsigned int >( l) ^ static_cast< unsigned int >( r) );
|
||||||
|
}
|
||||||
|
|
||||||
|
inline
|
||||||
|
constexpr state_t
|
||||||
|
operator~( state_t l) {
|
||||||
|
return static_cast< state_t >( ~static_cast< unsigned int >( l) );
|
||||||
|
}
|
||||||
|
|
||||||
|
inline
|
||||||
|
state_t &
|
||||||
|
operator&=( state_t & l, state_t r) {
|
||||||
|
l = l & r;
|
||||||
|
return l;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline
|
||||||
|
state_t &
|
||||||
|
operator|=( state_t & l, state_t r) {
|
||||||
|
l = l | r;
|
||||||
|
return l;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline
|
||||||
|
state_t &
|
||||||
|
operator^=( state_t & l, state_t r) {
|
||||||
|
l = l ^ r;
|
||||||
|
return l;
|
||||||
|
}
|
||||||
|
|
||||||
}}}
|
}}}
|
||||||
|
|
||||||
#ifdef BOOST_HAS_ABI_HEADERS
|
#ifdef BOOST_HAS_ABI_HEADERS
|
||||||
|
@ -20,7 +20,6 @@
|
|||||||
typedef boost::coroutines2::protected_fixedsize_stack stack_allocator;
|
typedef boost::coroutines2::protected_fixedsize_stack stack_allocator;
|
||||||
typedef boost::coroutines2::coroutine< void > coro_type;
|
typedef boost::coroutines2::coroutine< void > coro_type;
|
||||||
|
|
||||||
bool preserve = false;
|
|
||||||
boost::uint64_t jobs = 1000;
|
boost::uint64_t jobs = 1000;
|
||||||
|
|
||||||
void fn( coro_type::pull_type & c)
|
void fn( coro_type::pull_type & c)
|
||||||
@ -32,7 +31,7 @@ duration_type measure_time( duration_type overhead)
|
|||||||
|
|
||||||
time_point_type start( clock_type::now() );
|
time_point_type start( clock_type::now() );
|
||||||
for ( std::size_t i = 0; i < jobs; ++i) {
|
for ( std::size_t i = 0; i < jobs; ++i) {
|
||||||
coro_type::push_type c( stack_alloc, fn, preserve);
|
coro_type::push_type c( stack_alloc, fn);
|
||||||
}
|
}
|
||||||
duration_type total = clock_type::now() - start;
|
duration_type total = clock_type::now() - start;
|
||||||
total -= overhead_clock(); // overhead of measurement
|
total -= overhead_clock(); // overhead of measurement
|
||||||
@ -48,7 +47,7 @@ cycle_type measure_cycles( cycle_type overhead)
|
|||||||
|
|
||||||
cycle_type start( cycles() );
|
cycle_type start( cycles() );
|
||||||
for ( std::size_t i = 0; i < jobs; ++i) {
|
for ( std::size_t i = 0; i < jobs; ++i) {
|
||||||
coro_type::push_type c( stack_alloc, fn, preserve);
|
coro_type::push_type c( stack_alloc, fn);
|
||||||
}
|
}
|
||||||
cycle_type total = cycles() - start;
|
cycle_type total = cycles() - start;
|
||||||
total -= overhead; // overhead of measurement
|
total -= overhead; // overhead of measurement
|
||||||
@ -67,7 +66,6 @@ int main( int argc, char * argv[])
|
|||||||
desc.add_options()
|
desc.add_options()
|
||||||
("help", "help message")
|
("help", "help message")
|
||||||
("bind,b", boost::program_options::value< bool >( & bind), "bind thread to CPU")
|
("bind,b", boost::program_options::value< bool >( & bind), "bind thread to CPU")
|
||||||
("fpu,f", boost::program_options::value< bool >( & preserve), "preserve FPU registers")
|
|
||||||
("jobs,j", boost::program_options::value< boost::uint64_t >( & jobs), "jobs to run");
|
("jobs,j", boost::program_options::value< boost::uint64_t >( & jobs), "jobs to run");
|
||||||
|
|
||||||
boost::program_options::variables_map vm;
|
boost::program_options::variables_map vm;
|
||||||
|
@ -20,7 +20,6 @@
|
|||||||
typedef boost::coroutines2::fixedsize_stack stack_allocator;
|
typedef boost::coroutines2::fixedsize_stack stack_allocator;
|
||||||
typedef boost::coroutines2::coroutine< void > coro_type;
|
typedef boost::coroutines2::coroutine< void > coro_type;
|
||||||
|
|
||||||
bool preserve = false;
|
|
||||||
boost::uint64_t jobs = 1000;
|
boost::uint64_t jobs = 1000;
|
||||||
|
|
||||||
void fn( coro_type::pull_type & c)
|
void fn( coro_type::pull_type & c)
|
||||||
@ -32,7 +31,7 @@ duration_type measure_time( duration_type overhead)
|
|||||||
|
|
||||||
time_point_type start( clock_type::now() );
|
time_point_type start( clock_type::now() );
|
||||||
for ( std::size_t i = 0; i < jobs; ++i) {
|
for ( std::size_t i = 0; i < jobs; ++i) {
|
||||||
coro_type::push_type c( stack_alloc, fn, preserve);
|
coro_type::push_type c( stack_alloc, fn);
|
||||||
}
|
}
|
||||||
duration_type total = clock_type::now() - start;
|
duration_type total = clock_type::now() - start;
|
||||||
total -= overhead_clock(); // overhead of measurement
|
total -= overhead_clock(); // overhead of measurement
|
||||||
@ -48,7 +47,7 @@ cycle_type measure_cycles( cycle_type overhead)
|
|||||||
|
|
||||||
cycle_type start( cycles() );
|
cycle_type start( cycles() );
|
||||||
for ( std::size_t i = 0; i < jobs; ++i) {
|
for ( std::size_t i = 0; i < jobs; ++i) {
|
||||||
coro_type::push_type c( stack_alloc, fn, preserve);
|
coro_type::push_type c( stack_alloc, fn);
|
||||||
}
|
}
|
||||||
cycle_type total = cycles() - start;
|
cycle_type total = cycles() - start;
|
||||||
total -= overhead; // overhead of measurement
|
total -= overhead; // overhead of measurement
|
||||||
@ -67,7 +66,6 @@ int main( int argc, char * argv[])
|
|||||||
desc.add_options()
|
desc.add_options()
|
||||||
("help", "help message")
|
("help", "help message")
|
||||||
("bind,b", boost::program_options::value< bool >( & bind), "bind thread to CPU")
|
("bind,b", boost::program_options::value< bool >( & bind), "bind thread to CPU")
|
||||||
("fpu,f", boost::program_options::value< bool >( & preserve), "preserve FPU registers")
|
|
||||||
("jobs,j", boost::program_options::value< boost::uint64_t >( & jobs), "jobs to run");
|
("jobs,j", boost::program_options::value< boost::uint64_t >( & jobs), "jobs to run");
|
||||||
|
|
||||||
boost::program_options::variables_map vm;
|
boost::program_options::variables_map vm;
|
||||||
|
@ -18,7 +18,6 @@
|
|||||||
#include "clock.hpp"
|
#include "clock.hpp"
|
||||||
#include "cycle.hpp"
|
#include "cycle.hpp"
|
||||||
|
|
||||||
bool preserve = false;
|
|
||||||
boost::uint64_t jobs = 1000;
|
boost::uint64_t jobs = 1000;
|
||||||
|
|
||||||
struct X
|
struct X
|
||||||
@ -45,7 +44,7 @@ void fn_x( boost::coroutines2::coroutine< X >::push_type & c)
|
|||||||
|
|
||||||
duration_type measure_time_void( duration_type overhead)
|
duration_type measure_time_void( duration_type overhead)
|
||||||
{
|
{
|
||||||
boost::coroutines2::coroutine< void >::pull_type c( fn_void, preserve);
|
boost::coroutines2::coroutine< void >::pull_type c( fn_void);
|
||||||
|
|
||||||
time_point_type start( clock_type::now() );
|
time_point_type start( clock_type::now() );
|
||||||
for ( std::size_t i = 0; i < jobs; ++i) {
|
for ( std::size_t i = 0; i < jobs; ++i) {
|
||||||
@ -61,7 +60,7 @@ duration_type measure_time_void( duration_type overhead)
|
|||||||
|
|
||||||
duration_type measure_time_int( duration_type overhead)
|
duration_type measure_time_int( duration_type overhead)
|
||||||
{
|
{
|
||||||
boost::coroutines2::coroutine< int >::pull_type c( fn_int, preserve);
|
boost::coroutines2::coroutine< int >::pull_type c( fn_int);
|
||||||
|
|
||||||
time_point_type start( clock_type::now() );
|
time_point_type start( clock_type::now() );
|
||||||
for ( std::size_t i = 0; i < jobs; ++i) {
|
for ( std::size_t i = 0; i < jobs; ++i) {
|
||||||
@ -77,7 +76,7 @@ duration_type measure_time_int( duration_type overhead)
|
|||||||
|
|
||||||
duration_type measure_time_x( duration_type overhead)
|
duration_type measure_time_x( duration_type overhead)
|
||||||
{
|
{
|
||||||
boost::coroutines2::coroutine< X >::pull_type c( fn_x, preserve);
|
boost::coroutines2::coroutine< X >::pull_type c( fn_x);
|
||||||
|
|
||||||
time_point_type start( clock_type::now() );
|
time_point_type start( clock_type::now() );
|
||||||
for ( std::size_t i = 0; i < jobs; ++i) {
|
for ( std::size_t i = 0; i < jobs; ++i) {
|
||||||
@ -94,7 +93,7 @@ duration_type measure_time_x( duration_type overhead)
|
|||||||
# ifdef BOOST_CONTEXT_CYCLE
|
# ifdef BOOST_CONTEXT_CYCLE
|
||||||
cycle_type measure_cycles_void( cycle_type overhead)
|
cycle_type measure_cycles_void( cycle_type overhead)
|
||||||
{
|
{
|
||||||
boost::coroutines2::coroutine< void >::pull_type c( fn_void, preserve);
|
boost::coroutines2::coroutine< void >::pull_type c( fn_void);
|
||||||
|
|
||||||
cycle_type start( cycles() );
|
cycle_type start( cycles() );
|
||||||
for ( std::size_t i = 0; i < jobs; ++i) {
|
for ( std::size_t i = 0; i < jobs; ++i) {
|
||||||
@ -110,7 +109,7 @@ cycle_type measure_cycles_void( cycle_type overhead)
|
|||||||
|
|
||||||
cycle_type measure_cycles_int( cycle_type overhead)
|
cycle_type measure_cycles_int( cycle_type overhead)
|
||||||
{
|
{
|
||||||
boost::coroutines2::coroutine< int >::pull_type c( fn_int, preserve);
|
boost::coroutines2::coroutine< int >::pull_type c( fn_int);
|
||||||
|
|
||||||
cycle_type start( cycles() );
|
cycle_type start( cycles() );
|
||||||
for ( std::size_t i = 0; i < jobs; ++i) {
|
for ( std::size_t i = 0; i < jobs; ++i) {
|
||||||
@ -126,7 +125,7 @@ cycle_type measure_cycles_int( cycle_type overhead)
|
|||||||
|
|
||||||
cycle_type measure_cycles_x( cycle_type overhead)
|
cycle_type measure_cycles_x( cycle_type overhead)
|
||||||
{
|
{
|
||||||
boost::coroutines2::coroutine< X >::pull_type c( fn_x, preserve);
|
boost::coroutines2::coroutine< X >::pull_type c( fn_x);
|
||||||
|
|
||||||
cycle_type start( cycles() );
|
cycle_type start( cycles() );
|
||||||
for ( std::size_t i = 0; i < jobs; ++i) {
|
for ( std::size_t i = 0; i < jobs; ++i) {
|
||||||
@ -150,7 +149,6 @@ int main( int argc, char * argv[])
|
|||||||
desc.add_options()
|
desc.add_options()
|
||||||
("help", "help message")
|
("help", "help message")
|
||||||
("bind,b", boost::program_options::value< bool >( & bind), "bind thread to CPU")
|
("bind,b", boost::program_options::value< bool >( & bind), "bind thread to CPU")
|
||||||
("fpu,f", boost::program_options::value< bool >( & preserve), "preserve FPU registers")
|
|
||||||
("jobs,j", boost::program_options::value< boost::uint64_t >( & jobs), "jobs to run");
|
("jobs,j", boost::program_options::value< boost::uint64_t >( & jobs), "jobs to run");
|
||||||
|
|
||||||
boost::program_options::variables_map vm;
|
boost::program_options::variables_map vm;
|
||||||
|
@ -20,7 +20,6 @@
|
|||||||
typedef boost::coroutines2::segmented_stack stack_allocator;
|
typedef boost::coroutines2::segmented_stack stack_allocator;
|
||||||
typedef boost::coroutines2::coroutine< void > coro_type;
|
typedef boost::coroutines2::coroutine< void > coro_type;
|
||||||
|
|
||||||
bool preserve = false;
|
|
||||||
boost::uint64_t jobs = 1000;
|
boost::uint64_t jobs = 1000;
|
||||||
|
|
||||||
void fn( coro_type::push_type & c)
|
void fn( coro_type::push_type & c)
|
||||||
@ -32,7 +31,7 @@ duration_type measure_time( duration_type overhead)
|
|||||||
|
|
||||||
time_point_type start( clock_type::now() );
|
time_point_type start( clock_type::now() );
|
||||||
for ( std::size_t i = 0; i < jobs; ++i) {
|
for ( std::size_t i = 0; i < jobs; ++i) {
|
||||||
coro_type::pull_type c( stack_alloc, fn, preserve);
|
coro_type::pull_type c( stack_alloc, fn);
|
||||||
}
|
}
|
||||||
duration_type total = clock_type::now() - start;
|
duration_type total = clock_type::now() - start;
|
||||||
total -= overhead_clock(); // overhead of measurement
|
total -= overhead_clock(); // overhead of measurement
|
||||||
@ -48,7 +47,7 @@ cycle_type measure_cycles( cycle_type overhead)
|
|||||||
|
|
||||||
cycle_type start( cycles() );
|
cycle_type start( cycles() );
|
||||||
for ( std::size_t i = 0; i < jobs; ++i) {
|
for ( std::size_t i = 0; i < jobs; ++i) {
|
||||||
coro_type::pull_type c( stack_alloc, fn, preserve);
|
coro_type::pull_type c( stack_alloc, fn);
|
||||||
}
|
}
|
||||||
cycle_type total = cycles() - start;
|
cycle_type total = cycles() - start;
|
||||||
total -= overhead; // overhead of measurement
|
total -= overhead; // overhead of measurement
|
||||||
@ -62,12 +61,11 @@ int main( int argc, char * argv[])
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
bool preserve = false, unwind = true, bind = false;
|
bool bind = false;
|
||||||
boost::program_options::options_description desc("allowed options");
|
boost::program_options::options_description desc("allowed options");
|
||||||
desc.add_options()
|
desc.add_options()
|
||||||
("help", "help message")
|
("help", "help message")
|
||||||
("bind,b", boost::program_options::value< bool >( & bind), "bind thread to CPU")
|
("bind,b", boost::program_options::value< bool >( & bind), "bind thread to CPU")
|
||||||
("fpu,f", boost::program_options::value< bool >( & preserve), "preserve FPU registers")
|
|
||||||
("jobs,j", boost::program_options::value< boost::uint64_t >( & jobs), "jobs to run");
|
("jobs,j", boost::program_options::value< boost::uint64_t >( & jobs), "jobs to run");
|
||||||
|
|
||||||
boost::program_options::variables_map vm;
|
boost::program_options::variables_map vm;
|
||||||
|
@ -18,7 +18,6 @@
|
|||||||
#include "../clock.hpp"
|
#include "../clock.hpp"
|
||||||
#include "../cycle.hpp"
|
#include "../cycle.hpp"
|
||||||
|
|
||||||
bool preserve = false;
|
|
||||||
boost::uint64_t jobs = 1000;
|
boost::uint64_t jobs = 1000;
|
||||||
|
|
||||||
struct X
|
struct X
|
||||||
@ -46,7 +45,7 @@ void fn_x( boost::coroutines2::coroutine< X >::push_type & c)
|
|||||||
duration_type measure_time_void( duration_type overhead)
|
duration_type measure_time_void( duration_type overhead)
|
||||||
{
|
{
|
||||||
boost::coroutines2::segmented_stack stack_alloc;
|
boost::coroutines2::segmented_stack stack_alloc;
|
||||||
boost::coroutines2::coroutine< void >::pull_type c( stack_alloc, fn_void, preserve);
|
boost::coroutines2::coroutine< void >::pull_type c( stack_alloc, fn_void);
|
||||||
|
|
||||||
time_point_type start( clock_type::now() );
|
time_point_type start( clock_type::now() );
|
||||||
for ( std::size_t i = 0; i < jobs; ++i) {
|
for ( std::size_t i = 0; i < jobs; ++i) {
|
||||||
@ -63,7 +62,7 @@ duration_type measure_time_void( duration_type overhead)
|
|||||||
duration_type measure_time_int( duration_type overhead)
|
duration_type measure_time_int( duration_type overhead)
|
||||||
{
|
{
|
||||||
boost::coroutines2::segmented_stack stack_alloc;
|
boost::coroutines2::segmented_stack stack_alloc;
|
||||||
boost::coroutines2::coroutine< int >::pull_type c( stack_alloc, fn_int, preserve);
|
boost::coroutines2::coroutine< int >::pull_type c( stack_alloc, fn_int);
|
||||||
|
|
||||||
time_point_type start( clock_type::now() );
|
time_point_type start( clock_type::now() );
|
||||||
for ( std::size_t i = 0; i < jobs; ++i) {
|
for ( std::size_t i = 0; i < jobs; ++i) {
|
||||||
@ -80,7 +79,7 @@ duration_type measure_time_int( duration_type overhead)
|
|||||||
duration_type measure_time_x( duration_type overhead)
|
duration_type measure_time_x( duration_type overhead)
|
||||||
{
|
{
|
||||||
boost::coroutines2::segmented_stack stack_alloc;
|
boost::coroutines2::segmented_stack stack_alloc;
|
||||||
boost::coroutines2::coroutine< X >::pull_type c( stack_alloc, fn_x, preserve);
|
boost::coroutines2::coroutine< X >::pull_type c( stack_alloc, fn_x);
|
||||||
|
|
||||||
time_point_type start( clock_type::now() );
|
time_point_type start( clock_type::now() );
|
||||||
for ( std::size_t i = 0; i < jobs; ++i) {
|
for ( std::size_t i = 0; i < jobs; ++i) {
|
||||||
@ -98,7 +97,7 @@ duration_type measure_time_x( duration_type overhead)
|
|||||||
cycle_type measure_cycles_void( cycle_type overhead)
|
cycle_type measure_cycles_void( cycle_type overhead)
|
||||||
{
|
{
|
||||||
boost::coroutines2::segmented_stack stack_alloc;
|
boost::coroutines2::segmented_stack stack_alloc;
|
||||||
boost::coroutines2::coroutine< void >::pull_type c( stack_alloc, fn_void, preserve);
|
boost::coroutines2::coroutine< void >::pull_type c( stack_alloc, fn_void);
|
||||||
|
|
||||||
cycle_type start( cycles() );
|
cycle_type start( cycles() );
|
||||||
for ( std::size_t i = 0; i < jobs; ++i) {
|
for ( std::size_t i = 0; i < jobs; ++i) {
|
||||||
@ -115,7 +114,7 @@ cycle_type measure_cycles_void( cycle_type overhead)
|
|||||||
cycle_type measure_cycles_int( cycle_type overhead)
|
cycle_type measure_cycles_int( cycle_type overhead)
|
||||||
{
|
{
|
||||||
boost::coroutines2::segmented_stack stack_alloc;
|
boost::coroutines2::segmented_stack stack_alloc;
|
||||||
boost::coroutines2::coroutine< int >::pull_type c( stack_alloc, fn_int, preserve);
|
boost::coroutines2::coroutine< int >::pull_type c( stack_alloc, fn_int);
|
||||||
|
|
||||||
cycle_type start( cycles() );
|
cycle_type start( cycles() );
|
||||||
for ( std::size_t i = 0; i < jobs; ++i) {
|
for ( std::size_t i = 0; i < jobs; ++i) {
|
||||||
@ -132,7 +131,7 @@ cycle_type measure_cycles_int( cycle_type overhead)
|
|||||||
cycle_type measure_cycles_x( cycle_type overhead)
|
cycle_type measure_cycles_x( cycle_type overhead)
|
||||||
{
|
{
|
||||||
boost::coroutines2::segmented_stack stack_alloc;
|
boost::coroutines2::segmented_stack stack_alloc;
|
||||||
boost::coroutines2::coroutine< X >::pull_type c( stack_alloc, fn_x, preserve);
|
boost::coroutines2::coroutine< X >::pull_type c( stack_alloc, fn_x);
|
||||||
|
|
||||||
cycle_type start( cycles() );
|
cycle_type start( cycles() );
|
||||||
for ( std::size_t i = 0; i < jobs; ++i) {
|
for ( std::size_t i = 0; i < jobs; ++i) {
|
||||||
@ -156,7 +155,6 @@ int main( int argc, char * argv[])
|
|||||||
desc.add_options()
|
desc.add_options()
|
||||||
("help", "help message")
|
("help", "help message")
|
||||||
("bind,b", boost::program_options::value< bool >( & bind), "bind thread to CPU")
|
("bind,b", boost::program_options::value< bool >( & bind), "bind thread to CPU")
|
||||||
("fpu,f", boost::program_options::value< bool >( & preserve), "preserve FPU registers")
|
|
||||||
("jobs,j", boost::program_options::value< boost::uint64_t >( & jobs), "jobs to run");
|
("jobs,j", boost::program_options::value< boost::uint64_t >( & jobs), "jobs to run");
|
||||||
|
|
||||||
boost::program_options::variables_map vm;
|
boost::program_options::variables_map vm;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user