adapt new execution_context API

This commit is contained in:
Oliver Kowalke 2015-11-10 20:02:33 +01:00
parent fe869dd847
commit 4bb8f7585f
22 changed files with 501 additions and 544 deletions

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;

View File

@ -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;
}

View File

@ -54,7 +54,7 @@ int main() {
sink();
std::cout << "main: done" << std::endl;
std::cout << "main: Done" << std::endl;
return 0;
}

View File

@ -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;
}

View 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

View File

@ -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

View File

@ -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;

View File

@ -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);
}
}}}

View File

@ -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;

View File

@ -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;
}

View File

@ -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;

View File

@ -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 );
}
}}}

View File

@ -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;

View File

@ -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;
}

View File

@ -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

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;