relax to C++11

This commit is contained in:
Oliver Kowalke 2015-12-12 19:51:45 +01:00
parent ba6ea4b7a6
commit 2c2524fe8e
5 changed files with 213 additions and 34 deletions

View File

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

View File

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

View File

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

View File

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

View File

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