mirror of
https://github.com/boostorg/coroutine2.git
synced 2025-05-09 23:24:01 +00:00
relax to C++11
This commit is contained in:
parent
ba6ea4b7a6
commit
2c2524fe8e
@ -8,6 +8,7 @@
|
||||
#define BOOST_COROUTINES2_DETAIL_PULL_CONTROL_BLOCK_HPP
|
||||
|
||||
#include <exception>
|
||||
#include <functional>
|
||||
#include <type_traits>
|
||||
|
||||
#include <boost/config.hpp>
|
||||
@ -30,7 +31,7 @@ struct pull_coroutine< T >::control_block {
|
||||
state_t state;
|
||||
std::exception_ptr except;
|
||||
bool bvalid;
|
||||
typename std::aligned_storage< sizeof( T), alignof( T) >::type storage[1];
|
||||
typename std::aligned_storage< sizeof( T), alignof( T) >::type storage;
|
||||
|
||||
template< typename StackAllocator, typename Fn >
|
||||
control_block( context::preallocated, StackAllocator, Fn &&);
|
||||
|
@ -8,6 +8,7 @@
|
||||
#define BOOST_COROUTINES2_DETAIL_PULL_CONTROL_BLOCK_IPP
|
||||
|
||||
#include <exception>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
@ -32,10 +33,37 @@ namespace detail {
|
||||
template< typename T >
|
||||
template< typename StackAllocator, typename Fn >
|
||||
pull_coroutine< T >::control_block::control_block( context::preallocated palloc, StackAllocator salloc,
|
||||
Fn && fn_) :
|
||||
Fn && fn) :
|
||||
other{ nullptr },
|
||||
#if defined(BOOST_NO_CXX14_GENERIC_LAMBDAS)
|
||||
ctx{ std::allocator_arg, palloc, salloc,
|
||||
[this,fn=std::forward< Fn >( fn_),ctx=boost::context::execution_context::current()] (void *) mutable noexcept {
|
||||
std::bind(
|
||||
[this]( typename std::decay< Fn >::type & fn, boost::context::execution_context ctx, void *) mutable noexcept {
|
||||
// create synthesized push_coroutine< T >
|
||||
typename push_coroutine< T >::control_block synthesized_cb{ this, ctx };
|
||||
push_coroutine< T > synthesized{ & synthesized_cb };
|
||||
other = & synthesized_cb;
|
||||
try {
|
||||
// call coroutine-fn with synthesized push_coroutine as argument
|
||||
fn( synthesized);
|
||||
} catch ( forced_unwind const&) {
|
||||
// do nothing for unwinding exception
|
||||
} catch (...) {
|
||||
// store other exceptions in exception-pointer
|
||||
except = std::current_exception();
|
||||
}
|
||||
// set termination flags
|
||||
state |= state_t::complete;
|
||||
// jump back to ctx
|
||||
other->ctx();
|
||||
BOOST_ASSERT_MSG( false, "pull_coroutine is complete");
|
||||
},
|
||||
std::forward< Fn >( fn),
|
||||
boost::context::execution_context::current(),
|
||||
std::placeholders::_1)},
|
||||
#else
|
||||
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 };
|
||||
@ -55,6 +83,7 @@ pull_coroutine< T >::control_block::control_block( context::preallocated palloc,
|
||||
other->ctx();
|
||||
BOOST_ASSERT_MSG( false, "pull_coroutine is complete");
|
||||
}},
|
||||
#endif
|
||||
state{ state_t::unwind },
|
||||
except{},
|
||||
bvalid{ false },
|
||||
@ -84,7 +113,7 @@ pull_coroutine< T >::control_block::~control_block() noexcept {
|
||||
}
|
||||
// destroy data if it set
|
||||
if ( bvalid) {
|
||||
reinterpret_cast< T const* >( storage)->~T();
|
||||
reinterpret_cast< T * >( std::addressof( storage) )->~T();
|
||||
}
|
||||
}
|
||||
|
||||
@ -107,10 +136,10 @@ void
|
||||
pull_coroutine< T >::control_block::set( T * t) {
|
||||
// destroy data if it set
|
||||
if ( bvalid) {
|
||||
reinterpret_cast< T const* >( storage)->~T();
|
||||
reinterpret_cast< T * >( std::addressof( storage) )->~T();
|
||||
}
|
||||
if ( nullptr != t) {
|
||||
new ( storage) T( std::move( * t) ); // FIXME: differrentiation between move/copy
|
||||
::new ( static_cast< void * >( std::addressof( storage) ) ) T( std::move( * t) );
|
||||
bvalid = true;
|
||||
} else {
|
||||
bvalid = false;
|
||||
@ -120,7 +149,7 @@ pull_coroutine< T >::control_block::set( T * t) {
|
||||
template< typename T >
|
||||
T &
|
||||
pull_coroutine< T >::control_block::get() noexcept {
|
||||
return * reinterpret_cast< T * >( storage);
|
||||
return * reinterpret_cast< T * >( std::addressof( storage) );
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
@ -135,10 +164,37 @@ 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_) :
|
||||
Fn && fn) :
|
||||
other{ nullptr },
|
||||
#if defined(BOOST_NO_CXX14_GENERIC_LAMBDAS)
|
||||
ctx{ std::allocator_arg, palloc, salloc,
|
||||
[this,fn=std::forward< Fn >( fn_),ctx=boost::context::execution_context::current()] (void *) mutable noexcept {
|
||||
std::bind(
|
||||
[this]( typename std::decay< Fn >::type & fn, boost::context::execution_context ctx, void *) mutable noexcept {
|
||||
// create synthesized push_coroutine< T >
|
||||
typename push_coroutine< T & >::control_block synthesized_cb{ this, ctx };
|
||||
push_coroutine< T & > synthesized{ & synthesized_cb };
|
||||
other = & synthesized_cb;
|
||||
try {
|
||||
// call coroutine-fn with synthesized push_coroutine as argument
|
||||
fn( synthesized);
|
||||
} catch ( forced_unwind const&) {
|
||||
// do nothing for unwinding exception
|
||||
} catch (...) {
|
||||
// store other exceptions in exception-pointer
|
||||
except = std::current_exception();
|
||||
}
|
||||
// set termination flags
|
||||
state |= state_t::complete;
|
||||
// jump back to ctx
|
||||
other->ctx();
|
||||
BOOST_ASSERT_MSG( false, "pull_coroutine is complete");
|
||||
},
|
||||
std::forward< Fn >( fn),
|
||||
boost::context::execution_context::current(),
|
||||
std::placeholders::_1)},
|
||||
#else
|
||||
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 };
|
||||
@ -158,6 +214,7 @@ pull_coroutine< T & >::control_block::control_block( context::preallocated pallo
|
||||
other->ctx();
|
||||
BOOST_ASSERT_MSG( false, "pull_coroutine is complete");
|
||||
}},
|
||||
#endif
|
||||
state{ state_t::unwind },
|
||||
except{},
|
||||
t{ nullptr } {
|
||||
@ -216,10 +273,37 @@ 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_) :
|
||||
Fn && fn) :
|
||||
other{ nullptr },
|
||||
#if defined(BOOST_NO_CXX14_GENERIC_LAMBDAS)
|
||||
ctx{ std::allocator_arg, palloc, salloc,
|
||||
[this,fn=std::forward< Fn >( fn_),ctx=boost::context::execution_context::current()] (void *) mutable noexcept {
|
||||
std::bind(
|
||||
[this]( typename std::decay< Fn >::type & fn, boost::context::execution_context ctx, void *) mutable noexcept {
|
||||
// create synthesized push_coroutine< T >
|
||||
typename push_coroutine< void >::control_block synthesized_cb{ this, ctx };
|
||||
push_coroutine< void > synthesized{ & synthesized_cb };
|
||||
other = & synthesized_cb;
|
||||
try {
|
||||
// call coroutine-fn with synthesized push_coroutine as argument
|
||||
fn( synthesized);
|
||||
} catch ( forced_unwind const&) {
|
||||
// do nothing for unwinding exception
|
||||
} catch (...) {
|
||||
// store other exceptions in exception-pointer
|
||||
except = std::current_exception();
|
||||
}
|
||||
// set termination flags
|
||||
state |= state_t::complete;
|
||||
// jump back to ctx
|
||||
other->ctx();
|
||||
BOOST_ASSERT_MSG( false, "pull_coroutine is complete");
|
||||
},
|
||||
std::forward< Fn >( fn),
|
||||
boost::context::execution_context::current(),
|
||||
std::placeholders::_1)},
|
||||
#else
|
||||
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 };
|
||||
@ -239,6 +323,7 @@ pull_coroutine< void >::control_block::control_block( context::preallocated pall
|
||||
other->ctx();
|
||||
BOOST_ASSERT_MSG( false, "pull_coroutine is complete");
|
||||
}},
|
||||
#endif
|
||||
state{ state_t::unwind },
|
||||
except{} {
|
||||
// enter coroutine-fn in order to have first value available after ctor returns
|
||||
|
@ -7,6 +7,7 @@
|
||||
#ifndef BOOST_COROUTINES2_DETAIL_PUSH_CONTROL_BLOCK_HPP
|
||||
#define BOOST_COROUTINES2_DETAIL_PUSH_CONTROL_BLOCK_HPP
|
||||
|
||||
#include <functional>
|
||||
#include <exception>
|
||||
|
||||
#include <boost/config.hpp>
|
||||
|
@ -9,6 +9,7 @@
|
||||
|
||||
#include <algorithm>
|
||||
#include <exception>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
@ -33,10 +34,41 @@ namespace detail {
|
||||
template< typename T >
|
||||
template< typename StackAllocator, typename Fn >
|
||||
push_coroutine< T >::control_block::control_block( context::preallocated palloc, StackAllocator salloc,
|
||||
Fn && fn_) :
|
||||
Fn && fn) :
|
||||
other{ nullptr },
|
||||
#if defined(BOOST_NO_CXX14_GENERIC_LAMBDAS)
|
||||
ctx{ std::allocator_arg, palloc, salloc,
|
||||
[this,fn=std::forward< Fn >( fn_),ctx=boost::context::execution_context::current()] (void *) mutable noexcept {
|
||||
std::bind(
|
||||
[this]( typename std::decay< Fn >::type & fn, boost::context::execution_context ctx, void * vp) mutable noexcept {
|
||||
// create synthesized pull_coroutine< T >
|
||||
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 = static_cast< T * >( ctx() );
|
||||
// set transferred value
|
||||
synthesized_cb.set( t);
|
||||
try {
|
||||
// call coroutine-fn with synthesized pull_coroutine as argument
|
||||
fn( synthesized);
|
||||
} catch ( forced_unwind const&) {
|
||||
// do nothing for unwinding exception
|
||||
} catch (...) {
|
||||
// store other exceptions in exception-pointer
|
||||
except = std::current_exception();
|
||||
}
|
||||
// set termination flags
|
||||
state |= state_t::complete;
|
||||
// jump back to ctx
|
||||
other->ctx();
|
||||
BOOST_ASSERT_MSG( false, "push_coroutine is complete");
|
||||
},
|
||||
std::forward< Fn >( fn),
|
||||
boost::context::execution_context::current(),
|
||||
std::placeholders::_1)},
|
||||
#else
|
||||
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 };
|
||||
@ -60,6 +92,7 @@ push_coroutine< T >::control_block::control_block( context::preallocated palloc,
|
||||
other->ctx();
|
||||
BOOST_ASSERT_MSG( false, "push_coroutine is complete");
|
||||
}},
|
||||
#endif
|
||||
state{ state_t::unwind },
|
||||
except{} {
|
||||
// enter coroutine-fn in order to get other set
|
||||
@ -127,10 +160,41 @@ 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_) :
|
||||
Fn && fn) :
|
||||
other{ nullptr },
|
||||
#if defined(BOOST_NO_CXX14_GENERIC_LAMBDAS)
|
||||
ctx{ std::allocator_arg, palloc, salloc,
|
||||
[this,fn=std::forward< Fn >( fn_),ctx=boost::context::execution_context::current()] (void *) mutable noexcept {
|
||||
std::bind(
|
||||
[this]( typename std::decay< Fn >::type & fn, boost::context::execution_context ctx, void * vp) mutable noexcept {
|
||||
// create synthesized pull_coroutine< T >
|
||||
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 = static_cast< T * >( ctx() );
|
||||
// set transferred value
|
||||
synthesized_cb.t = t;
|
||||
try {
|
||||
// call coroutine-fn with synthesized pull_coroutine as argument
|
||||
fn( synthesized);
|
||||
} catch ( forced_unwind const&) {
|
||||
// do nothing for unwinding exception
|
||||
} catch (...) {
|
||||
// store other exceptions in exception-pointer
|
||||
except = std::current_exception();
|
||||
}
|
||||
// set termination flags
|
||||
state |= state_t::complete;
|
||||
// jump back to ctx
|
||||
other->ctx();
|
||||
BOOST_ASSERT_MSG( false, "push_coroutine is complete");
|
||||
},
|
||||
std::forward< Fn >( fn),
|
||||
boost::context::execution_context::current(),
|
||||
std::placeholders::_1)},
|
||||
#else
|
||||
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 };
|
||||
@ -154,6 +218,7 @@ push_coroutine< T & >::control_block::control_block( context::preallocated pallo
|
||||
other->ctx();
|
||||
BOOST_ASSERT_MSG( false, "push_coroutine is complete");
|
||||
}},
|
||||
#endif
|
||||
state{ state_t::unwind },
|
||||
except{} {
|
||||
// enter coroutine-fn in order to get other set
|
||||
@ -206,6 +271,36 @@ push_coroutine< T & >::control_block::valid() const noexcept {
|
||||
template< typename StackAllocator, typename Fn >
|
||||
push_coroutine< void >::control_block::control_block( context::preallocated palloc, StackAllocator salloc, Fn && fn_) :
|
||||
other{ nullptr },
|
||||
#if defined(BOOST_NO_CXX14_GENERIC_LAMBDAS)
|
||||
ctx{ std::allocator_arg, palloc, salloc,
|
||||
std::bind(
|
||||
[this]( typename std::decay< Fn >::type & fn, boost::context::execution_context ctx,
|
||||
void * vp) mutable noexcept {
|
||||
// create synthesized pull_coroutine< T >
|
||||
typename pull_coroutine< void >::control_block synthesized_cb{ this, ctx };
|
||||
pull_coroutine< void > synthesized{ & synthesized_cb };
|
||||
other = & synthesized_cb;
|
||||
// jump back to ctor
|
||||
ctx();
|
||||
try {
|
||||
// call coroutine-fn with synthesized pull_coroutine as argument
|
||||
fn( synthesized);
|
||||
} catch ( forced_unwind const&) {
|
||||
// do nothing for unwinding exception
|
||||
} catch (...) {
|
||||
// store other exceptions in exception-pointer
|
||||
except = std::current_exception();
|
||||
}
|
||||
// set termination flags
|
||||
state |= state_t::complete;
|
||||
// jump back to ctx
|
||||
other->ctx();
|
||||
BOOST_ASSERT_MSG( false, "push_coroutine is complete");
|
||||
},
|
||||
std::forward< Fn >( fn_),
|
||||
boost::context::execution_context::current(),
|
||||
std::placeholders::_1)},
|
||||
#else
|
||||
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 >
|
||||
@ -229,6 +324,7 @@ push_coroutine< void >::control_block::control_block( context::preallocated pall
|
||||
other->ctx();
|
||||
BOOST_ASSERT_MSG( false, "push_coroutine is complete");
|
||||
}},
|
||||
#endif
|
||||
state{ state_t::unwind },
|
||||
except{} {
|
||||
// enter coroutine-fn in order to get other set
|
||||
|
@ -193,10 +193,6 @@ void f12( coro::coroutine< void >::pull_type & c)
|
||||
c();
|
||||
}
|
||||
|
||||
template< typename E >
|
||||
void f14( coro::coroutine< void >::pull_type &, E const& e)
|
||||
{ throw e; }
|
||||
|
||||
void f16( coro::coroutine< int >::push_type & c)
|
||||
{
|
||||
c( 1);
|
||||
@ -216,13 +212,6 @@ void f17( coro::coroutine< int >::pull_type & c, std::vector< int > & vec)
|
||||
}
|
||||
}
|
||||
|
||||
void f19( coro::coroutine< int& >::push_type & c, int & i1, int & i2, int & i3)
|
||||
{
|
||||
c( i1);
|
||||
c( i2);
|
||||
c( i3);
|
||||
}
|
||||
|
||||
void f20( coro::coroutine< int >::push_type &)
|
||||
{}
|
||||
|
||||
@ -426,6 +415,12 @@ void test_const_ref()
|
||||
BOOST_CHECK_EQUAL( & a, value5);
|
||||
}
|
||||
|
||||
void test_no_result()
|
||||
{
|
||||
coro::coroutine< int >::pull_type coro( f20);
|
||||
BOOST_CHECK( ! coro);
|
||||
}
|
||||
|
||||
void test_tuple()
|
||||
{
|
||||
value8 = 0;
|
||||
@ -466,7 +461,9 @@ void test_exceptions()
|
||||
try
|
||||
{
|
||||
coro::coroutine< void >::push_type coro(
|
||||
std::bind( f14< std::runtime_error >, std::placeholders::_1, ex) );
|
||||
[&msg]( coro::coroutine< void >::pull_type &) {
|
||||
throw std::runtime_error( msg);
|
||||
});
|
||||
BOOST_CHECK( coro);
|
||||
coro();
|
||||
BOOST_CHECK( ! coro);
|
||||
@ -512,7 +509,12 @@ void test_input_iterator()
|
||||
{
|
||||
int i1 = 1, i2 = 2, i3 = 3;
|
||||
coro::coroutine< int& >::pull_type coro(
|
||||
std::bind( f19, std::placeholders::_1, std::ref( i1), std::ref( i2), std::ref( i3) ) );
|
||||
[&i1,&i2,&i3](coro::coroutine< int& >::push_type & c){
|
||||
c( i1);
|
||||
c( i2);
|
||||
c( i3);
|
||||
});
|
||||
|
||||
int counter = 1;
|
||||
for ( int & i : coro) {
|
||||
switch ( counter) {
|
||||
@ -564,12 +566,6 @@ void test_output_iterator()
|
||||
BOOST_CHECK_EQUAL( ( int)4, vec[3] );
|
||||
}
|
||||
|
||||
void test_no_result()
|
||||
{
|
||||
coro::coroutine< int >::pull_type coro( f20);
|
||||
BOOST_CHECK( ! coro);
|
||||
}
|
||||
|
||||
std::vector< int > vec;
|
||||
coro::coroutine< void >::pull_type * child = nullptr;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user