mirror of
https://github.com/boostorg/coroutine2.git
synced 2025-05-09 23:24:01 +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>
|
||||
|
||||
int main()
|
||||
{
|
||||
int main() {
|
||||
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;
|
||||
sink( first);
|
||||
sink( second);
|
||||
for ( int i = 0; i < 8; ++i)
|
||||
{
|
||||
for ( int i = 0; i < 8; ++i) {
|
||||
int third = first + second;
|
||||
first = second;
|
||||
second = third;
|
||||
sink( third);
|
||||
}
|
||||
});
|
||||
|
||||
for ( auto i : source)
|
||||
for ( auto i : source) {
|
||||
std::cout << i << " ";
|
||||
|
||||
}
|
||||
std::cout << "\nDone" << std::endl;
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
@ -21,13 +21,11 @@ struct FinalEOL{
|
||||
int main(int argc,char* argv[]){
|
||||
using std::begin;
|
||||
using std::end;
|
||||
|
||||
std::vector<std::string> words{
|
||||
"peas", "porridge", "hot", "peas",
|
||||
"porridge", "cold", "peas", "porridge",
|
||||
"in", "the", "pot", "nine",
|
||||
"days", "old" };
|
||||
|
||||
int num=5,width=15;
|
||||
boost::coroutines2::coroutine<std::string>::push_type writer(
|
||||
[&](boost::coroutines2::coroutine<std::string>::pull_type& in){
|
||||
@ -46,10 +44,7 @@ int main(int argc,char* argv[]){
|
||||
std::cout << std::endl;
|
||||
}
|
||||
});
|
||||
|
||||
std::copy(begin(words),end(words),begin(writer));
|
||||
|
||||
std::cout << "\nDone" << std::endl;
|
||||
|
||||
return 0;
|
||||
std::cout << "\nDone";
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
@ -108,14 +108,11 @@ int main() {
|
||||
});
|
||||
p.run();
|
||||
});
|
||||
|
||||
// user-code pulls parsed data from parser
|
||||
for(char c:seq){
|
||||
printf("Parsed: %c\n",c);
|
||||
}
|
||||
|
||||
std::cout << "\nDone" << std::endl;
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
} catch ( std::exception const& ex) {
|
||||
std::cerr << "exception: " << ex.what() << std::endl;
|
||||
|
@ -13,8 +13,7 @@
|
||||
|
||||
#include <boost/coroutine2/all.hpp>
|
||||
|
||||
struct node
|
||||
{
|
||||
struct node {
|
||||
typedef std::shared_ptr< node > ptr_t;
|
||||
|
||||
// Each tree node has an optional left subtree, an optional right subtree
|
||||
@ -25,26 +24,24 @@ struct node
|
||||
|
||||
// construct leaf
|
||||
node(const std::string& v):
|
||||
left(),right(),value(v)
|
||||
{}
|
||||
left(),right(),value(v) {
|
||||
}
|
||||
|
||||
// construct nonleaf
|
||||
node(ptr_t l, const std::string& v, ptr_t r):
|
||||
left(l),right(r),value(v)
|
||||
{}
|
||||
left(l),right(r),value(v) {
|
||||
}
|
||||
|
||||
static ptr_t create(const std::string& v)
|
||||
{
|
||||
static ptr_t create(const std::string& v) {
|
||||
return ptr_t(new node(v));
|
||||
}
|
||||
|
||||
static ptr_t create(ptr_t l, const std::string& v, ptr_t r)
|
||||
{
|
||||
static ptr_t create(ptr_t l, const std::string& v, ptr_t r) {
|
||||
return ptr_t(new node(l, v, r));
|
||||
}
|
||||
};
|
||||
|
||||
node::ptr_t create_left_tree_from(const std::string& root)
|
||||
{
|
||||
node::ptr_t create_left_tree_from(const std::string& root) {
|
||||
/* --------
|
||||
root
|
||||
/ \
|
||||
@ -62,8 +59,7 @@ node::ptr_t create_left_tree_from(const std::string& root)
|
||||
node::create("e"));
|
||||
}
|
||||
|
||||
node::ptr_t create_right_tree_from(const std::string& root)
|
||||
{
|
||||
node::ptr_t create_right_tree_from(const std::string& root) {
|
||||
/* --------
|
||||
root
|
||||
/ \
|
||||
@ -82,8 +78,7 @@ node::ptr_t create_right_tree_from(const std::string& root)
|
||||
}
|
||||
|
||||
// recursively walk the tree, delivering values in order
|
||||
void traverse(node::ptr_t n, boost::coroutines2::coroutine<std::string>::push_type& out)
|
||||
{
|
||||
void traverse(node::ptr_t n, boost::coroutines2::coroutine<std::string>::push_type& out) {
|
||||
if (n->left)
|
||||
traverse(n->left,out);
|
||||
out(n->value);
|
||||
@ -91,8 +86,7 @@ void traverse(node::ptr_t n, boost::coroutines2::coroutine<std::string>::push_ty
|
||||
traverse(n->right,out);
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
int main() {
|
||||
{
|
||||
node::ptr_t left_d(create_left_tree_from("d"));
|
||||
boost::coroutines2::coroutine<std::string>::pull_type left_d_reader(
|
||||
@ -127,7 +121,6 @@ int main()
|
||||
std::ostream_iterator<std::string>(std::cout, " "));
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
{
|
||||
node::ptr_t left_d(create_left_tree_from("d"));
|
||||
boost::coroutines2::coroutine<std::string>::pull_type left_d_reader(
|
||||
@ -148,7 +141,6 @@ int main()
|
||||
begin(right_b_reader))
|
||||
<< std::endl;
|
||||
}
|
||||
|
||||
{
|
||||
node::ptr_t left_d(create_left_tree_from("d"));
|
||||
boost::coroutines2::coroutine<std::string>::pull_type left_d_reader(
|
||||
@ -169,8 +161,6 @@ int main()
|
||||
begin(right_x_reader))
|
||||
<< std::endl;
|
||||
}
|
||||
|
||||
std::cout << "Done" << std::endl;
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
@ -54,7 +54,7 @@ int main() {
|
||||
|
||||
sink();
|
||||
|
||||
std::cout << "main: done" << std::endl;
|
||||
std::cout << "main: Done" << std::endl;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -9,15 +9,12 @@
|
||||
|
||||
#include <boost/coroutine2/all.hpp>
|
||||
|
||||
int main()
|
||||
{
|
||||
int main() {
|
||||
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;
|
||||
});
|
||||
sink();
|
||||
|
||||
std::cout << "Done" << std::endl;
|
||||
|
||||
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 {};
|
||||
|
||||
inline
|
||||
void * unwind_coroutine( void * data) {
|
||||
throw forced_unwind{};
|
||||
return data;
|
||||
}
|
||||
|
||||
}}}
|
||||
|
||||
#ifdef BOOST_HAS_ABI_HEADERS
|
||||
|
@ -13,6 +13,8 @@
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/context/execution_context.hpp>
|
||||
|
||||
#include <boost/coroutine2/detail/state.hpp>
|
||||
|
||||
#ifdef BOOST_HAS_ABI_HEADERS
|
||||
# include BOOST_ABI_PREFIX
|
||||
#endif
|
||||
@ -25,18 +27,17 @@ template< typename T >
|
||||
struct pull_coroutine< T >::control_block {
|
||||
typename push_coroutine< T >::control_block * other;
|
||||
boost::context::execution_context ctx;
|
||||
bool preserve_fpu;
|
||||
int state;
|
||||
state_t state;
|
||||
std::exception_ptr except;
|
||||
bool bvalid;
|
||||
typename std::aligned_storage< sizeof( T), alignof( T) >::type storage[1];
|
||||
|
||||
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 & operator=( control_block &) = delete;
|
||||
@ -45,7 +46,7 @@ struct pull_coroutine< T >::control_block {
|
||||
|
||||
void set( T *);
|
||||
|
||||
T & get();
|
||||
T & get() noexcept;
|
||||
|
||||
bool valid() const noexcept;
|
||||
};
|
||||
@ -54,24 +55,23 @@ template< typename T >
|
||||
struct pull_coroutine< T & >::control_block {
|
||||
typename push_coroutine< T & >::control_block * other;
|
||||
boost::context::execution_context ctx;
|
||||
bool preserve_fpu;
|
||||
int state;
|
||||
state_t state;
|
||||
std::exception_ptr except;
|
||||
T * t;
|
||||
|
||||
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 & operator=( control_block &) = delete;
|
||||
|
||||
void resume();
|
||||
|
||||
T & get();
|
||||
T & get() noexcept;
|
||||
|
||||
bool valid() const noexcept;
|
||||
};
|
||||
@ -79,16 +79,15 @@ struct pull_coroutine< T & >::control_block {
|
||||
struct pull_coroutine< void >::control_block {
|
||||
push_coroutine< void >::control_block * other;
|
||||
boost::context::execution_context ctx;
|
||||
bool preserve_fpu;
|
||||
int state;
|
||||
state_t state;
|
||||
std::exception_ptr except;
|
||||
|
||||
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 & operator=( control_block &) = delete;
|
||||
|
@ -32,13 +32,13 @@ namespace detail {
|
||||
template< typename T >
|
||||
template< typename StackAllocator, typename Fn >
|
||||
pull_coroutine< T >::control_block::control_block( context::preallocated palloc, StackAllocator salloc,
|
||||
Fn && fn_, bool preserve_fpu_) :
|
||||
other( nullptr),
|
||||
ctx( std::allocator_arg, palloc, salloc,
|
||||
[=,fn=std::forward< Fn >( fn_),ctx=boost::context::execution_context::current()] (void *) mutable -> void {
|
||||
Fn && fn_) :
|
||||
other{ nullptr },
|
||||
ctx{ std::allocator_arg, palloc, salloc,
|
||||
[this,fn=std::forward< Fn >( fn_),ctx=boost::context::execution_context::current()] (void *) mutable noexcept {
|
||||
// create synthesized push_coroutine< T >
|
||||
typename push_coroutine< T >::control_block synthesized_cb( this, ctx);
|
||||
push_coroutine< T > synthesized( & synthesized_cb);
|
||||
typename push_coroutine< T >::control_block synthesized_cb{ this, ctx };
|
||||
push_coroutine< T > synthesized{ & synthesized_cb };
|
||||
other = & synthesized_cb;
|
||||
try {
|
||||
// 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();
|
||||
}
|
||||
// set termination flags
|
||||
state |= static_cast< int >( state_t::complete);
|
||||
state |= state_t::complete;
|
||||
// jump back to ctx
|
||||
other->ctx( nullptr, preserve_fpu);
|
||||
other->ctx();
|
||||
BOOST_ASSERT_MSG( false, "pull_coroutine is complete");
|
||||
}),
|
||||
preserve_fpu( preserve_fpu_),
|
||||
state( static_cast< int >( state_t::unwind) ),
|
||||
except(),
|
||||
bvalid( false),
|
||||
storage() {
|
||||
}},
|
||||
state{ state_t::unwind },
|
||||
except{},
|
||||
bvalid{ false },
|
||||
storage{} {
|
||||
// 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 >
|
||||
pull_coroutine< T >::control_block::control_block( typename push_coroutine< T >::control_block * cb,
|
||||
boost::context::execution_context const& ctx_) :
|
||||
other( cb),
|
||||
ctx( ctx_),
|
||||
preserve_fpu( other->preserve_fpu),
|
||||
state( 0),
|
||||
except(),
|
||||
bvalid( false),
|
||||
storage() {
|
||||
boost::context::execution_context const& ctx_) noexcept :
|
||||
other{ cb },
|
||||
ctx{ ctx_ },
|
||||
state{ state_t::none },
|
||||
except{},
|
||||
bvalid{ false },
|
||||
storage{} {
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
pull_coroutine< T >::control_block::~control_block() {
|
||||
if ( 0 == ( state & static_cast< int >( state_t::complete ) ) &&
|
||||
0 != ( state & static_cast< int >( state_t::unwind) ) ) {
|
||||
pull_coroutine< T >::control_block::~control_block() noexcept {
|
||||
if ( state_t::none == ( state & state_t::complete) &&
|
||||
state_t::none != ( state & state_t::unwind) ) {
|
||||
// set early-exit flag
|
||||
state |= static_cast< int >( state_t::early_exit);
|
||||
ctx( nullptr, preserve_fpu);
|
||||
state |= state_t::early_exit;
|
||||
ctx();
|
||||
}
|
||||
// destroy data if it set
|
||||
if ( bvalid) {
|
||||
@ -94,12 +92,12 @@ template< typename T >
|
||||
void
|
||||
pull_coroutine< T >::control_block::resume() {
|
||||
other->ctx = boost::context::execution_context::current();
|
||||
set( reinterpret_cast< T * >( ctx( nullptr, preserve_fpu) ) );
|
||||
set( static_cast< T * >( ctx() ) );
|
||||
if ( except) {
|
||||
std::rethrow_exception( except);
|
||||
}
|
||||
// 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();
|
||||
}
|
||||
}
|
||||
@ -121,14 +119,14 @@ pull_coroutine< T >::control_block::set( T * t) {
|
||||
|
||||
template< typename T >
|
||||
T &
|
||||
pull_coroutine< T >::control_block::get() {
|
||||
pull_coroutine< T >::control_block::get() noexcept {
|
||||
return * reinterpret_cast< T * >( storage);
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
bool
|
||||
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 StackAllocator, typename Fn >
|
||||
pull_coroutine< T & >::control_block::control_block( context::preallocated palloc, StackAllocator salloc,
|
||||
Fn && fn_, bool preserve_fpu_) :
|
||||
other( nullptr),
|
||||
ctx( std::allocator_arg, palloc, salloc,
|
||||
[=,fn=std::forward< Fn >( fn_),ctx=boost::context::execution_context::current()] (void *) mutable -> void {
|
||||
Fn && fn_) :
|
||||
other{ nullptr },
|
||||
ctx{ std::allocator_arg, palloc, salloc,
|
||||
[this,fn=std::forward< Fn >( fn_),ctx=boost::context::execution_context::current()] (void *) mutable noexcept {
|
||||
// create synthesized push_coroutine< T >
|
||||
typename push_coroutine< T & >::control_block synthesized_cb( this, ctx);
|
||||
push_coroutine< T & > synthesized( & synthesized_cb);
|
||||
typename push_coroutine< T & >::control_block synthesized_cb{ this, ctx };
|
||||
push_coroutine< T & > synthesized{ & synthesized_cb };
|
||||
other = & synthesized_cb;
|
||||
try {
|
||||
// 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();
|
||||
}
|
||||
// set termination flags
|
||||
state |= static_cast< int >( state_t::complete);
|
||||
state |= state_t::complete;
|
||||
// jump back to ctx
|
||||
other->ctx( nullptr, preserve_fpu);
|
||||
other->ctx();
|
||||
BOOST_ASSERT_MSG( false, "pull_coroutine is complete");
|
||||
}),
|
||||
preserve_fpu( preserve_fpu_),
|
||||
state( static_cast< int >( state_t::unwind) ),
|
||||
except(),
|
||||
}},
|
||||
state{ state_t::unwind },
|
||||
except{},
|
||||
t( nullptr) {
|
||||
// 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 >
|
||||
pull_coroutine< T & >::control_block::control_block( typename push_coroutine< T & >::control_block * cb,
|
||||
boost::context::execution_context const& ctx_) :
|
||||
other( cb),
|
||||
ctx( ctx_),
|
||||
preserve_fpu( other->preserve_fpu),
|
||||
state( 0),
|
||||
except(),
|
||||
boost::context::execution_context const& ctx_) noexcept :
|
||||
other{ cb },
|
||||
ctx{ ctx_ },
|
||||
state{ state_t::none },
|
||||
except{},
|
||||
t( nullptr) {
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
pull_coroutine< T & >::control_block::~control_block() {
|
||||
if ( 0 == ( state & static_cast< int >( state_t::complete ) ) &&
|
||||
0 != ( state & static_cast< int >( state_t::unwind) ) ) {
|
||||
pull_coroutine< T & >::control_block::~control_block() noexcept {
|
||||
if ( state_t::none == ( state & state_t::complete) &&
|
||||
state_t::none != ( state & state_t::unwind) ) {
|
||||
// set early-exit flag
|
||||
state |= static_cast< int >( state_t::early_exit);
|
||||
ctx( nullptr, preserve_fpu);
|
||||
state |= state_t::early_exit;
|
||||
ctx();
|
||||
}
|
||||
}
|
||||
|
||||
@ -193,26 +189,26 @@ template< typename T >
|
||||
void
|
||||
pull_coroutine< T & >::control_block::resume() {
|
||||
other->ctx = boost::context::execution_context::current();
|
||||
t = reinterpret_cast< T * >( ctx( nullptr, preserve_fpu) );
|
||||
t = static_cast< T * >( ctx() );
|
||||
if ( except) {
|
||||
std::rethrow_exception( except);
|
||||
}
|
||||
// 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();
|
||||
}
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
T &
|
||||
pull_coroutine< T & >::control_block::get() {
|
||||
return * reinterpret_cast< T * >( t);
|
||||
pull_coroutine< T & >::control_block::get() noexcept {
|
||||
return * static_cast< T * >( t);
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
bool
|
||||
pull_coroutine< T & >::control_block::valid() const noexcept {
|
||||
return nullptr != other && 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 >
|
||||
pull_coroutine< void >::control_block::control_block( context::preallocated palloc, StackAllocator salloc,
|
||||
Fn && fn_, bool preserve_fpu_) :
|
||||
other( nullptr),
|
||||
ctx( std::allocator_arg, palloc, salloc,
|
||||
[=,fn=std::forward< Fn >( fn_),ctx=boost::context::execution_context::current()] (void *) mutable -> void {
|
||||
Fn && fn_) :
|
||||
other{ nullptr },
|
||||
ctx{ std::allocator_arg, palloc, salloc,
|
||||
[this,fn=std::forward< Fn >( fn_),ctx=boost::context::execution_context::current()] (void *) mutable noexcept {
|
||||
// create synthesized push_coroutine< T >
|
||||
typename push_coroutine< void >::control_block synthesized_cb( this, ctx);
|
||||
push_coroutine< void > synthesized( & synthesized_cb);
|
||||
typename push_coroutine< void >::control_block synthesized_cb{ this, ctx };
|
||||
push_coroutine< void > synthesized{ & synthesized_cb };
|
||||
other = & synthesized_cb;
|
||||
try {
|
||||
// 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();
|
||||
}
|
||||
// set termination flags
|
||||
state |= static_cast< int >( state_t::complete);
|
||||
state |= state_t::complete;
|
||||
// jump back to ctx
|
||||
other->ctx( nullptr, preserve_fpu);
|
||||
other->ctx();
|
||||
BOOST_ASSERT_MSG( false, "pull_coroutine is complete");
|
||||
}),
|
||||
preserve_fpu( preserve_fpu_),
|
||||
state( static_cast< int >( state_t::unwind) ),
|
||||
except() {
|
||||
}},
|
||||
state{ state_t::unwind },
|
||||
except{} {
|
||||
// enter coroutine-fn in order to have first value available after ctor returns
|
||||
ctx( nullptr, preserve_fpu);
|
||||
ctx();
|
||||
}
|
||||
|
||||
inline
|
||||
pull_coroutine< void >::control_block::control_block( push_coroutine< void >::control_block * cb,
|
||||
boost::context::execution_context const& ctx_) :
|
||||
other( cb),
|
||||
ctx( ctx_),
|
||||
preserve_fpu( other->preserve_fpu),
|
||||
state( 0),
|
||||
except() {
|
||||
boost::context::execution_context const& ctx_) noexcept :
|
||||
other{ cb },
|
||||
ctx{ ctx_ },
|
||||
state{ state_t::none },
|
||||
except{} {
|
||||
}
|
||||
|
||||
inline
|
||||
pull_coroutine< void >::control_block::~control_block() {
|
||||
if ( 0 == ( state & static_cast< int >( state_t::complete ) ) &&
|
||||
0 != ( state & static_cast< int >( state_t::unwind) ) ) {
|
||||
pull_coroutine< void >::control_block::~control_block() noexcept {
|
||||
if ( state_t::none == ( state & state_t::complete) &&
|
||||
state_t::none != ( state & state_t::unwind) ) {
|
||||
// set early-exit flag
|
||||
state |= static_cast< int >( state_t::early_exit);
|
||||
ctx( nullptr, preserve_fpu);
|
||||
state |= state_t::early_exit;
|
||||
ctx();
|
||||
}
|
||||
}
|
||||
|
||||
@ -274,12 +268,12 @@ inline
|
||||
void
|
||||
pull_coroutine< void >::control_block::resume() {
|
||||
other->ctx = boost::context::execution_context::current();
|
||||
ctx( nullptr, preserve_fpu);
|
||||
ctx();
|
||||
if ( except) {
|
||||
std::rethrow_exception( except);
|
||||
}
|
||||
// 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();
|
||||
}
|
||||
}
|
||||
@ -287,7 +281,7 @@ pull_coroutine< void >::control_block::resume() {
|
||||
inline
|
||||
bool
|
||||
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/config.hpp>
|
||||
#include <boost/context/execution_context.hpp>
|
||||
|
||||
#include <boost/coroutine2/detail/config.hpp>
|
||||
|
||||
@ -34,25 +33,25 @@ private:
|
||||
|
||||
control_block * cb_;
|
||||
|
||||
explicit pull_coroutine( control_block *);
|
||||
explicit pull_coroutine( control_block *) noexcept;
|
||||
|
||||
bool has_result_() const;
|
||||
bool has_result_() const noexcept;
|
||||
|
||||
public:
|
||||
template< typename Fn >
|
||||
explicit pull_coroutine( Fn &&, bool = false);
|
||||
explicit pull_coroutine( 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 & 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) {
|
||||
cb_ = other.cb_;
|
||||
other.cb_ = nullptr;
|
||||
@ -66,7 +65,7 @@ public:
|
||||
|
||||
bool operator!() const noexcept;
|
||||
|
||||
T get();
|
||||
T get() noexcept;
|
||||
|
||||
class iterator : public std::iterator< std::input_iterator_tag, typename std::remove_reference< T >::type > {
|
||||
private:
|
||||
@ -91,30 +90,31 @@ public:
|
||||
typedef typename iterator::pointer pointer_t;
|
||||
typedef typename iterator::reference reference_t;
|
||||
|
||||
iterator() :
|
||||
c_( nullptr) {
|
||||
iterator() noexcept :
|
||||
c_{ nullptr } {
|
||||
}
|
||||
|
||||
explicit iterator( pull_coroutine< T > * c) :
|
||||
c_( c) {
|
||||
c_{ c } {
|
||||
fetch_();
|
||||
}
|
||||
|
||||
iterator( iterator const& other) :
|
||||
c_( other.c_) {
|
||||
iterator( iterator const& other) noexcept :
|
||||
c_{ other.c_ } {
|
||||
}
|
||||
|
||||
iterator & operator=( iterator const& other) {
|
||||
if ( this == & other) return * this;
|
||||
c_ = other.c_;
|
||||
iterator & operator=( iterator const& other) noexcept {
|
||||
if ( this != & other) {
|
||||
c_ = other.c_;
|
||||
}
|
||||
return * this;
|
||||
}
|
||||
|
||||
bool operator==( iterator const& other) const {
|
||||
bool operator==( iterator const& other) const noexcept {
|
||||
return other.c_ == c_;
|
||||
}
|
||||
|
||||
bool operator!=( iterator const& other) const {
|
||||
bool operator!=( iterator const& other) const noexcept {
|
||||
return other.c_ != c_;
|
||||
}
|
||||
|
||||
@ -125,11 +125,11 @@ public:
|
||||
|
||||
iterator operator++( int) = delete;
|
||||
|
||||
reference_t operator*() const {
|
||||
reference_t operator*() const noexcept {
|
||||
return c_->cb_->get();
|
||||
}
|
||||
|
||||
pointer_t operator->() const {
|
||||
pointer_t operator->() const noexcept {
|
||||
return std::addressof( c_->cb_->get() );
|
||||
}
|
||||
};
|
||||
@ -147,25 +147,25 @@ private:
|
||||
|
||||
control_block * cb_;
|
||||
|
||||
explicit pull_coroutine( control_block *);
|
||||
explicit pull_coroutine( control_block *) noexcept;
|
||||
|
||||
bool has_result_() const;
|
||||
bool has_result_() const noexcept;
|
||||
|
||||
public:
|
||||
template< typename Fn >
|
||||
explicit pull_coroutine( Fn &&, bool = false);
|
||||
explicit pull_coroutine( 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 & 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) {
|
||||
cb_ = other.cb_;
|
||||
other.cb_ = nullptr;
|
||||
@ -179,7 +179,7 @@ public:
|
||||
|
||||
bool operator!() const noexcept;
|
||||
|
||||
T & get();
|
||||
T & get() noexcept;
|
||||
|
||||
class iterator : public std::iterator< std::input_iterator_tag, typename std::remove_reference< T >::type > {
|
||||
private:
|
||||
@ -204,30 +204,31 @@ public:
|
||||
typedef typename iterator::pointer pointer_t;
|
||||
typedef typename iterator::reference reference_t;
|
||||
|
||||
iterator() :
|
||||
c_( nullptr) {
|
||||
iterator() noexcept :
|
||||
c_{ nullptr } {
|
||||
}
|
||||
|
||||
explicit iterator( pull_coroutine< T & > * c) :
|
||||
c_( c) {
|
||||
c_{ c } {
|
||||
fetch_();
|
||||
}
|
||||
|
||||
iterator( iterator const& other) :
|
||||
c_( other.c_) {
|
||||
iterator( iterator const& other) noexcept :
|
||||
c_{ other.c_ } {
|
||||
}
|
||||
|
||||
iterator & operator=( iterator const& other) {
|
||||
if ( this == & other) return * this;
|
||||
c_ = other.c_;
|
||||
iterator & operator=( iterator const& other) noexcept {
|
||||
if ( this != & other) {
|
||||
c_ = other.c_;
|
||||
}
|
||||
return * this;
|
||||
}
|
||||
|
||||
bool operator==( iterator const& other) const {
|
||||
bool operator==( iterator const& other) const noexcept {
|
||||
return other.c_ == c_;
|
||||
}
|
||||
|
||||
bool operator!=( iterator const& other) const {
|
||||
bool operator!=( iterator const& other) const noexcept {
|
||||
return other.c_ != c_;
|
||||
}
|
||||
|
||||
@ -238,11 +239,11 @@ public:
|
||||
|
||||
iterator operator++( int) = delete;
|
||||
|
||||
reference_t operator*() const {
|
||||
reference_t operator*() const noexcept {
|
||||
return c_->cb_->get();
|
||||
}
|
||||
|
||||
pointer_t operator->() const {
|
||||
pointer_t operator->() const noexcept {
|
||||
return std::addressof( c_->cb_->get() );
|
||||
}
|
||||
};
|
||||
@ -260,23 +261,23 @@ private:
|
||||
|
||||
control_block * cb_;
|
||||
|
||||
explicit pull_coroutine( control_block *);
|
||||
explicit pull_coroutine( control_block *) noexcept;
|
||||
|
||||
public:
|
||||
template< typename Fn >
|
||||
explicit pull_coroutine( Fn &&, bool = false);
|
||||
explicit pull_coroutine( 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 & 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) {
|
||||
cb_ = other.cb_;
|
||||
other.cb_ = nullptr;
|
||||
|
@ -8,16 +8,13 @@
|
||||
#define BOOST_COROUTINES2_DETAIL_PULL_COROUTINE_IPP
|
||||
|
||||
#include <algorithm>
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
|
||||
#include <boost/assert.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/create_control_block.ipp>
|
||||
#include <boost/coroutine2/fixedsize_stack.hpp>
|
||||
#include <boost/coroutine2/segmented_stack.hpp>
|
||||
|
||||
@ -32,57 +29,41 @@ namespace detail {
|
||||
// pull_coroutine< T >
|
||||
|
||||
template< typename T >
|
||||
pull_coroutine< T >::pull_coroutine( control_block * cb) :
|
||||
cb_( cb) {
|
||||
pull_coroutine< T >::pull_coroutine( control_block * cb) noexcept :
|
||||
cb_{ cb } {
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
bool
|
||||
pull_coroutine< T >::has_result_() const {
|
||||
pull_coroutine< T >::has_result_() const noexcept {
|
||||
return nullptr != cb_->other->t;
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
template< typename Fn >
|
||||
pull_coroutine< T >::pull_coroutine( Fn && fn, bool preserve_fpu) :
|
||||
pull_coroutine( default_stack(), std::forward< Fn >( fn), preserve_fpu) {
|
||||
pull_coroutine< T >::pull_coroutine( Fn && fn) :
|
||||
pull_coroutine{ default_stack(), std::forward< Fn >( fn) } {
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
template< typename StackAllocator, typename Fn >
|
||||
pull_coroutine< T >::pull_coroutine( StackAllocator salloc, Fn && fn, bool preserve_fpu) :
|
||||
cb_( nullptr) {
|
||||
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);
|
||||
pull_coroutine< T >::pull_coroutine( StackAllocator salloc, Fn && fn) :
|
||||
cb_{ create_control_block< control_block >( salloc, std::forward< Fn >( fn) ) } {
|
||||
if ( ! cb_->valid() ) {
|
||||
cb_->~control_block();
|
||||
cb_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
pull_coroutine< T >::~pull_coroutine() {
|
||||
pull_coroutine< T >::~pull_coroutine() noexcept {
|
||||
if ( nullptr != cb_) {
|
||||
cb_->~control_block();
|
||||
}
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
pull_coroutine< T >::pull_coroutine( pull_coroutine && other) :
|
||||
pull_coroutine< T >::pull_coroutine( pull_coroutine && other) noexcept :
|
||||
cb_( other.cb_) {
|
||||
other.cb_ = nullptr;
|
||||
}
|
||||
@ -107,7 +88,7 @@ pull_coroutine< T >::operator!() const noexcept {
|
||||
|
||||
template< typename T >
|
||||
T
|
||||
pull_coroutine< T >::get() {
|
||||
pull_coroutine< T >::get() noexcept {
|
||||
return std::move( cb_->get() );
|
||||
}
|
||||
|
||||
@ -115,57 +96,41 @@ pull_coroutine< T >::get() {
|
||||
// pull_coroutine< T & >
|
||||
|
||||
template< typename T >
|
||||
pull_coroutine< T & >::pull_coroutine( control_block * cb) :
|
||||
pull_coroutine< T & >::pull_coroutine( control_block * cb) noexcept :
|
||||
cb_( cb) {
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
bool
|
||||
pull_coroutine< T & >::has_result_() const {
|
||||
pull_coroutine< T & >::has_result_() const noexcept {
|
||||
return nullptr != cb_->other->t;
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
template< typename Fn >
|
||||
pull_coroutine< T & >::pull_coroutine( Fn && fn, bool preserve_fpu) :
|
||||
pull_coroutine( default_stack(), std::forward< Fn >( fn), preserve_fpu) {
|
||||
pull_coroutine< T & >::pull_coroutine( Fn && fn) :
|
||||
pull_coroutine{ default_stack(), std::forward< Fn >( fn) } {
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
template< typename StackAllocator, typename Fn >
|
||||
pull_coroutine< T & >::pull_coroutine( StackAllocator salloc, Fn && fn, bool preserve_fpu) :
|
||||
cb_( nullptr) {
|
||||
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);
|
||||
pull_coroutine< T & >::pull_coroutine( StackAllocator salloc, Fn && fn) :
|
||||
cb_{ create_control_block< control_block >( salloc, std::forward< Fn >( fn) ) } {
|
||||
if ( ! cb_->valid() ) {
|
||||
cb_->~control_block();
|
||||
cb_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
pull_coroutine< T & >::~pull_coroutine() {
|
||||
pull_coroutine< T & >::~pull_coroutine() noexcept {
|
||||
if ( nullptr != cb_) {
|
||||
cb_->~control_block();
|
||||
}
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
pull_coroutine< T & >::pull_coroutine( pull_coroutine && other) :
|
||||
pull_coroutine< T & >::pull_coroutine( pull_coroutine && other) noexcept :
|
||||
cb_( other.cb_) {
|
||||
other.cb_ = nullptr;
|
||||
}
|
||||
@ -190,7 +155,7 @@ pull_coroutine< T & >::operator!() const noexcept {
|
||||
|
||||
template< typename T >
|
||||
T &
|
||||
pull_coroutine< T & >::get() {
|
||||
pull_coroutine< T & >::get() noexcept {
|
||||
return cb_->get();
|
||||
}
|
||||
|
||||
@ -198,49 +163,33 @@ pull_coroutine< T & >::get() {
|
||||
// pull_coroutine< void >
|
||||
|
||||
inline
|
||||
pull_coroutine< void >::pull_coroutine( control_block * cb) :
|
||||
pull_coroutine< void >::pull_coroutine( control_block * cb) noexcept :
|
||||
cb_( cb) {
|
||||
}
|
||||
|
||||
template< typename Fn >
|
||||
pull_coroutine< void >::pull_coroutine( Fn && fn, bool preserve_fpu) :
|
||||
pull_coroutine( default_stack(), std::forward< Fn >( fn), preserve_fpu) {
|
||||
pull_coroutine< void >::pull_coroutine( Fn && fn) :
|
||||
pull_coroutine{ default_stack(), std::forward< Fn >( fn) } {
|
||||
}
|
||||
|
||||
template< typename StackAllocator, typename Fn >
|
||||
pull_coroutine< void >::pull_coroutine( StackAllocator salloc, Fn && fn, bool preserve_fpu) :
|
||||
cb_( nullptr) {
|
||||
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);
|
||||
pull_coroutine< void >::pull_coroutine( StackAllocator salloc, Fn && fn) :
|
||||
cb_{ create_control_block< control_block >( salloc, std::forward< Fn >( fn) ) } {
|
||||
if ( ! cb_->valid() ) {
|
||||
cb_->~control_block();
|
||||
cb_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
inline
|
||||
pull_coroutine< void >::~pull_coroutine() {
|
||||
pull_coroutine< void >::~pull_coroutine() noexcept {
|
||||
if ( nullptr != cb_) {
|
||||
cb_->~control_block();
|
||||
}
|
||||
}
|
||||
|
||||
inline
|
||||
pull_coroutine< void >::pull_coroutine( pull_coroutine && other) :
|
||||
pull_coroutine< void >::pull_coroutine( pull_coroutine && other) noexcept :
|
||||
cb_( other.cb_) {
|
||||
other.cb_ = nullptr;
|
||||
}
|
||||
|
@ -12,6 +12,8 @@
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/context/execution_context.hpp>
|
||||
|
||||
#include <boost/coroutine2/detail/state.hpp>
|
||||
|
||||
#ifdef BOOST_HAS_ABI_HEADERS
|
||||
# include BOOST_ABI_PREFIX
|
||||
#endif
|
||||
@ -24,16 +26,15 @@ template< typename T >
|
||||
struct push_coroutine< T >::control_block {
|
||||
typename pull_coroutine< T >::control_block * other;
|
||||
boost::context::execution_context ctx;
|
||||
bool preserve_fpu;
|
||||
int state;
|
||||
state_t state;
|
||||
std::exception_ptr except;
|
||||
|
||||
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 & operator=( control_block &) = delete;
|
||||
@ -49,16 +50,15 @@ template< typename T >
|
||||
struct push_coroutine< T & >::control_block {
|
||||
typename pull_coroutine< T & >::control_block * other;
|
||||
boost::context::execution_context ctx;
|
||||
bool preserve_fpu;
|
||||
int state;
|
||||
state_t state;
|
||||
std::exception_ptr except;
|
||||
|
||||
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 & operator=( control_block &) = delete;
|
||||
@ -71,16 +71,15 @@ struct push_coroutine< T & >::control_block {
|
||||
struct push_coroutine< void >::control_block {
|
||||
pull_coroutine< void >::control_block * other;
|
||||
boost::context::execution_context ctx;
|
||||
bool preserve_fpu;
|
||||
int state;
|
||||
state_t state;
|
||||
std::exception_ptr except;
|
||||
|
||||
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 & operator=( control_block &) = delete;
|
||||
|
@ -33,16 +33,16 @@ namespace detail {
|
||||
template< typename T >
|
||||
template< typename StackAllocator, typename Fn >
|
||||
push_coroutine< T >::control_block::control_block( context::preallocated palloc, StackAllocator salloc,
|
||||
Fn && fn_, bool preserve_fpu_) :
|
||||
other( nullptr),
|
||||
ctx( std::allocator_arg, palloc, salloc,
|
||||
[=,fn=std::forward< Fn >( fn_),ctx=boost::context::execution_context::current()] (void *) mutable -> void {
|
||||
Fn && fn_) :
|
||||
other{ nullptr },
|
||||
ctx{ std::allocator_arg, palloc, salloc,
|
||||
[this,fn=std::forward< Fn >( fn_),ctx=boost::context::execution_context::current()] (void *) mutable noexcept {
|
||||
// create synthesized pull_coroutine< T >
|
||||
typename pull_coroutine< T >::control_block synthesized_cb( this, ctx);
|
||||
pull_coroutine< T > synthesized( & synthesized_cb);
|
||||
typename pull_coroutine< T >::control_block synthesized_cb{ this, ctx };
|
||||
pull_coroutine< T > synthesized{ & synthesized_cb };
|
||||
other = & synthesized_cb;
|
||||
// jump back to ctor
|
||||
T * t = reinterpret_cast< T * >( ctx( nullptr, preserve_fpu) );
|
||||
T * t = static_cast< T * >( ctx() );
|
||||
// set transferred value
|
||||
synthesized_cb.set( t);
|
||||
try {
|
||||
@ -55,35 +55,33 @@ push_coroutine< T >::control_block::control_block( context::preallocated palloc,
|
||||
except = std::current_exception();
|
||||
}
|
||||
// set termination flags
|
||||
state |= static_cast< int >( state_t::complete);
|
||||
state |= state_t::complete;
|
||||
// jump back to ctx
|
||||
other->ctx( nullptr, preserve_fpu);
|
||||
other->ctx();
|
||||
BOOST_ASSERT_MSG( false, "push_coroutine is complete");
|
||||
}),
|
||||
preserve_fpu( preserve_fpu_),
|
||||
state( static_cast< int >( state_t::unwind) ),
|
||||
except() {
|
||||
}},
|
||||
state{ state_t::unwind },
|
||||
except{} {
|
||||
// enter coroutine-fn in order to get other set
|
||||
ctx( nullptr, preserve_fpu);
|
||||
ctx();
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
push_coroutine< T >::control_block::control_block( typename pull_coroutine< T >::control_block * cb,
|
||||
boost::context::execution_context const& ctx_) :
|
||||
other( cb),
|
||||
ctx( ctx_),
|
||||
preserve_fpu( other->preserve_fpu),
|
||||
state( 0),
|
||||
except() {
|
||||
boost::context::execution_context const& ctx_) noexcept :
|
||||
other{ cb },
|
||||
ctx{ ctx_ },
|
||||
state{ state_t::none },
|
||||
except{} {
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
push_coroutine< T >::control_block::~control_block() {
|
||||
if ( 0 == ( state & static_cast< int >( state_t::complete ) ) &&
|
||||
0 != ( state & static_cast< int >( state_t::unwind) ) ) {
|
||||
push_coroutine< T >::control_block::~control_block() noexcept {
|
||||
if ( state_t::none == ( state & state_t::complete) &&
|
||||
state_t::none != ( state & state_t::unwind) ) {
|
||||
// set early-exit flag
|
||||
state |= static_cast< int >( state_t::early_exit);
|
||||
ctx( nullptr, preserve_fpu);
|
||||
state |= state_t::early_exit;
|
||||
ctx();
|
||||
}
|
||||
}
|
||||
|
||||
@ -92,12 +90,12 @@ void
|
||||
push_coroutine< T >::control_block::resume( T const& t) {
|
||||
other->ctx = boost::context::execution_context::current();
|
||||
// pass an pointer to other context
|
||||
ctx( const_cast< T * >( & t), preserve_fpu);
|
||||
ctx( const_cast< T * >( & t) );
|
||||
if ( except) {
|
||||
std::rethrow_exception( except);
|
||||
}
|
||||
// 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();
|
||||
}
|
||||
}
|
||||
@ -107,12 +105,12 @@ void
|
||||
push_coroutine< T >::control_block::resume( T && t) {
|
||||
other->ctx = boost::context::execution_context::current();
|
||||
// pass an pointer to other context
|
||||
ctx( std::addressof( t), preserve_fpu);
|
||||
ctx( std::addressof( t) );
|
||||
if ( except) {
|
||||
std::rethrow_exception( except);
|
||||
}
|
||||
// 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();
|
||||
}
|
||||
}
|
||||
@ -120,7 +118,7 @@ push_coroutine< T >::control_block::resume( T && t) {
|
||||
template< typename T >
|
||||
bool
|
||||
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 StackAllocator, typename Fn >
|
||||
push_coroutine< T & >::control_block::control_block( context::preallocated palloc, StackAllocator salloc,
|
||||
Fn && fn_, bool preserve_fpu_) :
|
||||
other( nullptr),
|
||||
ctx( std::allocator_arg, palloc, salloc,
|
||||
[=,fn=std::forward< Fn >( fn_),ctx=boost::context::execution_context::current()] (void *) mutable -> void {
|
||||
Fn && fn_) :
|
||||
other{ nullptr },
|
||||
ctx{ std::allocator_arg, palloc, salloc,
|
||||
[this,fn=std::forward< Fn >( fn_),ctx=boost::context::execution_context::current()] (void *) mutable noexcept {
|
||||
// create synthesized pull_coroutine< T >
|
||||
typename pull_coroutine< T & >::control_block synthesized_cb( this, ctx);
|
||||
pull_coroutine< T & > synthesized( & synthesized_cb);
|
||||
typename pull_coroutine< T & >::control_block synthesized_cb{ this, ctx };
|
||||
pull_coroutine< T & > synthesized{ & synthesized_cb };
|
||||
other = & synthesized_cb;
|
||||
// jump back to ctor
|
||||
T * t = reinterpret_cast< T * >( ctx( nullptr, preserve_fpu) );
|
||||
T * t = static_cast< T * >( ctx() );
|
||||
// set transferred value
|
||||
synthesized_cb.t = t;
|
||||
try {
|
||||
@ -151,35 +149,33 @@ push_coroutine< T & >::control_block::control_block( context::preallocated pallo
|
||||
except = std::current_exception();
|
||||
}
|
||||
// set termination flags
|
||||
state |= static_cast< int >( state_t::complete);
|
||||
state |= state_t::complete;
|
||||
// jump back to ctx
|
||||
other->ctx( nullptr, preserve_fpu);
|
||||
other->ctx();
|
||||
BOOST_ASSERT_MSG( false, "push_coroutine is complete");
|
||||
}),
|
||||
preserve_fpu( preserve_fpu_),
|
||||
state( static_cast< int >( state_t::unwind) ),
|
||||
except() {
|
||||
}},
|
||||
state{ state_t::unwind },
|
||||
except{} {
|
||||
// enter coroutine-fn in order to get other set
|
||||
ctx( nullptr, preserve_fpu);
|
||||
ctx();
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
push_coroutine< T & >::control_block::control_block( typename pull_coroutine< T & >::control_block * cb,
|
||||
boost::context::execution_context const& ctx_) :
|
||||
other( cb),
|
||||
ctx( ctx_),
|
||||
preserve_fpu( other->preserve_fpu),
|
||||
state( 0),
|
||||
except() {
|
||||
boost::context::execution_context const& ctx_) noexcept :
|
||||
other{ cb },
|
||||
ctx{ ctx_ },
|
||||
state{ state_t::none },
|
||||
except{} {
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
push_coroutine< T & >::control_block::~control_block() {
|
||||
if ( 0 == ( state & static_cast< int >( state_t::complete ) ) &&
|
||||
0 != ( state & static_cast< int >( state_t::unwind) ) ) {
|
||||
push_coroutine< T & >::control_block::~control_block() noexcept {
|
||||
if ( state_t::none == ( state & state_t::complete) &&
|
||||
state_t::none != ( state & state_t::unwind) ) {
|
||||
// set early-exit flag
|
||||
state |= static_cast< int >( state_t::early_exit);
|
||||
ctx( nullptr, preserve_fpu);
|
||||
state |= state_t::early_exit;
|
||||
ctx();
|
||||
}
|
||||
}
|
||||
|
||||
@ -188,12 +184,12 @@ void
|
||||
push_coroutine< T & >::control_block::resume( T & t) {
|
||||
other->ctx = boost::context::execution_context::current();
|
||||
// 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) {
|
||||
std::rethrow_exception( except);
|
||||
}
|
||||
// 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();
|
||||
}
|
||||
}
|
||||
@ -201,23 +197,23 @@ push_coroutine< T & >::control_block::resume( T & t) {
|
||||
template< typename T >
|
||||
bool
|
||||
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 >
|
||||
|
||||
template< typename StackAllocator, typename Fn >
|
||||
push_coroutine< void >::control_block::control_block( context::preallocated palloc, StackAllocator salloc, Fn && fn_, bool preserve_fpu_) :
|
||||
other( nullptr),
|
||||
ctx( std::allocator_arg, palloc, salloc,
|
||||
[=,fn=std::forward< Fn >( fn_),ctx=boost::context::execution_context::current()] (void *) mutable -> void {
|
||||
push_coroutine< void >::control_block::control_block( context::preallocated palloc, StackAllocator salloc, Fn && fn_) :
|
||||
other{ nullptr },
|
||||
ctx{ std::allocator_arg, palloc, salloc,
|
||||
[this,fn=std::forward< Fn >( fn_),ctx=boost::context::execution_context::current()] (void *) mutable noexcept {
|
||||
// create synthesized pull_coroutine< T >
|
||||
typename pull_coroutine< void >::control_block synthesized_cb( this, ctx);
|
||||
pull_coroutine< void > synthesized( & synthesized_cb);
|
||||
typename pull_coroutine< void >::control_block synthesized_cb{ this, ctx };
|
||||
pull_coroutine< void > synthesized{ & synthesized_cb };
|
||||
other = & synthesized_cb;
|
||||
// jump back to ctor
|
||||
ctx( nullptr, preserve_fpu);
|
||||
ctx();
|
||||
try {
|
||||
// call coroutine-fn with synthesized pull_coroutine as argument
|
||||
fn( synthesized);
|
||||
@ -228,35 +224,33 @@ push_coroutine< void >::control_block::control_block( context::preallocated pall
|
||||
except = std::current_exception();
|
||||
}
|
||||
// set termination flags
|
||||
state |= static_cast< int >( state_t::complete);
|
||||
state |= state_t::complete;
|
||||
// jump back to ctx
|
||||
other->ctx( nullptr, preserve_fpu);
|
||||
other->ctx();
|
||||
BOOST_ASSERT_MSG( false, "push_coroutine is complete");
|
||||
}),
|
||||
preserve_fpu( preserve_fpu_),
|
||||
state( static_cast< int >( state_t::unwind) ),
|
||||
except() {
|
||||
}},
|
||||
state{ state_t::unwind },
|
||||
except{} {
|
||||
// enter coroutine-fn in order to get other set
|
||||
ctx( nullptr, preserve_fpu);
|
||||
ctx();
|
||||
}
|
||||
|
||||
inline
|
||||
push_coroutine< void >::control_block::control_block( pull_coroutine< void >::control_block * cb,
|
||||
boost::context::execution_context const& ctx_) :
|
||||
other( cb),
|
||||
ctx( ctx_),
|
||||
preserve_fpu( other->preserve_fpu),
|
||||
state( 0),
|
||||
except() {
|
||||
boost::context::execution_context const& ctx_) noexcept :
|
||||
other{ cb },
|
||||
ctx{ ctx_ },
|
||||
state{ state_t::none },
|
||||
except{} {
|
||||
}
|
||||
|
||||
inline
|
||||
push_coroutine< void >::control_block::~control_block() {
|
||||
if ( 0 == ( state & static_cast< int >( state_t::complete ) ) &&
|
||||
0 != ( state & static_cast< int >( state_t::unwind) ) ) {
|
||||
push_coroutine< void >::control_block::~control_block() noexcept {
|
||||
if ( state_t::none == ( state & state_t::complete) &&
|
||||
state_t::none != ( state & state_t::unwind) ) {
|
||||
// set early-exit flag
|
||||
state |= static_cast< int >( state_t::early_exit);
|
||||
ctx( nullptr, preserve_fpu);
|
||||
state |= state_t::early_exit;
|
||||
ctx();
|
||||
}
|
||||
}
|
||||
|
||||
@ -264,12 +258,12 @@ inline
|
||||
void
|
||||
push_coroutine< void >::control_block::resume() {
|
||||
other->ctx = boost::context::execution_context::current();
|
||||
ctx( nullptr, preserve_fpu);
|
||||
ctx();
|
||||
if ( except) {
|
||||
std::rethrow_exception( except);
|
||||
}
|
||||
// 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();
|
||||
}
|
||||
}
|
||||
@ -277,7 +271,7 @@ push_coroutine< void >::control_block::resume() {
|
||||
inline
|
||||
bool
|
||||
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/config.hpp>
|
||||
#include <boost/context/execution_context.hpp>
|
||||
|
||||
#include <boost/coroutine2/detail/config.hpp>
|
||||
|
||||
@ -34,23 +33,23 @@ private:
|
||||
|
||||
control_block * cb_;
|
||||
|
||||
explicit push_coroutine( control_block *);
|
||||
explicit push_coroutine( control_block *) noexcept;
|
||||
|
||||
public:
|
||||
template< typename Fn >
|
||||
explicit push_coroutine( Fn &&, bool = false);
|
||||
explicit push_coroutine( 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 & 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) {
|
||||
cb_ = other.cb_;
|
||||
other.cb_ = nullptr;
|
||||
@ -71,33 +70,35 @@ public:
|
||||
push_coroutine< T > * c_;
|
||||
|
||||
public:
|
||||
iterator() :
|
||||
c_( nullptr) {
|
||||
iterator() noexcept :
|
||||
c_{ nullptr } {
|
||||
}
|
||||
|
||||
explicit iterator( push_coroutine< T > * c) :
|
||||
c_( c) {
|
||||
explicit iterator( push_coroutine< T > * c) noexcept :
|
||||
c_{ c } {
|
||||
}
|
||||
|
||||
iterator & operator=( T t) {
|
||||
BOOST_ASSERT( c_);
|
||||
if ( ! ( * c_)( t) ) c_ = 0;
|
||||
if ( ! ( * c_)( t) ) {
|
||||
c_ = nullptr;
|
||||
}
|
||||
return * this;
|
||||
}
|
||||
|
||||
bool operator==( iterator const& other) const {
|
||||
bool operator==( iterator const& other) const noexcept {
|
||||
return other.c_ == c_;
|
||||
}
|
||||
|
||||
bool operator!=( iterator const& other) const {
|
||||
bool operator!=( iterator const& other) const noexcept {
|
||||
return other.c_ != c_;
|
||||
}
|
||||
|
||||
iterator & operator*() {
|
||||
iterator & operator*() noexcept {
|
||||
return * this;
|
||||
}
|
||||
|
||||
iterator & operator++() {
|
||||
iterator & operator++() noexcept {
|
||||
return * this;
|
||||
}
|
||||
};
|
||||
@ -113,23 +114,23 @@ private:
|
||||
|
||||
control_block * cb_;
|
||||
|
||||
explicit push_coroutine( control_block *);
|
||||
explicit push_coroutine( control_block *) noexcept;
|
||||
|
||||
public:
|
||||
template< typename Fn >
|
||||
explicit push_coroutine( Fn &&, bool = false);
|
||||
explicit push_coroutine( 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 & 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) {
|
||||
cb_ = other.cb_;
|
||||
other.cb_ = nullptr;
|
||||
@ -148,33 +149,35 @@ public:
|
||||
push_coroutine< T & > * c_;
|
||||
|
||||
public:
|
||||
iterator() :
|
||||
c_( nullptr) {
|
||||
iterator() noexcept :
|
||||
c_{ nullptr } {
|
||||
}
|
||||
|
||||
explicit iterator( push_coroutine< T & > * c) :
|
||||
c_( c) {
|
||||
explicit iterator( push_coroutine< T & > * c) noexcept :
|
||||
c_{ c } {
|
||||
}
|
||||
|
||||
iterator & operator=( T & t) {
|
||||
BOOST_ASSERT( c_);
|
||||
if ( ! ( * c_)( t) ) c_ = 0;
|
||||
if ( ! ( * c_)( t) ) {
|
||||
c_ = nullptr;
|
||||
}
|
||||
return * this;
|
||||
}
|
||||
|
||||
bool operator==( iterator const& other) const {
|
||||
bool operator==( iterator const& other) const noexcept {
|
||||
return other.c_ == c_;
|
||||
}
|
||||
|
||||
bool operator!=( iterator const& other) const {
|
||||
bool operator!=( iterator const& other) const noexcept {
|
||||
return other.c_ != c_;
|
||||
}
|
||||
|
||||
iterator & operator*() {
|
||||
iterator & operator*() noexcept {
|
||||
return * this;
|
||||
}
|
||||
|
||||
iterator & operator++() {
|
||||
iterator & operator++() noexcept {
|
||||
return * this;
|
||||
}
|
||||
};
|
||||
@ -190,23 +193,23 @@ private:
|
||||
|
||||
control_block * cb_;
|
||||
|
||||
explicit push_coroutine( control_block *);
|
||||
explicit push_coroutine( control_block *) noexcept;
|
||||
|
||||
public:
|
||||
template< typename Fn >
|
||||
explicit push_coroutine( Fn &&, bool = false);
|
||||
explicit push_coroutine( 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 & 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) {
|
||||
cb_ = other.cb_;
|
||||
other.cb_ = nullptr;
|
||||
|
@ -7,16 +7,13 @@
|
||||
#ifndef BOOST_COROUTINES2_DETAIL_PUSH_COROUTINE_IPP
|
||||
#define BOOST_COROUTINES2_DETAIL_PUSH_COROUTINE_IPP
|
||||
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
|
||||
#include <boost/assert.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/create_control_block.ipp>
|
||||
#include <boost/coroutine2/fixedsize_stack.hpp>
|
||||
#include <boost/coroutine2/segmented_stack.hpp>
|
||||
|
||||
@ -31,51 +28,31 @@ namespace detail {
|
||||
// push_coroutine< T >
|
||||
|
||||
template< typename T >
|
||||
push_coroutine< T >::push_coroutine( control_block * cb) :
|
||||
cb_( cb) {
|
||||
push_coroutine< T >::push_coroutine( control_block * cb) noexcept :
|
||||
cb_{ cb } {
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
template< typename Fn >
|
||||
push_coroutine< T >::push_coroutine( Fn && fn, bool preserve_fpu) :
|
||||
push_coroutine( default_stack(), std::forward< Fn >( fn), preserve_fpu) {
|
||||
push_coroutine< T >::push_coroutine( Fn && fn) :
|
||||
push_coroutine{ default_stack(), std::forward< Fn >( fn) } {
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
template< typename StackAllocator, typename Fn >
|
||||
push_coroutine< T >::push_coroutine( StackAllocator salloc, Fn && fn, bool preserve_fpu) :
|
||||
cb_( nullptr) {
|
||||
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);
|
||||
push_coroutine< T >::push_coroutine( StackAllocator salloc, Fn && fn) :
|
||||
cb_{ create_control_block< control_block >( salloc, std::forward< Fn >( fn) ) } {
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
push_coroutine< T >::~push_coroutine() {
|
||||
push_coroutine< T >::~push_coroutine() noexcept {
|
||||
if ( nullptr != cb_) {
|
||||
cb_->~control_block();
|
||||
}
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
push_coroutine< T >::push_coroutine( push_coroutine && other) :
|
||||
push_coroutine< T >::push_coroutine( push_coroutine && other) noexcept :
|
||||
cb_( other.cb_) {
|
||||
other.cb_ = nullptr;
|
||||
}
|
||||
@ -109,51 +86,31 @@ push_coroutine< T >::operator!() const noexcept {
|
||||
// push_coroutine< T & >
|
||||
|
||||
template< typename T >
|
||||
push_coroutine< T & >::push_coroutine( control_block * cb) :
|
||||
cb_( cb) {
|
||||
push_coroutine< T & >::push_coroutine( control_block * cb) noexcept :
|
||||
cb_{ cb } {
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
template< typename Fn >
|
||||
push_coroutine< T & >::push_coroutine( Fn && fn, bool preserve_fpu) :
|
||||
push_coroutine( default_stack(), std::forward< Fn >( fn), preserve_fpu) {
|
||||
push_coroutine< T & >::push_coroutine( Fn && fn) :
|
||||
push_coroutine{ default_stack(), std::forward< Fn >( fn) } {
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
template< typename StackAllocator, typename Fn >
|
||||
push_coroutine< T & >::push_coroutine( StackAllocator salloc, Fn && fn, bool preserve_fpu) :
|
||||
cb_( nullptr) {
|
||||
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);
|
||||
push_coroutine< T & >::push_coroutine( StackAllocator salloc, Fn && fn) :
|
||||
cb_{ create_control_block< control_block >( salloc, std::forward< Fn >( fn) ) } {
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
push_coroutine< T & >::~push_coroutine() {
|
||||
push_coroutine< T & >::~push_coroutine() noexcept {
|
||||
if ( nullptr != cb_) {
|
||||
cb_->~control_block();
|
||||
}
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
push_coroutine< T & >::push_coroutine( push_coroutine && other) :
|
||||
push_coroutine< T & >::push_coroutine( push_coroutine && other) noexcept :
|
||||
cb_( other.cb_) {
|
||||
other.cb_ = nullptr;
|
||||
}
|
||||
@ -180,49 +137,29 @@ push_coroutine< T & >::operator!() const noexcept {
|
||||
// push_coroutine< void >
|
||||
|
||||
inline
|
||||
push_coroutine< void >::push_coroutine( control_block * cb) :
|
||||
cb_( cb) {
|
||||
push_coroutine< void >::push_coroutine( control_block * cb) noexcept :
|
||||
cb_{ cb } {
|
||||
}
|
||||
|
||||
template< typename Fn >
|
||||
push_coroutine< void >::push_coroutine( Fn && fn, bool preserve_fpu) :
|
||||
push_coroutine( default_stack(), std::forward< Fn >( fn), preserve_fpu) {
|
||||
push_coroutine< void >::push_coroutine( Fn && fn) :
|
||||
push_coroutine{ default_stack(), std::forward< Fn >( fn) } {
|
||||
}
|
||||
|
||||
template< typename StackAllocator, typename Fn >
|
||||
push_coroutine< void >::push_coroutine( StackAllocator salloc, Fn && fn, bool preserve_fpu) :
|
||||
cb_( nullptr) {
|
||||
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);
|
||||
push_coroutine< void >::push_coroutine( StackAllocator salloc, Fn && fn) :
|
||||
cb_{ create_control_block< control_block >( salloc, std::forward< Fn >( fn) ) } {
|
||||
}
|
||||
|
||||
inline
|
||||
push_coroutine< void >::~push_coroutine() {
|
||||
push_coroutine< void >::~push_coroutine() noexcept {
|
||||
if ( nullptr != cb_) {
|
||||
cb_->~control_block();
|
||||
}
|
||||
}
|
||||
|
||||
inline
|
||||
push_coroutine< void >::push_coroutine( push_coroutine && other) :
|
||||
push_coroutine< void >::push_coroutine( push_coroutine && other) noexcept :
|
||||
cb_( other.cb_) {
|
||||
other.cb_ = nullptr;
|
||||
}
|
||||
|
@ -23,11 +23,61 @@ namespace coroutines2 {
|
||||
namespace detail {
|
||||
|
||||
enum class state_t : unsigned int {
|
||||
none = 0,
|
||||
complete = 1 << 1,
|
||||
unwind = 1 << 2,
|
||||
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
|
||||
|
@ -20,7 +20,6 @@
|
||||
typedef boost::coroutines2::protected_fixedsize_stack stack_allocator;
|
||||
typedef boost::coroutines2::coroutine< void > coro_type;
|
||||
|
||||
bool preserve = false;
|
||||
boost::uint64_t jobs = 1000;
|
||||
|
||||
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() );
|
||||
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;
|
||||
total -= overhead_clock(); // overhead of measurement
|
||||
@ -48,7 +47,7 @@ cycle_type measure_cycles( cycle_type overhead)
|
||||
|
||||
cycle_type start( cycles() );
|
||||
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;
|
||||
total -= overhead; // overhead of measurement
|
||||
@ -67,7 +66,6 @@ int main( int argc, char * argv[])
|
||||
desc.add_options()
|
||||
("help", "help message")
|
||||
("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");
|
||||
|
||||
boost::program_options::variables_map vm;
|
||||
|
@ -20,7 +20,6 @@
|
||||
typedef boost::coroutines2::fixedsize_stack stack_allocator;
|
||||
typedef boost::coroutines2::coroutine< void > coro_type;
|
||||
|
||||
bool preserve = false;
|
||||
boost::uint64_t jobs = 1000;
|
||||
|
||||
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() );
|
||||
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;
|
||||
total -= overhead_clock(); // overhead of measurement
|
||||
@ -48,7 +47,7 @@ cycle_type measure_cycles( cycle_type overhead)
|
||||
|
||||
cycle_type start( cycles() );
|
||||
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;
|
||||
total -= overhead; // overhead of measurement
|
||||
@ -67,7 +66,6 @@ int main( int argc, char * argv[])
|
||||
desc.add_options()
|
||||
("help", "help message")
|
||||
("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");
|
||||
|
||||
boost::program_options::variables_map vm;
|
||||
|
@ -18,7 +18,6 @@
|
||||
#include "clock.hpp"
|
||||
#include "cycle.hpp"
|
||||
|
||||
bool preserve = false;
|
||||
boost::uint64_t jobs = 1000;
|
||||
|
||||
struct X
|
||||
@ -45,7 +44,7 @@ void fn_x( boost::coroutines2::coroutine< X >::push_type & c)
|
||||
|
||||
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() );
|
||||
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)
|
||||
{
|
||||
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() );
|
||||
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)
|
||||
{
|
||||
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() );
|
||||
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
|
||||
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() );
|
||||
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)
|
||||
{
|
||||
boost::coroutines2::coroutine< int >::pull_type c( fn_int, preserve);
|
||||
boost::coroutines2::coroutine< int >::pull_type c( fn_int);
|
||||
|
||||
cycle_type start( cycles() );
|
||||
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)
|
||||
{
|
||||
boost::coroutines2::coroutine< X >::pull_type c( fn_x, preserve);
|
||||
boost::coroutines2::coroutine< X >::pull_type c( fn_x);
|
||||
|
||||
cycle_type start( cycles() );
|
||||
for ( std::size_t i = 0; i < jobs; ++i) {
|
||||
@ -150,7 +149,6 @@ int main( int argc, char * argv[])
|
||||
desc.add_options()
|
||||
("help", "help message")
|
||||
("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");
|
||||
|
||||
boost::program_options::variables_map vm;
|
||||
|
@ -20,7 +20,6 @@
|
||||
typedef boost::coroutines2::segmented_stack stack_allocator;
|
||||
typedef boost::coroutines2::coroutine< void > coro_type;
|
||||
|
||||
bool preserve = false;
|
||||
boost::uint64_t jobs = 1000;
|
||||
|
||||
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() );
|
||||
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;
|
||||
total -= overhead_clock(); // overhead of measurement
|
||||
@ -48,7 +47,7 @@ cycle_type measure_cycles( cycle_type overhead)
|
||||
|
||||
cycle_type start( cycles() );
|
||||
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;
|
||||
total -= overhead; // overhead of measurement
|
||||
@ -62,12 +61,11 @@ int main( int argc, char * argv[])
|
||||
{
|
||||
try
|
||||
{
|
||||
bool preserve = false, unwind = true, bind = false;
|
||||
bool bind = false;
|
||||
boost::program_options::options_description desc("allowed options");
|
||||
desc.add_options()
|
||||
("help", "help message")
|
||||
("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");
|
||||
|
||||
boost::program_options::variables_map vm;
|
||||
|
@ -18,7 +18,6 @@
|
||||
#include "../clock.hpp"
|
||||
#include "../cycle.hpp"
|
||||
|
||||
bool preserve = false;
|
||||
boost::uint64_t jobs = 1000;
|
||||
|
||||
struct X
|
||||
@ -46,7 +45,7 @@ void fn_x( boost::coroutines2::coroutine< X >::push_type & c)
|
||||
duration_type measure_time_void( duration_type overhead)
|
||||
{
|
||||
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() );
|
||||
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)
|
||||
{
|
||||
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() );
|
||||
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)
|
||||
{
|
||||
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() );
|
||||
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)
|
||||
{
|
||||
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() );
|
||||
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)
|
||||
{
|
||||
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() );
|
||||
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)
|
||||
{
|
||||
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() );
|
||||
for ( std::size_t i = 0; i < jobs; ++i) {
|
||||
@ -156,7 +155,6 @@ int main( int argc, char * argv[])
|
||||
desc.add_options()
|
||||
("help", "help message")
|
||||
("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");
|
||||
|
||||
boost::program_options::variables_map vm;
|
||||
|
Loading…
x
Reference in New Issue
Block a user