update boost on linux
This commit is contained in:
@@ -27,12 +27,4 @@
|
||||
# define BOOST_COROUTINES2_DECL
|
||||
#endif
|
||||
|
||||
#if ! defined(BOOST_COROUTINES2_SOURCE) && ! defined(BOOST_ALL_NO_LIB) && ! defined(BOOST_COROUTINES2_NO_LIB)
|
||||
# define BOOST_LIB_NAME boost_coroutine2
|
||||
# if defined(BOOST_ALL_DYN_LINK) || defined(BOOST_COROUTINES2_DYN_LINK)
|
||||
# define BOOST_DYN_LINK
|
||||
# endif
|
||||
# include <boost/config/auto_link.hpp>
|
||||
#endif
|
||||
|
||||
#endif // BOOST_COROUTINES2_DETAIL_CONFIG_H
|
||||
|
||||
@@ -29,26 +29,14 @@ class push_coroutine;
|
||||
#include <boost/coroutine2/detail/pull_coroutine.hpp>
|
||||
#include <boost/coroutine2/detail/push_coroutine.hpp>
|
||||
|
||||
#if defined(BOOST_EXECUTION_CONTEXT)
|
||||
# if (BOOST_EXECUTION_CONTEXT==1)
|
||||
# include <boost/coroutine2/detail/pull_control_block_ecv1.hpp>
|
||||
# include <boost/coroutine2/detail/push_control_block_ecv1.hpp>
|
||||
# else
|
||||
# include <boost/coroutine2/detail/pull_control_block_cc.hpp>
|
||||
# include <boost/coroutine2/detail/push_control_block_cc.hpp>
|
||||
# endif
|
||||
#include <boost/coroutine2/detail/pull_control_block_cc.hpp>
|
||||
#include <boost/coroutine2/detail/push_control_block_cc.hpp>
|
||||
|
||||
# include <boost/coroutine2/detail/pull_coroutine.ipp>
|
||||
# include <boost/coroutine2/detail/push_coroutine.ipp>
|
||||
#include <boost/coroutine2/detail/pull_coroutine.ipp>
|
||||
#include <boost/coroutine2/detail/push_coroutine.ipp>
|
||||
|
||||
# if (BOOST_EXECUTION_CONTEXT==1)
|
||||
# include <boost/coroutine2/detail/pull_control_block_ecv1.ipp>
|
||||
# include <boost/coroutine2/detail/push_control_block_ecv1.ipp>
|
||||
# else
|
||||
# include <boost/coroutine2/detail/pull_control_block_cc.ipp>
|
||||
# include <boost/coroutine2/detail/push_control_block_cc.ipp>
|
||||
# endif
|
||||
#endif
|
||||
#include <boost/coroutine2/detail/pull_control_block_cc.ipp>
|
||||
#include <boost/coroutine2/detail/push_control_block_cc.ipp>
|
||||
|
||||
#ifdef BOOST_HAS_ABI_HEADERS
|
||||
# include BOOST_ABI_SUFFIX
|
||||
|
||||
@@ -28,7 +28,7 @@ namespace coroutines2 {
|
||||
namespace detail {
|
||||
|
||||
template< typename ControlBlock, typename StackAllocator, typename Fn >
|
||||
ControlBlock * create_control_block( StackAllocator salloc, Fn && fn) {
|
||||
ControlBlock * create_control_block( StackAllocator && salloc, Fn && fn) {
|
||||
auto sctx = salloc.allocate();
|
||||
// reserve space for control structure
|
||||
#if defined(BOOST_NO_CXX11_CONSTEXPR) || defined(BOOST_NO_CXX11_STD_ALIGN)
|
||||
@@ -48,7 +48,7 @@ ControlBlock * create_control_block( StackAllocator salloc, Fn && fn) {
|
||||
#endif
|
||||
// placment new for control structure on coroutine stack
|
||||
return new ( sp) ControlBlock{ context::preallocated( sp, size, sctx),
|
||||
salloc, std::forward< Fn >( fn) };
|
||||
std::forward< StackAllocator >( salloc), std::forward< Fn >( fn) };
|
||||
}
|
||||
|
||||
}}}
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
#include <type_traits>
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/context/continuation.hpp>
|
||||
#include <boost/context/fiber.hpp>
|
||||
|
||||
#include <boost/coroutine2/detail/state.hpp>
|
||||
|
||||
@@ -25,7 +25,7 @@ namespace detail {
|
||||
|
||||
template< typename T >
|
||||
struct pull_coroutine< T >::control_block {
|
||||
boost::context::continuation c;
|
||||
boost::context::fiber c;
|
||||
typename push_coroutine< T >::control_block * other;
|
||||
state_t state;
|
||||
std::exception_ptr except;
|
||||
@@ -35,9 +35,9 @@ struct pull_coroutine< T >::control_block {
|
||||
static void destroy( control_block * cb) noexcept;
|
||||
|
||||
template< typename StackAllocator, typename Fn >
|
||||
control_block( context::preallocated, StackAllocator, Fn &&);
|
||||
control_block( context::preallocated, StackAllocator &&, Fn &&);
|
||||
|
||||
control_block( typename push_coroutine< T >::control_block *, boost::context::continuation &) noexcept;
|
||||
control_block( typename push_coroutine< T >::control_block *, boost::context::fiber &) noexcept;
|
||||
|
||||
~control_block();
|
||||
|
||||
@@ -50,7 +50,6 @@ struct pull_coroutine< T >::control_block {
|
||||
|
||||
void set( T const&);
|
||||
void set( T &&);
|
||||
void reset();
|
||||
|
||||
T & get() noexcept;
|
||||
|
||||
@@ -67,7 +66,7 @@ struct pull_coroutine< T & >::control_block {
|
||||
}
|
||||
};
|
||||
|
||||
boost::context::continuation c;
|
||||
boost::context::fiber c;
|
||||
typename push_coroutine< T & >::control_block * other;
|
||||
state_t state;
|
||||
std::exception_ptr except;
|
||||
@@ -77,9 +76,9 @@ struct pull_coroutine< T & >::control_block {
|
||||
static void destroy( control_block * cb) noexcept;
|
||||
|
||||
template< typename StackAllocator, typename Fn >
|
||||
control_block( context::preallocated, StackAllocator, Fn &&);
|
||||
control_block( context::preallocated, StackAllocator &&, Fn &&);
|
||||
|
||||
control_block( typename push_coroutine< T & >::control_block *, boost::context::continuation &) noexcept;
|
||||
control_block( typename push_coroutine< T & >::control_block *, boost::context::fiber &) noexcept;
|
||||
|
||||
control_block( control_block &) = delete;
|
||||
control_block & operator=( control_block &) = delete;
|
||||
@@ -89,7 +88,6 @@ struct pull_coroutine< T & >::control_block {
|
||||
void resume();
|
||||
|
||||
void set( T &);
|
||||
void reset();
|
||||
|
||||
T & get() noexcept;
|
||||
|
||||
@@ -97,7 +95,7 @@ struct pull_coroutine< T & >::control_block {
|
||||
};
|
||||
|
||||
struct pull_coroutine< void >::control_block {
|
||||
boost::context::continuation c;
|
||||
boost::context::fiber c;
|
||||
push_coroutine< void >::control_block * other;
|
||||
state_t state;
|
||||
std::exception_ptr except;
|
||||
@@ -105,9 +103,9 @@ struct pull_coroutine< void >::control_block {
|
||||
static void destroy( control_block * cb) noexcept;
|
||||
|
||||
template< typename StackAllocator, typename Fn >
|
||||
control_block( context::preallocated, StackAllocator, Fn &&);
|
||||
control_block( context::preallocated, StackAllocator &&, Fn &&);
|
||||
|
||||
control_block( push_coroutine< void >::control_block *, boost::context::continuation &) noexcept;
|
||||
control_block( push_coroutine< void >::control_block *, boost::context::fiber &) noexcept;
|
||||
|
||||
control_block( control_block &) = delete;
|
||||
control_block & operator=( control_block &) = delete;
|
||||
|
||||
@@ -14,8 +14,9 @@
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/context/detail/config.hpp>
|
||||
|
||||
#include <boost/context/continuation.hpp>
|
||||
#include <boost/context/fiber.hpp>
|
||||
|
||||
#include <boost/coroutine2/detail/config.hpp>
|
||||
#include <boost/coroutine2/detail/forced_unwind.hpp>
|
||||
@@ -34,54 +35,20 @@ namespace detail {
|
||||
template< typename T >
|
||||
void
|
||||
pull_coroutine< T >::control_block::destroy( control_block * cb) noexcept {
|
||||
boost::context::continuation c = std::move( cb->c);
|
||||
boost::context::fiber c = std::move( cb->c);
|
||||
// destroy control structure
|
||||
cb->~control_block();
|
||||
// destroy coroutine's stack
|
||||
cb->state |= state_t::destroy;
|
||||
c.resume();
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
template< typename StackAllocator, typename Fn >
|
||||
pull_coroutine< T >::control_block::control_block( context::preallocated palloc, StackAllocator salloc,
|
||||
pull_coroutine< T >::control_block::control_block( context::preallocated palloc, StackAllocator && salloc,
|
||||
Fn && fn) :
|
||||
c{},
|
||||
other{ nullptr },
|
||||
state{ state_t::unwind },
|
||||
except{},
|
||||
bvalid{ false },
|
||||
storage{} {
|
||||
#if defined(BOOST_NO_CXX14_GENERIC_LAMBDAS)
|
||||
c = boost::context::callcc(
|
||||
std::allocator_arg, palloc, salloc,
|
||||
wrap( [this](typename std::decay< Fn >::type & fn_,boost::context::continuation && c) mutable {
|
||||
// create synthesized push_coroutine< T >
|
||||
typename push_coroutine< T >::control_block synthesized_cb{ this, c };
|
||||
push_coroutine< T > synthesized{ & synthesized_cb };
|
||||
other = & synthesized_cb;
|
||||
if ( state_t::none == ( state & state_t::destroy) ) {
|
||||
try {
|
||||
auto fn = std::move( fn_);
|
||||
// call coroutine-fn with synthesized push_coroutine as argument
|
||||
fn( synthesized);
|
||||
} catch ( boost::context::detail::forced_unwind const&) {
|
||||
throw;
|
||||
} catch (...) {
|
||||
// store other exceptions in exception-pointer
|
||||
except = std::current_exception();
|
||||
}
|
||||
}
|
||||
// set termination flags
|
||||
state |= state_t::complete;
|
||||
// jump back
|
||||
return other->c.resume();
|
||||
},
|
||||
std::forward< Fn >( fn) ) );
|
||||
#else
|
||||
c = boost::context::callcc(
|
||||
std::allocator_arg, palloc, salloc,
|
||||
[this,fn_=std::forward< Fn >( fn)](boost::context::continuation && c) mutable {
|
||||
c{ std::allocator_arg, palloc, std::forward< StackAllocator >( salloc),
|
||||
wrap( [this](typename std::decay< Fn >::type & fn_,boost::context::fiber && c) mutable {
|
||||
// create synthesized push_coroutine< T >
|
||||
typename push_coroutine< T >::control_block synthesized_cb{ this, c };
|
||||
push_coroutine< T > synthesized{ & synthesized_cb };
|
||||
@@ -93,6 +60,10 @@ pull_coroutine< T >::control_block::control_block( context::preallocated palloc,
|
||||
fn( synthesized);
|
||||
} catch ( boost::context::detail::forced_unwind const&) {
|
||||
throw;
|
||||
#if defined( BOOST_CONTEXT_HAS_CXXABI_H )
|
||||
} catch ( abi::__forced_unwind const&) {
|
||||
throw;
|
||||
#endif
|
||||
} catch (...) {
|
||||
// store other exceptions in exception-pointer
|
||||
except = std::current_exception();
|
||||
@@ -101,17 +72,52 @@ pull_coroutine< T >::control_block::control_block( context::preallocated palloc,
|
||||
// set termination flags
|
||||
state |= state_t::complete;
|
||||
// jump back
|
||||
return other->c.resume();
|
||||
});
|
||||
return std::move( other->c).resume();
|
||||
},
|
||||
std::forward< Fn >( fn) ) },
|
||||
#else
|
||||
c{ std::allocator_arg, palloc, std::forward< StackAllocator >( salloc),
|
||||
[this,fn_=std::forward< Fn >( fn)](boost::context::fiber && c) mutable {
|
||||
// create synthesized push_coroutine< T >
|
||||
typename push_coroutine< T >::control_block synthesized_cb{ this, c };
|
||||
push_coroutine< T > synthesized{ & synthesized_cb };
|
||||
other = & synthesized_cb;
|
||||
if ( state_t::none == ( state & state_t::destroy) ) {
|
||||
try {
|
||||
auto fn = std::move( fn_);
|
||||
// call coroutine-fn with synthesized push_coroutine as argument
|
||||
fn( synthesized);
|
||||
} catch ( boost::context::detail::forced_unwind const&) {
|
||||
throw;
|
||||
#if defined( BOOST_CONTEXT_HAS_CXXABI_H )
|
||||
} catch ( abi::__forced_unwind const&) {
|
||||
throw;
|
||||
#endif
|
||||
if ( c.data_available() ) {
|
||||
set( c.get_data< T >() );
|
||||
}
|
||||
} catch (...) {
|
||||
// store other exceptions in exception-pointer
|
||||
except = std::current_exception();
|
||||
}
|
||||
}
|
||||
// set termination flags
|
||||
state |= state_t::complete;
|
||||
// jump back
|
||||
return std::move( other->c).resume();
|
||||
} },
|
||||
#endif
|
||||
other{ nullptr },
|
||||
state{ state_t::unwind },
|
||||
except{},
|
||||
bvalid{ false },
|
||||
storage{} {
|
||||
c = std::move( c).resume();
|
||||
if ( except) {
|
||||
std::rethrow_exception( except);
|
||||
}
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
pull_coroutine< T >::control_block::control_block( typename push_coroutine< T >::control_block * cb,
|
||||
boost::context::continuation & c_) noexcept :
|
||||
boost::context::fiber & c_) noexcept :
|
||||
c{ std::move( c_) },
|
||||
other{ cb },
|
||||
state{ state_t::none },
|
||||
@@ -139,12 +145,7 @@ pull_coroutine< T >::control_block::deallocate() noexcept {
|
||||
template< typename T >
|
||||
void
|
||||
pull_coroutine< T >::control_block::resume() {
|
||||
c = c.resume();
|
||||
if ( c.data_available() ) {
|
||||
set( c.get_data< T >() );
|
||||
} else {
|
||||
reset();
|
||||
}
|
||||
c = std::move( c).resume();
|
||||
if ( except) {
|
||||
std::rethrow_exception( except);
|
||||
}
|
||||
@@ -172,16 +173,6 @@ pull_coroutine< T >::control_block::set( T && t) {
|
||||
bvalid = true;
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
void
|
||||
pull_coroutine< T >::control_block::reset() {
|
||||
// destroy data if set
|
||||
if ( bvalid) {
|
||||
reinterpret_cast< T * >( std::addressof( storage) )->~T();
|
||||
}
|
||||
bvalid = false;
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
T &
|
||||
pull_coroutine< T >::control_block::get() noexcept {
|
||||
@@ -200,54 +191,20 @@ pull_coroutine< T >::control_block::valid() const noexcept {
|
||||
template< typename T >
|
||||
void
|
||||
pull_coroutine< T & >::control_block::destroy( control_block * cb) noexcept {
|
||||
boost::context::continuation c = std::move( cb->c);
|
||||
boost::context::fiber c = std::move( cb->c);
|
||||
// destroy control structure
|
||||
cb->~control_block();
|
||||
// destroy coroutine's stack
|
||||
cb->state |= state_t::destroy;
|
||||
c.resume();
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
template< typename StackAllocator, typename Fn >
|
||||
pull_coroutine< T & >::control_block::control_block( context::preallocated palloc, StackAllocator salloc,
|
||||
pull_coroutine< T & >::control_block::control_block( context::preallocated palloc, StackAllocator && salloc,
|
||||
Fn && fn) :
|
||||
c{},
|
||||
other{ nullptr },
|
||||
state{ state_t::unwind },
|
||||
except{},
|
||||
bvalid{ false },
|
||||
storage{} {
|
||||
#if defined(BOOST_NO_CXX14_GENERIC_LAMBDAS)
|
||||
c = boost::context::callcc(
|
||||
std::allocator_arg, palloc, salloc,
|
||||
wrap( [this](typename std::decay< Fn >::type & fn_,boost::context::continuation && c) mutable {
|
||||
// create synthesized push_coroutine< T & >
|
||||
typename push_coroutine< T & >::control_block synthesized_cb{ this, c };
|
||||
push_coroutine< T & > synthesized{ & synthesized_cb };
|
||||
other = & synthesized_cb;
|
||||
if ( state_t::none == ( state & state_t::destroy) ) {
|
||||
try {
|
||||
auto fn = std::move( fn_);
|
||||
// call coroutine-fn with synthesized push_coroutine as argument
|
||||
fn( synthesized);
|
||||
} catch ( boost::context::detail::forced_unwind const&) {
|
||||
throw;
|
||||
} catch (...) {
|
||||
// store other exceptions in exception-pointer
|
||||
except = std::current_exception();
|
||||
}
|
||||
}
|
||||
// set termination flags
|
||||
state |= state_t::complete;
|
||||
// jump back
|
||||
return other->c.resume();
|
||||
},
|
||||
std::forward< Fn >( fn) ) );
|
||||
#else
|
||||
c = boost::context::callcc(
|
||||
std::allocator_arg, palloc, salloc,
|
||||
[this,fn_=std::forward< Fn >( fn)](boost::context::continuation && c) mutable {
|
||||
c{ std::allocator_arg, palloc, std::forward< StackAllocator >( salloc),
|
||||
wrap( [this](typename std::decay< Fn >::type & fn_,boost::context::fiber && c) mutable {
|
||||
// create synthesized push_coroutine< T & >
|
||||
typename push_coroutine< T & >::control_block synthesized_cb{ this, c };
|
||||
push_coroutine< T & > synthesized{ & synthesized_cb };
|
||||
@@ -259,6 +216,10 @@ pull_coroutine< T & >::control_block::control_block( context::preallocated pallo
|
||||
fn( synthesized);
|
||||
} catch ( boost::context::detail::forced_unwind const&) {
|
||||
throw;
|
||||
#if defined( BOOST_CONTEXT_HAS_CXXABI_H )
|
||||
} catch ( abi::__forced_unwind const&) {
|
||||
throw;
|
||||
#endif
|
||||
} catch (...) {
|
||||
// store other exceptions in exception-pointer
|
||||
except = std::current_exception();
|
||||
@@ -267,17 +228,52 @@ pull_coroutine< T & >::control_block::control_block( context::preallocated pallo
|
||||
// set termination flags
|
||||
state |= state_t::complete;
|
||||
// jump back
|
||||
return other->c.resume();
|
||||
});
|
||||
return std::move( other->c).resume();
|
||||
},
|
||||
std::forward< Fn >( fn) ) },
|
||||
#else
|
||||
c{ std::allocator_arg, palloc, std::forward< StackAllocator >( salloc),
|
||||
[this,fn_=std::forward< Fn >( fn)](boost::context::fiber && c) mutable {
|
||||
// create synthesized push_coroutine< T & >
|
||||
typename push_coroutine< T & >::control_block synthesized_cb{ this, c };
|
||||
push_coroutine< T & > synthesized{ & synthesized_cb };
|
||||
other = & synthesized_cb;
|
||||
if ( state_t::none == ( state & state_t::destroy) ) {
|
||||
try {
|
||||
auto fn = std::move( fn_);
|
||||
// call coroutine-fn with synthesized push_coroutine as argument
|
||||
fn( synthesized);
|
||||
} catch ( boost::context::detail::forced_unwind const&) {
|
||||
throw;
|
||||
#if defined( BOOST_CONTEXT_HAS_CXXABI_H )
|
||||
} catch ( abi::__forced_unwind const&) {
|
||||
throw;
|
||||
#endif
|
||||
if ( c.data_available() ) {
|
||||
set( c.get_data< T & >() );
|
||||
}
|
||||
} catch (...) {
|
||||
// store other exceptions in exception-pointer
|
||||
except = std::current_exception();
|
||||
}
|
||||
}
|
||||
// set termination flags
|
||||
state |= state_t::complete;
|
||||
// jump back
|
||||
return std::move( other->c).resume();
|
||||
} },
|
||||
#endif
|
||||
other{ nullptr },
|
||||
state{ state_t::unwind },
|
||||
except{},
|
||||
bvalid{ false },
|
||||
storage{} {
|
||||
c = std::move( c).resume();
|
||||
if ( except) {
|
||||
std::rethrow_exception( except);
|
||||
}
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
pull_coroutine< T & >::control_block::control_block( typename push_coroutine< T & >::control_block * cb,
|
||||
boost::context::continuation & c_) noexcept :
|
||||
boost::context::fiber & c_) noexcept :
|
||||
c{ std::move( c_) },
|
||||
other{ cb },
|
||||
state{ state_t::none },
|
||||
@@ -297,12 +293,7 @@ pull_coroutine< T & >::control_block::deallocate() noexcept {
|
||||
template< typename T >
|
||||
void
|
||||
pull_coroutine< T & >::control_block::resume() {
|
||||
c = c.resume();
|
||||
if ( c.data_available() ) {
|
||||
set( c.get_data< T & >() );
|
||||
} else {
|
||||
reset();
|
||||
}
|
||||
c = std::move( c).resume();
|
||||
if ( except) {
|
||||
std::rethrow_exception( except);
|
||||
}
|
||||
@@ -315,15 +306,6 @@ pull_coroutine< T & >::control_block::set( T & t) {
|
||||
bvalid = true;
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
void
|
||||
pull_coroutine< T & >::control_block::reset() {
|
||||
if ( bvalid) {
|
||||
reinterpret_cast< holder * >( std::addressof( storage) )->~holder();
|
||||
}
|
||||
bvalid = false;
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
T &
|
||||
pull_coroutine< T & >::control_block::get() noexcept {
|
||||
@@ -342,51 +324,19 @@ pull_coroutine< T & >::control_block::valid() const noexcept {
|
||||
inline
|
||||
void
|
||||
pull_coroutine< void >::control_block::destroy( control_block * cb) noexcept {
|
||||
boost::context::continuation c = std::move( cb->c);
|
||||
boost::context::fiber c = std::move( cb->c);
|
||||
// destroy control structure
|
||||
cb->~control_block();
|
||||
// destroy coroutine's stack
|
||||
cb->state |= state_t::destroy;
|
||||
c.resume();
|
||||
}
|
||||
|
||||
template< typename StackAllocator, typename Fn >
|
||||
pull_coroutine< void >::control_block::control_block( context::preallocated palloc, StackAllocator salloc,
|
||||
pull_coroutine< void >::control_block::control_block( context::preallocated palloc, StackAllocator && salloc,
|
||||
Fn && fn) :
|
||||
c{},
|
||||
other{ nullptr },
|
||||
state{ state_t::unwind },
|
||||
except{} {
|
||||
#if defined(BOOST_NO_CXX14_GENERIC_LAMBDAS)
|
||||
c = boost::context::callcc(
|
||||
std::allocator_arg, palloc, salloc,
|
||||
wrap( [this](typename std::decay< Fn >::type & fn_,boost::context::continuation && c) mutable {
|
||||
// create synthesized push_coroutine< void >
|
||||
typename push_coroutine< void >::control_block synthesized_cb{ this, c };
|
||||
push_coroutine< void > synthesized{ & synthesized_cb };
|
||||
other = & synthesized_cb;
|
||||
if ( state_t::none == ( state & state_t::destroy) ) {
|
||||
try {
|
||||
auto fn = std::move( fn_);
|
||||
// call coroutine-fn with synthesized push_coroutine as argument
|
||||
fn( synthesized);
|
||||
} catch ( boost::context::detail::forced_unwind const&) {
|
||||
throw;
|
||||
} catch (...) {
|
||||
// store other exceptions in exception-pointer
|
||||
except = std::current_exception();
|
||||
}
|
||||
}
|
||||
// set termination flags
|
||||
state |= state_t::complete;
|
||||
// jump back
|
||||
return other->c.resume();
|
||||
},
|
||||
std::forward< Fn >( fn) ) );
|
||||
#else
|
||||
c = boost::context::callcc(
|
||||
std::allocator_arg, palloc, salloc,
|
||||
[this,fn_=std::forward< Fn >( fn)]( boost::context::continuation && c) mutable {
|
||||
c{ std::allocator_arg, palloc, std::forward< StackAllocator >( salloc),
|
||||
wrap( [this](typename std::decay< Fn >::type & fn_,boost::context::fiber && c) mutable {
|
||||
// create synthesized push_coroutine< void >
|
||||
typename push_coroutine< void >::control_block synthesized_cb{ this, c };
|
||||
push_coroutine< void > synthesized{ & synthesized_cb };
|
||||
@@ -398,6 +348,10 @@ pull_coroutine< void >::control_block::control_block( context::preallocated pall
|
||||
fn( synthesized);
|
||||
} catch ( boost::context::detail::forced_unwind const&) {
|
||||
throw;
|
||||
#if defined( BOOST_CONTEXT_HAS_CXXABI_H )
|
||||
} catch ( abi::__forced_unwind const&) {
|
||||
throw;
|
||||
#endif
|
||||
} catch (...) {
|
||||
// store other exceptions in exception-pointer
|
||||
except = std::current_exception();
|
||||
@@ -405,15 +359,51 @@ pull_coroutine< void >::control_block::control_block( context::preallocated pall
|
||||
}
|
||||
// set termination flags
|
||||
state |= state_t::complete;
|
||||
// jump back to ctx
|
||||
return other->c.resume();
|
||||
});
|
||||
// jump back
|
||||
return std::move( other->c).resume();
|
||||
},
|
||||
std::forward< Fn >( fn) ) },
|
||||
#else
|
||||
c{ std::allocator_arg, palloc, std::forward< StackAllocator >( salloc),
|
||||
[this,fn_=std::forward< Fn >( fn)]( boost::context::fiber && c) mutable {
|
||||
// create synthesized push_coroutine< void >
|
||||
typename push_coroutine< void >::control_block synthesized_cb{ this, c };
|
||||
push_coroutine< void > synthesized{ & synthesized_cb };
|
||||
other = & synthesized_cb;
|
||||
if ( state_t::none == ( state & state_t::destroy) ) {
|
||||
try {
|
||||
auto fn = std::move( fn_);
|
||||
// call coroutine-fn with synthesized push_coroutine as argument
|
||||
fn( synthesized);
|
||||
} catch ( boost::context::detail::forced_unwind const&) {
|
||||
throw;
|
||||
#if defined( BOOST_CONTEXT_HAS_CXXABI_H )
|
||||
} catch ( abi::__forced_unwind const&) {
|
||||
throw;
|
||||
#endif
|
||||
} catch (...) {
|
||||
// store other exceptions in exception-pointer
|
||||
except = std::current_exception();
|
||||
}
|
||||
}
|
||||
// set termination flags
|
||||
state |= state_t::complete;
|
||||
// jump back to ctx
|
||||
return std::move( other->c).resume();
|
||||
} },
|
||||
#endif
|
||||
other{ nullptr },
|
||||
state{ state_t::unwind },
|
||||
except{} {
|
||||
c = std::move( c).resume();
|
||||
if ( except) {
|
||||
std::rethrow_exception( except);
|
||||
}
|
||||
}
|
||||
|
||||
inline
|
||||
pull_coroutine< void >::control_block::control_block( push_coroutine< void >::control_block * cb,
|
||||
boost::context::continuation & c_) noexcept :
|
||||
boost::context::fiber & c_) noexcept :
|
||||
c{ std::move( c_) },
|
||||
other{ cb },
|
||||
state{ state_t::none },
|
||||
@@ -431,7 +421,7 @@ pull_coroutine< void >::control_block::deallocate() noexcept {
|
||||
inline
|
||||
void
|
||||
pull_coroutine< void >::control_block::resume() {
|
||||
c = c.resume();
|
||||
c = std::move( c).resume();
|
||||
if ( except) {
|
||||
std::rethrow_exception( except);
|
||||
}
|
||||
|
||||
@@ -1,119 +0,0 @@
|
||||
|
||||
// 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_PULL_CONTROL_BLOCK_HPP
|
||||
#define BOOST_COROUTINES2_DETAIL_PULL_CONTROL_BLOCK_HPP
|
||||
|
||||
#include <exception>
|
||||
#include <functional>
|
||||
#include <type_traits>
|
||||
|
||||
#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
|
||||
|
||||
namespace boost {
|
||||
namespace coroutines2 {
|
||||
namespace detail {
|
||||
|
||||
template< typename T >
|
||||
struct pull_coroutine< T >::control_block {
|
||||
boost::context::execution_context ctx;
|
||||
typename push_coroutine< T >::control_block * other;
|
||||
state_t state;
|
||||
std::exception_ptr except;
|
||||
bool bvalid;
|
||||
typename std::aligned_storage< sizeof( T), alignof( T) >::type storage;
|
||||
|
||||
static void destroy( control_block * cb) noexcept;
|
||||
|
||||
template< typename StackAllocator, typename Fn >
|
||||
control_block( context::preallocated, StackAllocator, Fn &&);
|
||||
|
||||
control_block( typename push_coroutine< T >::control_block *, boost::context::execution_context const&) noexcept;
|
||||
|
||||
~control_block() noexcept;
|
||||
|
||||
control_block( control_block &) = delete;
|
||||
control_block & operator=( control_block &) = delete;
|
||||
|
||||
void deallocate() noexcept;
|
||||
|
||||
void resume();
|
||||
|
||||
void set( T *);
|
||||
|
||||
T & get() noexcept;
|
||||
|
||||
bool valid() const noexcept;
|
||||
};
|
||||
|
||||
template< typename T >
|
||||
struct pull_coroutine< T & >::control_block {
|
||||
boost::context::execution_context ctx;
|
||||
typename push_coroutine< T & >::control_block * other;
|
||||
state_t state;
|
||||
std::exception_ptr except;
|
||||
T * t;
|
||||
|
||||
static void destroy( control_block * cb) noexcept;
|
||||
|
||||
template< typename StackAllocator, typename Fn >
|
||||
control_block( context::preallocated, StackAllocator, Fn &&);
|
||||
|
||||
control_block( typename push_coroutine< T & >::control_block *, boost::context::execution_context const&) noexcept;
|
||||
|
||||
~control_block() noexcept;
|
||||
|
||||
control_block( control_block &) = delete;
|
||||
control_block & operator=( control_block &) = delete;
|
||||
|
||||
void deallocate() noexcept;
|
||||
|
||||
void resume();
|
||||
|
||||
T & get() noexcept;
|
||||
|
||||
bool valid() const noexcept;
|
||||
};
|
||||
|
||||
struct pull_coroutine< void >::control_block {
|
||||
boost::context::execution_context ctx;
|
||||
push_coroutine< void >::control_block * other;
|
||||
state_t state;
|
||||
std::exception_ptr except;
|
||||
|
||||
static void destroy( control_block * cb) noexcept;
|
||||
|
||||
template< typename StackAllocator, typename Fn >
|
||||
control_block( context::preallocated, StackAllocator, Fn &&);
|
||||
|
||||
control_block( push_coroutine< void >::control_block *, boost::context::execution_context const&) noexcept;
|
||||
|
||||
~control_block() noexcept;
|
||||
|
||||
control_block( control_block &) = delete;
|
||||
control_block & operator=( control_block &) = delete;
|
||||
|
||||
void deallocate() noexcept;
|
||||
|
||||
void resume();
|
||||
|
||||
bool valid() const noexcept;
|
||||
};
|
||||
|
||||
}}}
|
||||
|
||||
#ifdef BOOST_HAS_ABI_HEADERS
|
||||
# include BOOST_ABI_SUFFIX
|
||||
#endif
|
||||
|
||||
#endif // BOOST_COROUTINES2_DETAIL_PULL_CONTROL_BLOCK_HPP
|
||||
@@ -1,431 +0,0 @@
|
||||
|
||||
// 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_PULL_CONTROL_BLOCK_IPP
|
||||
#define BOOST_COROUTINES2_DETAIL_PULL_CONTROL_BLOCK_IPP
|
||||
|
||||
#include <exception>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/config.hpp>
|
||||
|
||||
#include <boost/context/execution_context.hpp>
|
||||
|
||||
#include <boost/coroutine2/detail/config.hpp>
|
||||
#include <boost/coroutine2/detail/decay_copy.hpp>
|
||||
#include <boost/coroutine2/detail/forced_unwind.hpp>
|
||||
#include <boost/coroutine2/detail/state.hpp>
|
||||
#include <boost/coroutine2/detail/wrap.hpp>
|
||||
|
||||
#ifdef BOOST_HAS_ABI_HEADERS
|
||||
# include BOOST_ABI_PREFIX
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
namespace coroutines2 {
|
||||
namespace detail {
|
||||
|
||||
// pull_coroutine< T >
|
||||
|
||||
template< typename T >
|
||||
void
|
||||
pull_coroutine< T >::control_block::destroy( control_block * cb) noexcept {
|
||||
boost::context::execution_context ctx = cb->ctx;
|
||||
// destroy control structure
|
||||
cb->state |= state_t::destroy;
|
||||
cb->~control_block();
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
template< typename StackAllocator, typename Fn >
|
||||
pull_coroutine< T >::control_block::control_block( context::preallocated palloc, StackAllocator salloc,
|
||||
Fn && fn) :
|
||||
#if defined(BOOST_NO_CXX14_GENERIC_LAMBDAS)
|
||||
ctx{ std::allocator_arg, palloc, salloc,
|
||||
wrap( [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;
|
||||
if ( state_t::none == ( state & state_t::destroy) ) {
|
||||
try {
|
||||
auto fn = std::move( fn_);
|
||||
// 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() ) },
|
||||
#else
|
||||
ctx{ std::allocator_arg, palloc, salloc,
|
||||
[this,fn_=decay_copy( 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 };
|
||||
other = & synthesized_cb;
|
||||
if ( state_t::none == ( state & state_t::destroy) ) {
|
||||
try {
|
||||
auto fn = std::move( fn_);
|
||||
// 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");
|
||||
}},
|
||||
#endif
|
||||
other{ nullptr },
|
||||
state{ state_t::unwind },
|
||||
except{},
|
||||
bvalid{ false },
|
||||
storage{} {
|
||||
// enter coroutine-fn in order to have first value available after ctor (of `*this`) returns
|
||||
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_) noexcept :
|
||||
ctx{ ctx_ },
|
||||
other{ cb },
|
||||
state{ state_t::none },
|
||||
except{},
|
||||
bvalid{ false },
|
||||
storage{} {
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
pull_coroutine< T >::control_block::~control_block() {
|
||||
if ( state_t::none == ( state & state_t::complete) &&
|
||||
state_t::none != ( state & state_t::unwind) ) {
|
||||
// unwind coroutine stack
|
||||
other->ctx = boost::context::execution_context::current();
|
||||
ctx( context::exec_ontop_arg, unwind_coroutine);
|
||||
}
|
||||
// destroy data if it set
|
||||
if ( bvalid) {
|
||||
reinterpret_cast< T * >( std::addressof( storage) )->~T();
|
||||
}
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
void
|
||||
pull_coroutine< T >::control_block::deallocate() noexcept {
|
||||
if ( state_t::none != ( state & state_t::unwind) ) {
|
||||
destroy( this);
|
||||
}
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
void
|
||||
pull_coroutine< T >::control_block::resume() {
|
||||
other->ctx = boost::context::execution_context::current();
|
||||
set( static_cast< T * >( ctx() ) );
|
||||
if ( except) {
|
||||
std::rethrow_exception( except);
|
||||
}
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
void
|
||||
pull_coroutine< T >::control_block::set( T * t) {
|
||||
// destroy data if it set
|
||||
if ( bvalid) {
|
||||
reinterpret_cast< T * >( std::addressof( storage) )->~T();
|
||||
}
|
||||
if ( nullptr != t) {
|
||||
::new ( static_cast< void * >( std::addressof( storage) ) ) T( std::move( * t) );
|
||||
bvalid = true;
|
||||
} else {
|
||||
bvalid = false;
|
||||
}
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
T &
|
||||
pull_coroutine< T >::control_block::get() noexcept {
|
||||
return * reinterpret_cast< T * >( std::addressof( storage) );
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
bool
|
||||
pull_coroutine< T >::control_block::valid() const noexcept {
|
||||
return nullptr != other && state_t::none == ( state & state_t::complete) && bvalid;
|
||||
}
|
||||
|
||||
|
||||
// pull_coroutine< T & >
|
||||
|
||||
template< typename T >
|
||||
void
|
||||
pull_coroutine< T & >::control_block::destroy( control_block * cb) noexcept {
|
||||
boost::context::execution_context ctx = cb->ctx;
|
||||
// destroy control structure
|
||||
cb->state |= state_t::destroy;
|
||||
cb->~control_block();
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
template< typename StackAllocator, typename Fn >
|
||||
pull_coroutine< T & >::control_block::control_block( context::preallocated palloc, StackAllocator salloc,
|
||||
Fn && fn) :
|
||||
#if defined(BOOST_NO_CXX14_GENERIC_LAMBDAS)
|
||||
ctx{ std::allocator_arg, palloc, salloc,
|
||||
wrap( [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;
|
||||
if ( state_t::none == ( state & state_t::destroy) ) {
|
||||
try {
|
||||
auto fn = std::move( fn_);
|
||||
// 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() ) },
|
||||
#else
|
||||
ctx{ std::allocator_arg, palloc, salloc,
|
||||
[this,fn_=decay_copy( 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 };
|
||||
other = & synthesized_cb;
|
||||
if ( state_t::none == ( state & state_t::destroy) ) {
|
||||
try {
|
||||
auto fn = std::move( fn_);
|
||||
// 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");
|
||||
}},
|
||||
#endif
|
||||
other{ nullptr },
|
||||
state{ state_t::unwind },
|
||||
except{},
|
||||
t{ nullptr } {
|
||||
// enter coroutine-fn in order to have first value available after ctor (of `*this`) returns
|
||||
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_) noexcept :
|
||||
ctx{ ctx_ },
|
||||
other{ cb },
|
||||
state{ state_t::none },
|
||||
except{},
|
||||
t( nullptr) {
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
pull_coroutine< T & >::control_block::~control_block() {
|
||||
if ( state_t::none == ( state & state_t::complete) &&
|
||||
state_t::none != ( state & state_t::unwind) ) {
|
||||
// unwind coroutine stack
|
||||
other->ctx = boost::context::execution_context::current();
|
||||
ctx( context::exec_ontop_arg, unwind_coroutine);
|
||||
}
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
void
|
||||
pull_coroutine< T & >::control_block::deallocate() noexcept {
|
||||
if ( state_t::none != ( state & state_t::unwind) ) {
|
||||
destroy( this);
|
||||
}
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
void
|
||||
pull_coroutine< T & >::control_block::resume() {
|
||||
other->ctx = boost::context::execution_context::current();
|
||||
t = static_cast< T * >( ctx() );
|
||||
if ( except) {
|
||||
std::rethrow_exception( except);
|
||||
}
|
||||
}
|
||||
|
||||
template< typename 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 && state_t::none == ( state & state_t::complete) && nullptr != t;
|
||||
}
|
||||
|
||||
|
||||
// pull_coroutine< void >
|
||||
|
||||
inline
|
||||
void
|
||||
pull_coroutine< void >::control_block::destroy( control_block * cb) noexcept {
|
||||
boost::context::execution_context ctx = cb->ctx;
|
||||
// destroy control structure
|
||||
cb->state |= state_t::destroy;
|
||||
cb->~control_block();
|
||||
}
|
||||
|
||||
template< typename StackAllocator, typename Fn >
|
||||
pull_coroutine< void >::control_block::control_block( context::preallocated palloc, StackAllocator salloc,
|
||||
Fn && fn) :
|
||||
#if defined(BOOST_NO_CXX14_GENERIC_LAMBDAS)
|
||||
ctx{ std::allocator_arg, palloc, salloc,
|
||||
wrap( [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;
|
||||
if ( state_t::none == ( state & state_t::destroy) ) {
|
||||
try {
|
||||
auto fn = std::move( fn_);
|
||||
// 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() ) },
|
||||
#else
|
||||
ctx{ std::allocator_arg, palloc, salloc,
|
||||
[this,fn_=decay_copy( 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 };
|
||||
other = & synthesized_cb;
|
||||
if ( state_t::none == ( state & state_t::destroy) ) {
|
||||
try {
|
||||
auto fn = std::move( fn_);
|
||||
// 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");
|
||||
}},
|
||||
#endif
|
||||
other{ nullptr },
|
||||
state{ state_t::unwind },
|
||||
except{} {
|
||||
// enter coroutine-fn in order to have first value available after ctor returns
|
||||
ctx();
|
||||
}
|
||||
|
||||
inline
|
||||
pull_coroutine< void >::control_block::control_block( push_coroutine< void >::control_block * cb,
|
||||
boost::context::execution_context const& ctx_) noexcept :
|
||||
ctx{ ctx_ },
|
||||
other{ cb },
|
||||
state{ state_t::none },
|
||||
except{} {
|
||||
}
|
||||
|
||||
inline
|
||||
pull_coroutine< void >::control_block::~control_block() {
|
||||
if ( state_t::none == ( state & state_t::complete) &&
|
||||
state_t::none != ( state & state_t::unwind) ) {
|
||||
// unwind coroutine stack
|
||||
other->ctx = boost::context::execution_context::current();
|
||||
ctx( context::exec_ontop_arg, unwind_coroutine);
|
||||
}
|
||||
}
|
||||
|
||||
inline
|
||||
void
|
||||
pull_coroutine< void >::control_block::deallocate() noexcept {
|
||||
if ( state_t::none != ( state & state_t::unwind) ) {
|
||||
destroy( this);
|
||||
}
|
||||
}
|
||||
|
||||
inline
|
||||
void
|
||||
pull_coroutine< void >::control_block::resume() {
|
||||
other->ctx = boost::context::execution_context::current();
|
||||
ctx();
|
||||
if ( except) {
|
||||
std::rethrow_exception( except);
|
||||
}
|
||||
}
|
||||
|
||||
inline
|
||||
bool
|
||||
pull_coroutine< void >::control_block::valid() const noexcept {
|
||||
return nullptr != other && state_t::none == ( state & state_t::complete);
|
||||
}
|
||||
|
||||
}}}
|
||||
|
||||
#ifdef BOOST_HAS_ABI_HEADERS
|
||||
# include BOOST_ABI_SUFFIX
|
||||
#endif
|
||||
|
||||
#endif // BOOST_COROUTINES2_DETAIL_PULL_CONTROL_BLOCK_IPP
|
||||
@@ -45,7 +45,7 @@ public:
|
||||
explicit pull_coroutine( Fn &&);
|
||||
|
||||
template< typename StackAllocator, typename Fn >
|
||||
pull_coroutine( StackAllocator, Fn &&);
|
||||
pull_coroutine( StackAllocator &&, Fn &&);
|
||||
|
||||
~pull_coroutine();
|
||||
|
||||
@@ -55,9 +55,7 @@ public:
|
||||
pull_coroutine( pull_coroutine &&) noexcept;
|
||||
|
||||
pull_coroutine & operator=( pull_coroutine && other) noexcept {
|
||||
if ( this == & other) return * this;
|
||||
cb_ = other.cb_;
|
||||
other.cb_ = nullptr;
|
||||
std::swap( cb_, other.cb_);
|
||||
return * this;
|
||||
}
|
||||
|
||||
@@ -69,7 +67,7 @@ public:
|
||||
|
||||
T get() noexcept;
|
||||
|
||||
class iterator : public std::iterator< std::input_iterator_tag, typename std::remove_reference< T >::type > {
|
||||
class iterator {
|
||||
private:
|
||||
pull_coroutine< T > * c_{ nullptr };
|
||||
|
||||
@@ -89,8 +87,14 @@ public:
|
||||
}
|
||||
|
||||
public:
|
||||
typedef typename iterator::pointer pointer_t;
|
||||
typedef typename iterator::reference reference_t;
|
||||
typedef std::input_iterator_tag iterator_category;
|
||||
typedef typename std::remove_reference< T >::type value_type;
|
||||
typedef std::ptrdiff_t difference_type;
|
||||
typedef value_type * pointer;
|
||||
typedef value_type & reference;
|
||||
|
||||
typedef pointer pointer_t;
|
||||
typedef reference reference_t;
|
||||
|
||||
iterator() noexcept = default;
|
||||
|
||||
@@ -99,16 +103,6 @@ public:
|
||||
fetch_();
|
||||
}
|
||||
|
||||
iterator( iterator const& other) noexcept :
|
||||
c_{ other.c_ } {
|
||||
}
|
||||
|
||||
iterator & operator=( iterator const& other) noexcept {
|
||||
if ( this == & other) return * this;
|
||||
c_ = other.c_;
|
||||
return * this;
|
||||
}
|
||||
|
||||
bool operator==( iterator const& other) const noexcept {
|
||||
return other.c_ == c_;
|
||||
}
|
||||
@@ -122,7 +116,9 @@ public:
|
||||
return * this;
|
||||
}
|
||||
|
||||
iterator operator++( int) = delete;
|
||||
void operator++( int) {
|
||||
increment_();
|
||||
}
|
||||
|
||||
reference_t operator*() const noexcept {
|
||||
return c_->cb_->get();
|
||||
@@ -157,7 +153,7 @@ public:
|
||||
explicit pull_coroutine( Fn &&);
|
||||
|
||||
template< typename StackAllocator, typename Fn >
|
||||
pull_coroutine( StackAllocator, Fn &&);
|
||||
pull_coroutine( StackAllocator &&, Fn &&);
|
||||
|
||||
~pull_coroutine();
|
||||
|
||||
@@ -167,9 +163,7 @@ public:
|
||||
pull_coroutine( pull_coroutine &&) noexcept;
|
||||
|
||||
pull_coroutine & operator=( pull_coroutine && other) noexcept {
|
||||
if ( this == & other) return * this;
|
||||
cb_ = other.cb_;
|
||||
other.cb_ = nullptr;
|
||||
std::swap( cb_, other.cb_);
|
||||
return * this;
|
||||
}
|
||||
|
||||
@@ -181,7 +175,7 @@ public:
|
||||
|
||||
T & get() noexcept;
|
||||
|
||||
class iterator : public std::iterator< std::input_iterator_tag, typename std::remove_reference< T >::type > {
|
||||
class iterator {
|
||||
private:
|
||||
pull_coroutine< T & > * c_{ nullptr };
|
||||
|
||||
@@ -201,8 +195,14 @@ public:
|
||||
}
|
||||
|
||||
public:
|
||||
typedef typename iterator::pointer pointer_t;
|
||||
typedef typename iterator::reference reference_t;
|
||||
typedef std::input_iterator_tag iterator_category;
|
||||
typedef typename std::remove_reference< T >::type value_type;
|
||||
typedef std::ptrdiff_t difference_type;
|
||||
typedef value_type * pointer;
|
||||
typedef value_type & reference;
|
||||
|
||||
typedef pointer pointer_t;
|
||||
typedef reference reference_t;
|
||||
|
||||
iterator() noexcept = default;
|
||||
|
||||
@@ -211,16 +211,6 @@ public:
|
||||
fetch_();
|
||||
}
|
||||
|
||||
iterator( iterator const& other) noexcept :
|
||||
c_{ other.c_ } {
|
||||
}
|
||||
|
||||
iterator & operator=( iterator const& other) noexcept {
|
||||
if ( this == & other) return * this;
|
||||
c_ = other.c_;
|
||||
return * this;
|
||||
}
|
||||
|
||||
bool operator==( iterator const& other) const noexcept {
|
||||
return other.c_ == c_;
|
||||
}
|
||||
@@ -234,7 +224,9 @@ public:
|
||||
return * this;
|
||||
}
|
||||
|
||||
iterator operator++( int) = delete;
|
||||
void operator++( int) {
|
||||
increment_();
|
||||
}
|
||||
|
||||
reference_t operator*() const noexcept {
|
||||
return c_->cb_->get();
|
||||
@@ -267,7 +259,7 @@ public:
|
||||
explicit pull_coroutine( Fn &&);
|
||||
|
||||
template< typename StackAllocator, typename Fn >
|
||||
pull_coroutine( StackAllocator, Fn &&);
|
||||
pull_coroutine( StackAllocator &&, Fn &&);
|
||||
|
||||
~pull_coroutine();
|
||||
|
||||
@@ -277,9 +269,7 @@ public:
|
||||
pull_coroutine( pull_coroutine &&) noexcept;
|
||||
|
||||
pull_coroutine & operator=( pull_coroutine && other) noexcept {
|
||||
if ( this == & other) return * this;
|
||||
cb_ = other.cb_;
|
||||
other.cb_ = nullptr;
|
||||
std::swap( cb_, other.cb_);
|
||||
return * this;
|
||||
}
|
||||
|
||||
|
||||
@@ -50,8 +50,8 @@ pull_coroutine< T >::pull_coroutine( Fn && fn) :
|
||||
|
||||
template< typename T >
|
||||
template< typename StackAllocator, typename Fn >
|
||||
pull_coroutine< T >::pull_coroutine( StackAllocator salloc, Fn && fn) :
|
||||
cb_{ create_control_block< control_block >( salloc, std::forward< Fn >( fn) ) } {
|
||||
pull_coroutine< T >::pull_coroutine( StackAllocator && salloc, Fn && fn) :
|
||||
cb_{ create_control_block< control_block >( std::forward< StackAllocator >( salloc), std::forward< Fn >( fn) ) } {
|
||||
if ( ! cb_->valid() ) {
|
||||
cb_->deallocate();
|
||||
cb_ = nullptr;
|
||||
@@ -67,8 +67,8 @@ pull_coroutine< T >::~pull_coroutine() {
|
||||
|
||||
template< typename T >
|
||||
pull_coroutine< T >::pull_coroutine( pull_coroutine && other) noexcept :
|
||||
cb_{ other.cb_ } {
|
||||
other.cb_ = nullptr;
|
||||
cb_{ nullptr } {
|
||||
std::swap( cb_, other.cb_);
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
@@ -119,8 +119,8 @@ pull_coroutine< T & >::pull_coroutine( Fn && fn) :
|
||||
|
||||
template< typename T >
|
||||
template< typename StackAllocator, typename Fn >
|
||||
pull_coroutine< T & >::pull_coroutine( StackAllocator salloc, Fn && fn) :
|
||||
cb_{ create_control_block< control_block >( salloc, std::forward< Fn >( fn) ) } {
|
||||
pull_coroutine< T & >::pull_coroutine( StackAllocator && salloc, Fn && fn) :
|
||||
cb_{ create_control_block< control_block >( std::forward< StackAllocator >( salloc), std::forward< Fn >( fn) ) } {
|
||||
if ( ! cb_->valid() ) {
|
||||
cb_->deallocate();
|
||||
cb_ = nullptr;
|
||||
@@ -136,8 +136,8 @@ pull_coroutine< T & >::~pull_coroutine() {
|
||||
|
||||
template< typename T >
|
||||
pull_coroutine< T & >::pull_coroutine( pull_coroutine && other) noexcept :
|
||||
cb_{ other.cb_ } {
|
||||
other.cb_ = nullptr;
|
||||
cb_{ nullptr } {
|
||||
std::swap( cb_, other.cb_);
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
@@ -180,8 +180,8 @@ pull_coroutine< void >::pull_coroutine( Fn && fn) :
|
||||
}
|
||||
|
||||
template< typename StackAllocator, typename Fn >
|
||||
pull_coroutine< void >::pull_coroutine( StackAllocator salloc, Fn && fn) :
|
||||
cb_{ create_control_block< control_block >( salloc, std::forward< Fn >( fn) ) } {
|
||||
pull_coroutine< void >::pull_coroutine( StackAllocator && salloc, Fn && fn) :
|
||||
cb_{ create_control_block< control_block >( std::forward< StackAllocator >( salloc), std::forward< Fn >( fn) ) } {
|
||||
if ( ! cb_->valid() ) {
|
||||
cb_->deallocate();
|
||||
cb_ = nullptr;
|
||||
@@ -197,8 +197,8 @@ pull_coroutine< void >::~pull_coroutine() {
|
||||
|
||||
inline
|
||||
pull_coroutine< void >::pull_coroutine( pull_coroutine && other) noexcept :
|
||||
cb_{ other.cb_ } {
|
||||
other.cb_ = nullptr;
|
||||
cb_{ nullptr } {
|
||||
std::swap( cb_, other.cb_);
|
||||
}
|
||||
|
||||
inline
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
#include <exception>
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/context/continuation.hpp>
|
||||
#include <boost/context/fiber.hpp>
|
||||
|
||||
#include <boost/coroutine2/detail/state.hpp>
|
||||
|
||||
@@ -24,7 +24,7 @@ namespace detail {
|
||||
|
||||
template< typename T >
|
||||
struct push_coroutine< T >::control_block {
|
||||
boost::context::continuation c;
|
||||
boost::context::fiber c;
|
||||
typename pull_coroutine< T >::control_block * other;
|
||||
state_t state;
|
||||
std::exception_ptr except;
|
||||
@@ -32,9 +32,9 @@ struct push_coroutine< T >::control_block {
|
||||
static void destroy( control_block * cb) noexcept;
|
||||
|
||||
template< typename StackAllocator, typename Fn >
|
||||
control_block( context::preallocated, StackAllocator, Fn &&);
|
||||
control_block( context::preallocated, StackAllocator &&, Fn &&);
|
||||
|
||||
control_block( typename pull_coroutine< T >::control_block *, boost::context::continuation &) noexcept;
|
||||
control_block( typename pull_coroutine< T >::control_block *, boost::context::fiber &) noexcept;
|
||||
|
||||
control_block( control_block &) = delete;
|
||||
control_block & operator=( control_block &) = delete;
|
||||
@@ -50,7 +50,7 @@ struct push_coroutine< T >::control_block {
|
||||
|
||||
template< typename T >
|
||||
struct push_coroutine< T & >::control_block {
|
||||
boost::context::continuation c;
|
||||
boost::context::fiber c;
|
||||
typename pull_coroutine< T & >::control_block * other;
|
||||
state_t state;
|
||||
std::exception_ptr except;
|
||||
@@ -58,9 +58,9 @@ struct push_coroutine< T & >::control_block {
|
||||
static void destroy( control_block * cb) noexcept;
|
||||
|
||||
template< typename StackAllocator, typename Fn >
|
||||
control_block( context::preallocated, StackAllocator, Fn &&);
|
||||
control_block( context::preallocated, StackAllocator &&, Fn &&);
|
||||
|
||||
control_block( typename pull_coroutine< T & >::control_block *, boost::context::continuation &) noexcept;
|
||||
control_block( typename pull_coroutine< T & >::control_block *, boost::context::fiber &) noexcept;
|
||||
|
||||
control_block( control_block &) = delete;
|
||||
control_block & operator=( control_block &) = delete;
|
||||
@@ -73,7 +73,7 @@ struct push_coroutine< T & >::control_block {
|
||||
};
|
||||
|
||||
struct push_coroutine< void >::control_block {
|
||||
boost::context::continuation c;
|
||||
boost::context::fiber c;
|
||||
pull_coroutine< void >::control_block * other;
|
||||
state_t state;
|
||||
std::exception_ptr except;
|
||||
@@ -81,9 +81,9 @@ struct push_coroutine< void >::control_block {
|
||||
static void destroy( control_block * cb) noexcept;
|
||||
|
||||
template< typename StackAllocator, typename Fn >
|
||||
control_block( context::preallocated, StackAllocator, Fn &&);
|
||||
control_block( context::preallocated, StackAllocator &&, Fn &&);
|
||||
|
||||
control_block( pull_coroutine< void >::control_block *, boost::context::continuation &) noexcept;
|
||||
control_block( pull_coroutine< void >::control_block *, boost::context::fiber &) noexcept;
|
||||
|
||||
control_block( control_block &) = delete;
|
||||
control_block & operator=( control_block &) = delete;
|
||||
|
||||
@@ -13,8 +13,9 @@
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/context/detail/config.hpp>
|
||||
|
||||
#include <boost/context/continuation.hpp>
|
||||
#include <boost/context/fiber.hpp>
|
||||
|
||||
#include <boost/coroutine2/detail/config.hpp>
|
||||
#include <boost/coroutine2/detail/forced_unwind.hpp>
|
||||
@@ -33,70 +34,25 @@ namespace detail {
|
||||
template< typename T >
|
||||
void
|
||||
push_coroutine< T >::control_block::destroy( control_block * cb) noexcept {
|
||||
boost::context::continuation c = std::move( cb->c);
|
||||
boost::context::fiber c = std::move( cb->c);
|
||||
// destroy control structure
|
||||
cb->~control_block();
|
||||
// destroy coroutine's stack
|
||||
cb->state |= state_t::destroy;
|
||||
c.resume();
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
template< typename StackAllocator, typename Fn >
|
||||
push_coroutine< T >::control_block::control_block( context::preallocated palloc, StackAllocator salloc,
|
||||
push_coroutine< T >::control_block::control_block( context::preallocated palloc, StackAllocator && salloc,
|
||||
Fn && fn) :
|
||||
c{},
|
||||
other{ nullptr },
|
||||
state{ state_t::unwind },
|
||||
except{} {
|
||||
#if defined(BOOST_NO_CXX14_GENERIC_LAMBDAS)
|
||||
c = boost::context::callcc(
|
||||
std::allocator_arg, palloc, salloc,
|
||||
wrap( [this](typename std::decay< Fn >::type & fn_,boost::context::continuation && c) mutable {
|
||||
// create synthesized pull_coroutine< T >
|
||||
typename pull_coroutine< T >::control_block synthesized_cb{ this, c };
|
||||
pull_coroutine< T > synthesized{ & synthesized_cb };
|
||||
other = & synthesized_cb;
|
||||
other->c = other->c.resume();
|
||||
// set transferred value
|
||||
if ( other->c.data_available() ) {
|
||||
synthesized_cb.set( other->c.template get_data< T >() );
|
||||
} else {
|
||||
synthesized_cb.reset();
|
||||
}
|
||||
if ( state_t::none == ( state & state_t::destroy) ) {
|
||||
try {
|
||||
auto fn = std::move( fn_);
|
||||
// call coroutine-fn with synthesized pull_coroutine as argument
|
||||
fn( synthesized);
|
||||
} catch ( boost::context::detail::forced_unwind const&) {
|
||||
throw;
|
||||
} catch (...) {
|
||||
// store other exceptions in exception-pointer
|
||||
except = std::current_exception();
|
||||
}
|
||||
}
|
||||
// set termination flags
|
||||
state |= state_t::complete;
|
||||
// jump back
|
||||
return other->c.resume();
|
||||
},
|
||||
std::forward< Fn >( fn) ) );
|
||||
#else
|
||||
c = boost::context::callcc(
|
||||
std::allocator_arg, palloc, salloc,
|
||||
[this,fn_=std::forward< Fn >( fn)](boost::context::continuation && c) mutable {
|
||||
c{ std::allocator_arg, palloc, std::forward< StackAllocator >( salloc),
|
||||
wrap( [this](typename std::decay< Fn >::type & fn_,boost::context::fiber && c) mutable {
|
||||
// create synthesized pull_coroutine< T >
|
||||
typename pull_coroutine< T >::control_block synthesized_cb{ this, c };
|
||||
pull_coroutine< T > synthesized{ & synthesized_cb };
|
||||
other = & synthesized_cb;
|
||||
other->c = other->c.resume();
|
||||
// set transferred value
|
||||
if ( other->c.data_available() ) {
|
||||
synthesized_cb.set( other->c.template get_data< T >() );
|
||||
} else {
|
||||
synthesized_cb.reset();
|
||||
}
|
||||
other->c = std::move( other->c).resume();
|
||||
if ( state_t::none == ( state & state_t::destroy) ) {
|
||||
try {
|
||||
auto fn = std::move( fn_);
|
||||
@@ -104,6 +60,10 @@ push_coroutine< T >::control_block::control_block( context::preallocated palloc,
|
||||
fn( synthesized);
|
||||
} catch ( boost::context::detail::forced_unwind const&) {
|
||||
throw;
|
||||
#if defined( BOOST_CONTEXT_HAS_CXXABI_H )
|
||||
} catch ( abi::__forced_unwind const&) {
|
||||
throw;
|
||||
#endif
|
||||
} catch (...) {
|
||||
// store other exceptions in exception-pointer
|
||||
except = std::current_exception();
|
||||
@@ -112,14 +72,49 @@ push_coroutine< T >::control_block::control_block( context::preallocated palloc,
|
||||
// set termination flags
|
||||
state |= state_t::complete;
|
||||
// jump back
|
||||
return other->c.resume();
|
||||
});
|
||||
other->c = std::move( other->c).resume();
|
||||
return std::move( other->c);
|
||||
},
|
||||
std::forward< Fn >( fn) ) },
|
||||
#else
|
||||
c{ std::allocator_arg, palloc, std::forward< StackAllocator >( salloc),
|
||||
[this,fn_=std::forward< Fn >( fn)](boost::context::fiber && c) mutable {
|
||||
// create synthesized pull_coroutine< T >
|
||||
typename pull_coroutine< T >::control_block synthesized_cb{ this, c };
|
||||
pull_coroutine< T > synthesized{ & synthesized_cb };
|
||||
other = & synthesized_cb;
|
||||
other->c = std::move( other->c).resume();
|
||||
if ( state_t::none == ( state & state_t::destroy) ) {
|
||||
try {
|
||||
auto fn = std::move( fn_);
|
||||
// call coroutine-fn with synthesized pull_coroutine as argument
|
||||
fn( synthesized);
|
||||
} catch ( boost::context::detail::forced_unwind const&) {
|
||||
throw;
|
||||
#if defined( BOOST_CONTEXT_HAS_CXXABI_H )
|
||||
} catch ( abi::__forced_unwind const&) {
|
||||
throw;
|
||||
#endif
|
||||
} catch (...) {
|
||||
// store other exceptions in exception-pointer
|
||||
except = std::current_exception();
|
||||
}
|
||||
}
|
||||
// set termination flags
|
||||
state |= state_t::complete;
|
||||
// jump back
|
||||
return std::move( other->c).resume();
|
||||
} },
|
||||
#endif
|
||||
other{ nullptr },
|
||||
state{ state_t::unwind },
|
||||
except{} {
|
||||
c = std::move( c).resume();
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
push_coroutine< T >::control_block::control_block( typename pull_coroutine< T >::control_block * cb,
|
||||
boost::context::continuation & c_) noexcept :
|
||||
boost::context::fiber & c_) noexcept :
|
||||
c{ std::move( c_) },
|
||||
other{ cb },
|
||||
state{ state_t::none },
|
||||
@@ -137,8 +132,10 @@ push_coroutine< T >::control_block::deallocate() noexcept {
|
||||
template< typename T >
|
||||
void
|
||||
push_coroutine< T >::control_block::resume( T const& data) {
|
||||
// pass an pointer to other context
|
||||
c = c.resume( data);
|
||||
// pass data to other context
|
||||
other->set( data);
|
||||
// resume other context
|
||||
c = std::move( c).resume();
|
||||
if ( except) {
|
||||
std::rethrow_exception( except);
|
||||
}
|
||||
@@ -147,8 +144,10 @@ push_coroutine< T >::control_block::resume( T const& data) {
|
||||
template< typename T >
|
||||
void
|
||||
push_coroutine< T >::control_block::resume( T && data) {
|
||||
// pass an pointer to other context
|
||||
c = c.resume( std::move( data) );
|
||||
// pass data to other context
|
||||
other->set( std::move( data) );
|
||||
// resume other context
|
||||
c = std::move( c).resume();
|
||||
if ( except) {
|
||||
std::rethrow_exception( except);
|
||||
}
|
||||
@@ -166,70 +165,25 @@ push_coroutine< T >::control_block::valid() const noexcept {
|
||||
template< typename T >
|
||||
void
|
||||
push_coroutine< T & >::control_block::destroy( control_block * cb) noexcept {
|
||||
boost::context::continuation c = std::move( cb->c);
|
||||
boost::context::fiber c = std::move( cb->c);
|
||||
// destroy control structure
|
||||
cb->~control_block();
|
||||
// destroy coroutine's stack
|
||||
cb->state |= state_t::destroy;
|
||||
c.resume();
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
template< typename StackAllocator, typename Fn >
|
||||
push_coroutine< T & >::control_block::control_block( context::preallocated palloc, StackAllocator salloc,
|
||||
push_coroutine< T & >::control_block::control_block( context::preallocated palloc, StackAllocator && salloc,
|
||||
Fn && fn) :
|
||||
c{},
|
||||
other{ nullptr },
|
||||
state{ state_t::unwind },
|
||||
except{} {
|
||||
#if defined(BOOST_NO_CXX14_GENERIC_LAMBDAS)
|
||||
c = boost::context::callcc(
|
||||
std::allocator_arg, palloc, salloc,
|
||||
wrap( [this](typename std::decay< Fn >::type & fn_,boost::context::continuation && c) mutable {
|
||||
// create synthesized pull_coroutine< T & >
|
||||
typename pull_coroutine< T & >::control_block synthesized_cb{ this, c };
|
||||
pull_coroutine< T & > synthesized{ & synthesized_cb };
|
||||
other = & synthesized_cb;
|
||||
other->c = other->c.resume();
|
||||
// set transferred value
|
||||
if ( other->c.data_available() ) {
|
||||
synthesized_cb.set( other->c.template get_data< T & >() );
|
||||
} else {
|
||||
synthesized_cb.reset();
|
||||
}
|
||||
if ( state_t::none == ( state & state_t::destroy) ) {
|
||||
try {
|
||||
auto fn = std::move( fn_);
|
||||
// call coroutine-fn with synthesized pull_coroutine as argument
|
||||
fn( synthesized);
|
||||
} catch ( boost::context::detail::forced_unwind const&) {
|
||||
throw;
|
||||
} catch (...) {
|
||||
// store other exceptions in exception-pointer
|
||||
except = std::current_exception();
|
||||
}
|
||||
}
|
||||
// set termination flags
|
||||
state |= state_t::complete;
|
||||
// jump back
|
||||
return other->c.resume();
|
||||
},
|
||||
std::forward< Fn >( fn) ) );
|
||||
#else
|
||||
c = boost::context::callcc(
|
||||
std::allocator_arg, palloc, salloc,
|
||||
[this,fn_=std::forward< Fn >( fn)](boost::context::continuation && c) mutable {
|
||||
c{ std::allocator_arg, palloc, std::forward< StackAllocator >( salloc),
|
||||
wrap( [this](typename std::decay< Fn >::type & fn_,boost::context::fiber && c) mutable {
|
||||
// create synthesized pull_coroutine< T & >
|
||||
typename pull_coroutine< T & >::control_block synthesized_cb{ this, c };
|
||||
pull_coroutine< T & > synthesized{ & synthesized_cb };
|
||||
other = & synthesized_cb;
|
||||
other->c = other->c.resume();
|
||||
// set transferred value
|
||||
if ( other->c.data_available() ) {
|
||||
synthesized_cb.set( other->c.template get_data< T & >() );
|
||||
} else {
|
||||
synthesized_cb.reset();
|
||||
}
|
||||
other->c = std::move( other->c).resume();
|
||||
if ( state_t::none == ( state & state_t::destroy) ) {
|
||||
try {
|
||||
auto fn = std::move( fn_);
|
||||
@@ -237,6 +191,10 @@ push_coroutine< T & >::control_block::control_block( context::preallocated pallo
|
||||
fn( synthesized);
|
||||
} catch ( boost::context::detail::forced_unwind const&) {
|
||||
throw;
|
||||
#if defined( BOOST_CONTEXT_HAS_CXXABI_H )
|
||||
} catch ( abi::__forced_unwind const&) {
|
||||
throw;
|
||||
#endif
|
||||
} catch (...) {
|
||||
// store other exceptions in exception-pointer
|
||||
except = std::current_exception();
|
||||
@@ -245,14 +203,50 @@ push_coroutine< T & >::control_block::control_block( context::preallocated pallo
|
||||
// set termination flags
|
||||
state |= state_t::complete;
|
||||
// jump back
|
||||
return other->c.resume();
|
||||
});
|
||||
other->c = std::move( other->c).resume();
|
||||
return std::move( other->c);
|
||||
},
|
||||
std::forward< Fn >( fn) ) },
|
||||
#else
|
||||
c{ std::allocator_arg, palloc, std::forward< StackAllocator >( salloc),
|
||||
[this,fn_=std::forward< Fn >( fn)](boost::context::fiber && c) mutable {
|
||||
// create synthesized pull_coroutine< T & >
|
||||
typename pull_coroutine< T & >::control_block synthesized_cb{ this, c };
|
||||
pull_coroutine< T & > synthesized{ & synthesized_cb };
|
||||
other = & synthesized_cb;
|
||||
other->c = std::move( other->c).resume();
|
||||
if ( state_t::none == ( state & state_t::destroy) ) {
|
||||
try {
|
||||
auto fn = std::move( fn_);
|
||||
// call coroutine-fn with synthesized pull_coroutine as argument
|
||||
fn( synthesized);
|
||||
} catch ( boost::context::detail::forced_unwind const&) {
|
||||
throw;
|
||||
#if defined( BOOST_CONTEXT_HAS_CXXABI_H )
|
||||
} catch ( abi::__forced_unwind const&) {
|
||||
throw;
|
||||
#endif
|
||||
} catch (...) {
|
||||
// store other exceptions in exception-pointer
|
||||
except = std::current_exception();
|
||||
}
|
||||
}
|
||||
// set termination flags
|
||||
state |= state_t::complete;
|
||||
// jump back
|
||||
other->c = std::move( other->c).resume();
|
||||
return std::move( other->c);
|
||||
} },
|
||||
#endif
|
||||
other{ nullptr },
|
||||
state{ state_t::unwind },
|
||||
except{} {
|
||||
c = std::move( c).resume();
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
push_coroutine< T & >::control_block::control_block( typename pull_coroutine< T & >::control_block * cb,
|
||||
boost::context::continuation & c_) noexcept :
|
||||
boost::context::fiber & c_) noexcept :
|
||||
c{ std::move( c_) },
|
||||
other{ cb },
|
||||
state{ state_t::none },
|
||||
@@ -269,9 +263,11 @@ push_coroutine< T & >::control_block::deallocate() noexcept {
|
||||
|
||||
template< typename T >
|
||||
void
|
||||
push_coroutine< T & >::control_block::resume( T & t) {
|
||||
// pass an pointer to other context
|
||||
c = c.resume( std::ref( t) );
|
||||
push_coroutine< T & >::control_block::resume( T & data) {
|
||||
// pass data to other context
|
||||
other->set( data);
|
||||
// resume other context
|
||||
c = std::move( c).resume();
|
||||
if ( except) {
|
||||
std::rethrow_exception( except);
|
||||
}
|
||||
@@ -289,56 +285,23 @@ push_coroutine< T & >::control_block::valid() const noexcept {
|
||||
inline
|
||||
void
|
||||
push_coroutine< void >::control_block::destroy( control_block * cb) noexcept {
|
||||
boost::context::continuation c = std::move( cb->c);
|
||||
boost::context::fiber c = std::move( cb->c);
|
||||
// destroy control structure
|
||||
cb->~control_block();
|
||||
// destroy coroutine's stack
|
||||
cb->state |= state_t::destroy;
|
||||
c.resume();
|
||||
}
|
||||
|
||||
template< typename StackAllocator, typename Fn >
|
||||
push_coroutine< void >::control_block::control_block( context::preallocated palloc, StackAllocator salloc, Fn && fn) :
|
||||
c{},
|
||||
other{ nullptr },
|
||||
state{ state_t::unwind },
|
||||
except{} {
|
||||
push_coroutine< void >::control_block::control_block( context::preallocated palloc, StackAllocator && salloc, Fn && fn) :
|
||||
#if defined(BOOST_NO_CXX14_GENERIC_LAMBDAS)
|
||||
c = boost::context::callcc(
|
||||
std::allocator_arg, palloc, salloc,
|
||||
wrap( [this](typename std::decay< Fn >::type & fn_,boost::context::continuation && c) mutable {
|
||||
// create synthesized pull_coroutine< void >
|
||||
typename pull_coroutine< void >::control_block synthesized_cb{ this, c };
|
||||
pull_coroutine< void > synthesized{ & synthesized_cb };
|
||||
other = & synthesized_cb;
|
||||
other->c = other->c.resume();
|
||||
if ( state_t::none == ( state & state_t::destroy) ) {
|
||||
try {
|
||||
auto fn = std::move( fn_);
|
||||
// call coroutine-fn with synthesized pull_coroutine as argument
|
||||
fn( synthesized);
|
||||
} catch ( boost::context::detail::forced_unwind const&) {
|
||||
throw;
|
||||
} catch (...) {
|
||||
// store other exceptions in exception-pointer
|
||||
except = std::current_exception();
|
||||
}
|
||||
}
|
||||
// set termination flags
|
||||
state |= state_t::complete;
|
||||
// jump back
|
||||
return other->c.resume();
|
||||
},
|
||||
std::forward< Fn >( fn) ) );
|
||||
#else
|
||||
c = boost::context::callcc(
|
||||
std::allocator_arg, palloc, salloc,
|
||||
[this,fn_=std::forward< Fn >( fn)](boost::context::continuation && c) mutable {
|
||||
c{ std::allocator_arg, palloc, std::forward< StackAllocator >( salloc),
|
||||
wrap( [this](typename std::decay< Fn >::type & fn_,boost::context::fiber && c) mutable {
|
||||
// create synthesized pull_coroutine< void >
|
||||
typename pull_coroutine< void >::control_block synthesized_cb{ this, c};
|
||||
typename pull_coroutine< void >::control_block synthesized_cb{ this, c };
|
||||
pull_coroutine< void > synthesized{ & synthesized_cb };
|
||||
other = & synthesized_cb;
|
||||
other->c = other->c.resume();
|
||||
other->c = std::move( other->c).resume();
|
||||
if ( state_t::none == ( state & state_t::destroy) ) {
|
||||
try {
|
||||
auto fn = std::move( fn_);
|
||||
@@ -346,6 +309,10 @@ push_coroutine< void >::control_block::control_block( context::preallocated pall
|
||||
fn( synthesized);
|
||||
} catch ( boost::context::detail::forced_unwind const&) {
|
||||
throw;
|
||||
#if defined( BOOST_CONTEXT_HAS_CXXABI_H )
|
||||
} catch ( abi::__forced_unwind const&) {
|
||||
throw;
|
||||
#endif
|
||||
} catch (...) {
|
||||
// store other exceptions in exception-pointer
|
||||
except = std::current_exception();
|
||||
@@ -354,14 +321,50 @@ push_coroutine< void >::control_block::control_block( context::preallocated pall
|
||||
// set termination flags
|
||||
state |= state_t::complete;
|
||||
// jump back
|
||||
return other->c.resume();
|
||||
});
|
||||
other->c = std::move( other->c).resume();
|
||||
return std::move( other->c);
|
||||
},
|
||||
std::forward< Fn >( fn) ) },
|
||||
#else
|
||||
c{ std::allocator_arg, palloc, std::forward< StackAllocator >( salloc),
|
||||
[this,fn_=std::forward< Fn >( fn)](boost::context::fiber && c) mutable {
|
||||
// create synthesized pull_coroutine< void >
|
||||
typename pull_coroutine< void >::control_block synthesized_cb{ this, c};
|
||||
pull_coroutine< void > synthesized{ & synthesized_cb };
|
||||
other = & synthesized_cb;
|
||||
other->c = std::move( other->c).resume();
|
||||
if ( state_t::none == ( state & state_t::destroy) ) {
|
||||
try {
|
||||
auto fn = std::move( fn_);
|
||||
// call coroutine-fn with synthesized pull_coroutine as argument
|
||||
fn( synthesized);
|
||||
} catch ( boost::context::detail::forced_unwind const&) {
|
||||
throw;
|
||||
#if defined( BOOST_CONTEXT_HAS_CXXABI_H )
|
||||
} catch ( abi::__forced_unwind const&) {
|
||||
throw;
|
||||
#endif
|
||||
} catch (...) {
|
||||
// store other exceptions in exception-pointer
|
||||
except = std::current_exception();
|
||||
}
|
||||
}
|
||||
// set termination flags
|
||||
state |= state_t::complete;
|
||||
// jump back
|
||||
other->c = std::move( other->c).resume();
|
||||
return std::move( other->c);
|
||||
} },
|
||||
#endif
|
||||
other{ nullptr },
|
||||
state{ state_t::unwind },
|
||||
except{} {
|
||||
c = std::move( c).resume();
|
||||
}
|
||||
|
||||
inline
|
||||
push_coroutine< void >::control_block::control_block( pull_coroutine< void >::control_block * cb,
|
||||
boost::context::continuation & c_) noexcept :
|
||||
boost::context::fiber & c_) noexcept :
|
||||
c{ std::move( c_) },
|
||||
other{ cb },
|
||||
state{ state_t::none },
|
||||
@@ -379,7 +382,7 @@ push_coroutine< void >::control_block::deallocate() noexcept {
|
||||
inline
|
||||
void
|
||||
push_coroutine< void >::control_block::resume() {
|
||||
c = c.resume();
|
||||
c = std::move( c).resume();
|
||||
if ( except) {
|
||||
std::rethrow_exception( except);
|
||||
}
|
||||
|
||||
@@ -1,111 +0,0 @@
|
||||
|
||||
// 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_PUSH_CONTROL_BLOCK_HPP
|
||||
#define BOOST_COROUTINES2_DETAIL_PUSH_CONTROL_BLOCK_HPP
|
||||
|
||||
#include <functional>
|
||||
#include <exception>
|
||||
|
||||
#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
|
||||
|
||||
namespace boost {
|
||||
namespace coroutines2 {
|
||||
namespace detail {
|
||||
|
||||
template< typename T >
|
||||
struct push_coroutine< T >::control_block {
|
||||
boost::context::execution_context ctx;
|
||||
typename pull_coroutine< T >::control_block * other;
|
||||
state_t state;
|
||||
std::exception_ptr except;
|
||||
|
||||
static void destroy( control_block * cb) noexcept;
|
||||
|
||||
template< typename StackAllocator, typename Fn >
|
||||
control_block( context::preallocated, StackAllocator, Fn &&);
|
||||
|
||||
control_block( typename pull_coroutine< T >::control_block *, boost::context::execution_context const&) noexcept;
|
||||
|
||||
~control_block() noexcept;
|
||||
|
||||
control_block( control_block &) = delete;
|
||||
control_block & operator=( control_block &) = delete;
|
||||
|
||||
void deallocate() noexcept;
|
||||
|
||||
void resume( T const&);
|
||||
|
||||
void resume( T &&);
|
||||
|
||||
bool valid() const noexcept;
|
||||
};
|
||||
|
||||
template< typename T >
|
||||
struct push_coroutine< T & >::control_block {
|
||||
boost::context::execution_context ctx;
|
||||
typename pull_coroutine< T & >::control_block * other;
|
||||
state_t state;
|
||||
std::exception_ptr except;
|
||||
|
||||
static void destroy( control_block * cb) noexcept;
|
||||
|
||||
template< typename StackAllocator, typename Fn >
|
||||
control_block( context::preallocated, StackAllocator, Fn &&);
|
||||
|
||||
control_block( typename pull_coroutine< T & >::control_block *, boost::context::execution_context const&) noexcept;
|
||||
|
||||
~control_block() noexcept;
|
||||
|
||||
control_block( control_block &) = delete;
|
||||
control_block & operator=( control_block &) = delete;
|
||||
|
||||
void deallocate() noexcept;
|
||||
|
||||
void resume( T &);
|
||||
|
||||
bool valid() const noexcept;
|
||||
};
|
||||
|
||||
struct push_coroutine< void >::control_block {
|
||||
boost::context::execution_context ctx;
|
||||
pull_coroutine< void >::control_block * other;
|
||||
state_t state;
|
||||
std::exception_ptr except;
|
||||
|
||||
static void destroy( control_block * cb) noexcept;
|
||||
|
||||
template< typename StackAllocator, typename Fn >
|
||||
control_block( context::preallocated, StackAllocator, Fn &&);
|
||||
|
||||
control_block( pull_coroutine< void >::control_block *, boost::context::execution_context const&) noexcept;
|
||||
|
||||
~control_block() noexcept;
|
||||
|
||||
control_block( control_block &) = delete;
|
||||
control_block & operator=( control_block &) = delete;
|
||||
|
||||
void deallocate() noexcept;
|
||||
|
||||
void resume();
|
||||
|
||||
bool valid() const noexcept;
|
||||
};
|
||||
|
||||
}}}
|
||||
|
||||
#ifdef BOOST_HAS_ABI_HEADERS
|
||||
# include BOOST_ABI_SUFFIX
|
||||
#endif
|
||||
|
||||
#endif // BOOST_COROUTINES2_DETAIL_PUSH_CONTROL_BLOCK_HPP
|
||||
@@ -1,428 +0,0 @@
|
||||
|
||||
// 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_PUSH_CONTROL_BLOCK_IPP
|
||||
#define BOOST_COROUTINES2_DETAIL_PUSH_CONTROL_BLOCK_IPP
|
||||
|
||||
#include <algorithm>
|
||||
#include <exception>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/config.hpp>
|
||||
|
||||
#include <boost/context/execution_context.hpp>
|
||||
|
||||
#include <boost/coroutine2/detail/config.hpp>
|
||||
#include <boost/coroutine2/detail/decay_copy.hpp>
|
||||
#include <boost/coroutine2/detail/forced_unwind.hpp>
|
||||
#include <boost/coroutine2/detail/state.hpp>
|
||||
#include <boost/coroutine2/detail/wrap.hpp>
|
||||
|
||||
#ifdef BOOST_HAS_ABI_HEADERS
|
||||
# include BOOST_ABI_PREFIX
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
namespace coroutines2 {
|
||||
namespace detail {
|
||||
|
||||
// push_coroutine< T >
|
||||
|
||||
template< typename T >
|
||||
void
|
||||
push_coroutine< T >::control_block::destroy( control_block * cb) noexcept {
|
||||
boost::context::execution_context ctx = cb->ctx;
|
||||
// destroy control structure
|
||||
cb->state |= state_t::destroy;
|
||||
cb->~control_block();
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
template< typename StackAllocator, typename Fn >
|
||||
push_coroutine< T >::control_block::control_block( context::preallocated palloc, StackAllocator salloc,
|
||||
Fn && fn) :
|
||||
#if defined(BOOST_NO_CXX14_GENERIC_LAMBDAS)
|
||||
ctx{ std::allocator_arg, palloc, salloc,
|
||||
wrap( [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;
|
||||
if ( state_t::none == ( state & state_t::destroy) ) {
|
||||
try {
|
||||
// jump back to ctor
|
||||
T * t = static_cast< T * >( ctx() );
|
||||
// set transferred value
|
||||
synthesized_cb.set( t);
|
||||
auto fn = std::move( fn_);
|
||||
// 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() ) },
|
||||
#else
|
||||
ctx{ std::allocator_arg, palloc, salloc,
|
||||
[this,fn_=decay_copy( 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 };
|
||||
other = & synthesized_cb;
|
||||
if ( state_t::none == ( state & state_t::destroy) ) {
|
||||
try {
|
||||
// jump back to ctor
|
||||
T * t = static_cast< T * >( ctx() );
|
||||
// set transferred value
|
||||
synthesized_cb.set( t);
|
||||
auto fn = std::move( fn_);
|
||||
// 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");
|
||||
}},
|
||||
#endif
|
||||
other{ nullptr },
|
||||
state{ state_t::unwind },
|
||||
except{} {
|
||||
// enter coroutine-fn in order to get other set
|
||||
ctx();
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
push_coroutine< T >::control_block::control_block( typename pull_coroutine< T >::control_block * cb,
|
||||
boost::context::execution_context const& ctx_) noexcept :
|
||||
ctx{ ctx_ },
|
||||
other{ cb },
|
||||
state{ state_t::none },
|
||||
except{} {
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
push_coroutine< T >::control_block::~control_block() {
|
||||
if ( state_t::none == ( state & state_t::complete) &&
|
||||
state_t::none != ( state & state_t::unwind) ) {
|
||||
// unwind coroutine stack
|
||||
other->ctx = boost::context::execution_context::current();
|
||||
ctx( context::exec_ontop_arg, unwind_coroutine);
|
||||
}
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
void
|
||||
push_coroutine< T >::control_block::deallocate() noexcept {
|
||||
if ( state_t::none != ( state & state_t::unwind) ) {
|
||||
destroy( this);
|
||||
}
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
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) );
|
||||
if ( except) {
|
||||
std::rethrow_exception( except);
|
||||
}
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
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) );
|
||||
if ( except) {
|
||||
std::rethrow_exception( except);
|
||||
}
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
bool
|
||||
push_coroutine< T >::control_block::valid() const noexcept {
|
||||
return state_t::none == ( state & state_t::complete );
|
||||
}
|
||||
|
||||
|
||||
// push_coroutine< T & >
|
||||
|
||||
template< typename T >
|
||||
void
|
||||
push_coroutine< T & >::control_block::destroy( control_block * cb) noexcept {
|
||||
boost::context::execution_context ctx = cb->ctx;
|
||||
// destroy control structure
|
||||
cb->state |= state_t::destroy;
|
||||
cb->~control_block();
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
template< typename StackAllocator, typename Fn >
|
||||
push_coroutine< T & >::control_block::control_block( context::preallocated palloc, StackAllocator salloc,
|
||||
Fn && fn) :
|
||||
#if defined(BOOST_NO_CXX14_GENERIC_LAMBDAS)
|
||||
ctx{ std::allocator_arg, palloc, salloc,
|
||||
wrap( [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;
|
||||
if ( state_t::none == ( state & state_t::destroy) ) {
|
||||
try {
|
||||
// jump back to ctor
|
||||
T * t = static_cast< T * >( ctx() );
|
||||
// set transferred value
|
||||
synthesized_cb.t = t;
|
||||
auto fn = std::move( fn_);
|
||||
// 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() ) },
|
||||
#else
|
||||
ctx{ std::allocator_arg, palloc, salloc,
|
||||
[this,fn_=decay_copy( 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 };
|
||||
other = & synthesized_cb;
|
||||
if ( state_t::none == ( state & state_t::destroy) ) {
|
||||
try {
|
||||
// jump back to ctor
|
||||
T * t = static_cast< T * >( ctx() );
|
||||
// set transferred value
|
||||
synthesized_cb.t = t;
|
||||
auto fn = std::move( fn_);
|
||||
// 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");
|
||||
}},
|
||||
#endif
|
||||
other{ nullptr },
|
||||
state{ state_t::unwind },
|
||||
except{} {
|
||||
// enter coroutine-fn in order to get other set
|
||||
ctx();
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
push_coroutine< T & >::control_block::control_block( typename pull_coroutine< T & >::control_block * cb,
|
||||
boost::context::execution_context const& ctx_) noexcept :
|
||||
ctx{ ctx_ },
|
||||
other{ cb },
|
||||
state{ state_t::none },
|
||||
except{} {
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
push_coroutine< T & >::control_block::~control_block() {
|
||||
if ( state_t::none == ( state & state_t::complete) &&
|
||||
state_t::none != ( state & state_t::unwind) ) {
|
||||
// unwind coroutine stack
|
||||
other->ctx = boost::context::execution_context::current();
|
||||
ctx( context::exec_ontop_arg, unwind_coroutine);
|
||||
}
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
void
|
||||
push_coroutine< T & >::control_block::deallocate() noexcept {
|
||||
if ( state_t::none != ( state & state_t::unwind) ) {
|
||||
destroy( this);
|
||||
}
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
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) ) );
|
||||
if ( except) {
|
||||
std::rethrow_exception( except);
|
||||
}
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
bool
|
||||
push_coroutine< T & >::control_block::valid() const noexcept {
|
||||
return state_t::none == ( state & state_t::complete );
|
||||
}
|
||||
|
||||
|
||||
// push_coroutine< void >
|
||||
|
||||
inline
|
||||
void
|
||||
push_coroutine< void >::control_block::destroy( control_block * cb) noexcept {
|
||||
boost::context::execution_context ctx = cb->ctx;
|
||||
// destroy control structure
|
||||
cb->state |= state_t::destroy;
|
||||
cb->~control_block();
|
||||
}
|
||||
|
||||
template< typename StackAllocator, typename Fn >
|
||||
push_coroutine< void >::control_block::control_block( context::preallocated palloc, StackAllocator salloc, Fn && fn) :
|
||||
#if defined(BOOST_NO_CXX14_GENERIC_LAMBDAS)
|
||||
ctx{ std::allocator_arg, palloc, salloc,
|
||||
wrap( [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;
|
||||
if ( state_t::none == ( state & state_t::destroy) ) {
|
||||
try {
|
||||
// jump back to ctor
|
||||
ctx();
|
||||
auto fn = std::move( fn_);
|
||||
// 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() ) },
|
||||
#else
|
||||
ctx{ std::allocator_arg, palloc, salloc,
|
||||
[this,fn_=decay_copy( 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 };
|
||||
other = & synthesized_cb;
|
||||
if ( state_t::none == ( state & state_t::destroy) ) {
|
||||
try {
|
||||
// jump back to ctor
|
||||
ctx();
|
||||
auto fn = std::move( fn_);
|
||||
// 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");
|
||||
}},
|
||||
#endif
|
||||
other{ nullptr },
|
||||
state{ state_t::unwind },
|
||||
except{} {
|
||||
// enter coroutine-fn in order to get other set
|
||||
ctx();
|
||||
}
|
||||
|
||||
inline
|
||||
push_coroutine< void >::control_block::control_block( pull_coroutine< void >::control_block * cb,
|
||||
boost::context::execution_context const& ctx_) noexcept :
|
||||
ctx{ ctx_ },
|
||||
other{ cb },
|
||||
state{ state_t::none },
|
||||
except{} {
|
||||
}
|
||||
|
||||
inline
|
||||
push_coroutine< void >::control_block::~control_block() {
|
||||
if ( state_t::none == ( state & state_t::complete) &&
|
||||
state_t::none != ( state & state_t::unwind) ) {
|
||||
// unwind coroutine stack
|
||||
other->ctx = boost::context::execution_context::current();
|
||||
ctx( context::exec_ontop_arg, unwind_coroutine);
|
||||
}
|
||||
}
|
||||
|
||||
inline
|
||||
void
|
||||
push_coroutine< void >::control_block::deallocate() noexcept {
|
||||
if ( state_t::none != ( state & state_t::unwind) ) {
|
||||
destroy( this);
|
||||
}
|
||||
}
|
||||
|
||||
inline
|
||||
void
|
||||
push_coroutine< void >::control_block::resume() {
|
||||
other->ctx = boost::context::execution_context::current();
|
||||
ctx();
|
||||
if ( except) {
|
||||
std::rethrow_exception( except);
|
||||
}
|
||||
}
|
||||
|
||||
inline
|
||||
bool
|
||||
push_coroutine< void >::control_block::valid() const noexcept {
|
||||
return state_t::none == ( state & state_t::complete );
|
||||
}
|
||||
|
||||
}}}
|
||||
|
||||
#ifdef BOOST_HAS_ABI_HEADERS
|
||||
# include BOOST_ABI_SUFFIX
|
||||
#endif
|
||||
|
||||
#endif // BOOST_COROUTINES2_DETAIL_PUSH_CONTROL_BLOCK_IPP
|
||||
@@ -43,7 +43,7 @@ public:
|
||||
explicit push_coroutine( Fn &&);
|
||||
|
||||
template< typename StackAllocator, typename Fn >
|
||||
push_coroutine( StackAllocator, Fn &&);
|
||||
push_coroutine( StackAllocator &&, Fn &&);
|
||||
|
||||
~push_coroutine();
|
||||
|
||||
@@ -54,8 +54,7 @@ public:
|
||||
|
||||
push_coroutine & operator=( push_coroutine && other) noexcept {
|
||||
if ( this == & other) return * this;
|
||||
cb_ = other.cb_;
|
||||
other.cb_ = nullptr;
|
||||
std::swap( cb_, other.cb_);
|
||||
return * this;
|
||||
}
|
||||
|
||||
@@ -67,11 +66,17 @@ public:
|
||||
|
||||
bool operator!() const noexcept;
|
||||
|
||||
class iterator : public std::iterator< std::output_iterator_tag, void, void, void, void > {
|
||||
class iterator {
|
||||
private:
|
||||
push_coroutine< T > * c_{ nullptr };
|
||||
|
||||
public:
|
||||
typedef std::output_iterator_tag iterator_category;
|
||||
typedef void value_type;
|
||||
typedef void difference_type;
|
||||
typedef void pointer;
|
||||
typedef void reference;
|
||||
|
||||
iterator() noexcept = default;
|
||||
|
||||
explicit iterator( push_coroutine< T > * c) noexcept :
|
||||
@@ -123,7 +128,7 @@ public:
|
||||
explicit push_coroutine( Fn &&);
|
||||
|
||||
template< typename StackAllocator, typename Fn >
|
||||
push_coroutine( StackAllocator, Fn &&);
|
||||
push_coroutine( StackAllocator &&, Fn &&);
|
||||
|
||||
~push_coroutine();
|
||||
|
||||
@@ -134,8 +139,7 @@ public:
|
||||
|
||||
push_coroutine & operator=( push_coroutine && other) noexcept {
|
||||
if ( this == & other) return * this;
|
||||
cb_ = other.cb_;
|
||||
other.cb_ = nullptr;
|
||||
std::swap( cb_, other.cb_);
|
||||
return * this;
|
||||
}
|
||||
|
||||
@@ -145,11 +149,17 @@ public:
|
||||
|
||||
bool operator!() const noexcept;
|
||||
|
||||
class iterator : public std::iterator< std::output_iterator_tag, void, void, void, void > {
|
||||
class iterator {
|
||||
private:
|
||||
push_coroutine< T & > * c_{ nullptr };
|
||||
|
||||
public:
|
||||
typedef std::output_iterator_tag iterator_category;
|
||||
typedef void value_type;
|
||||
typedef void difference_type;
|
||||
typedef void pointer;
|
||||
typedef void reference;
|
||||
|
||||
iterator() noexcept = default;
|
||||
|
||||
explicit iterator( push_coroutine< T & > * c) noexcept :
|
||||
@@ -201,7 +211,7 @@ public:
|
||||
explicit push_coroutine( Fn &&);
|
||||
|
||||
template< typename StackAllocator, typename Fn >
|
||||
push_coroutine( StackAllocator, Fn &&);
|
||||
push_coroutine( StackAllocator &&, Fn &&);
|
||||
|
||||
~push_coroutine();
|
||||
|
||||
@@ -212,8 +222,7 @@ public:
|
||||
|
||||
push_coroutine & operator=( push_coroutine && other) noexcept {
|
||||
if ( this == & other) return * this;
|
||||
cb_ = other.cb_;
|
||||
other.cb_ = nullptr;
|
||||
std::swap( cb_, other.cb_);
|
||||
return * this;
|
||||
}
|
||||
|
||||
|
||||
@@ -43,8 +43,8 @@ push_coroutine< T >::push_coroutine( Fn && fn) :
|
||||
|
||||
template< typename T >
|
||||
template< typename StackAllocator, typename Fn >
|
||||
push_coroutine< T >::push_coroutine( StackAllocator salloc, Fn && fn) :
|
||||
cb_{ create_control_block< control_block >( salloc, std::forward< Fn >( fn) ) } {
|
||||
push_coroutine< T >::push_coroutine( StackAllocator && salloc, Fn && fn) :
|
||||
cb_{ create_control_block< control_block >( std::forward< StackAllocator >( salloc), std::forward< Fn >( fn) ) } {
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
@@ -56,8 +56,8 @@ push_coroutine< T >::~push_coroutine() {
|
||||
|
||||
template< typename T >
|
||||
push_coroutine< T >::push_coroutine( push_coroutine && other) noexcept :
|
||||
cb_{ other.cb_ } {
|
||||
other.cb_ = nullptr;
|
||||
cb_{ nullptr } {
|
||||
std::swap( cb_, other.cb_);
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
@@ -103,8 +103,8 @@ push_coroutine< T & >::push_coroutine( Fn && fn) :
|
||||
|
||||
template< typename T >
|
||||
template< typename StackAllocator, typename Fn >
|
||||
push_coroutine< T & >::push_coroutine( StackAllocator salloc, Fn && fn) :
|
||||
cb_{ create_control_block< control_block >( salloc, std::forward< Fn >( fn) ) } {
|
||||
push_coroutine< T & >::push_coroutine( StackAllocator && salloc, Fn && fn) :
|
||||
cb_{ create_control_block< control_block >( std::forward< StackAllocator >( salloc), std::forward< Fn >( fn) ) } {
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
@@ -116,8 +116,8 @@ push_coroutine< T & >::~push_coroutine() {
|
||||
|
||||
template< typename T >
|
||||
push_coroutine< T & >::push_coroutine( push_coroutine && other) noexcept :
|
||||
cb_{ other.cb_ } {
|
||||
other.cb_ = nullptr;
|
||||
cb_{ nullptr } {
|
||||
std::swap( cb_, other.cb_);
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
@@ -154,8 +154,8 @@ push_coroutine< void >::push_coroutine( Fn && fn) :
|
||||
}
|
||||
|
||||
template< typename StackAllocator, typename Fn >
|
||||
push_coroutine< void >::push_coroutine( StackAllocator salloc, Fn && fn) :
|
||||
cb_{ create_control_block< control_block >( salloc, std::forward< Fn >( fn) ) } {
|
||||
push_coroutine< void >::push_coroutine( StackAllocator && salloc, Fn && fn) :
|
||||
cb_{ create_control_block< control_block >( std::forward< StackAllocator >( salloc), std::forward< Fn >( fn) ) } {
|
||||
}
|
||||
|
||||
inline
|
||||
@@ -167,8 +167,8 @@ push_coroutine< void >::~push_coroutine() {
|
||||
|
||||
inline
|
||||
push_coroutine< void >::push_coroutine( push_coroutine && other) noexcept :
|
||||
cb_{ other.cb_ } {
|
||||
other.cb_ = nullptr;
|
||||
cb_{ nullptr } {
|
||||
std::swap( cb_, other.cb_);
|
||||
}
|
||||
|
||||
inline
|
||||
|
||||
@@ -11,14 +11,9 @@
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/context/detail/invoke.hpp>
|
||||
#if (BOOST_EXECUTION_CONTEXT==1)
|
||||
# include <boost/context/execution_context.hpp>
|
||||
#else
|
||||
# include <boost/context/continuation.hpp>
|
||||
#endif
|
||||
#include <boost/context/fiber.hpp>
|
||||
|
||||
#include <boost/fiber/detail/config.hpp>
|
||||
#include <boost/fiber/detail/data.hpp>
|
||||
#include <boost/coroutine2/detail/config.hpp>
|
||||
|
||||
#ifdef BOOST_HAS_ABI_HEADERS
|
||||
# include BOOST_ABI_PREFIX
|
||||
@@ -28,45 +23,6 @@ namespace boost {
|
||||
namespace coroutines2 {
|
||||
namespace detail {
|
||||
|
||||
#if (BOOST_EXECUTION_CONTEXT==1)
|
||||
template< typename Fn1, typename Fn2 >
|
||||
class wrapper {
|
||||
private:
|
||||
typename std::decay< Fn1 >::type fn1_;
|
||||
typename std::decay< Fn2 >::type fn2_;
|
||||
boost::context::execution_context ctx_;
|
||||
|
||||
public:
|
||||
wrapper( Fn1 && fn1, Fn2 && fn2,
|
||||
boost::context::execution_context const& ctx) :
|
||||
fn1_( std::move( fn1) ),
|
||||
fn2_( std::move( fn2) ),
|
||||
ctx_{ ctx } {
|
||||
}
|
||||
|
||||
wrapper( wrapper const&) = delete;
|
||||
wrapper & operator=( wrapper const&) = delete;
|
||||
|
||||
wrapper( wrapper && other) = default;
|
||||
wrapper & operator=( wrapper && other) = default;
|
||||
|
||||
void operator()( void * vp) {
|
||||
boost::context::detail::invoke(
|
||||
std::move( fn1_),
|
||||
fn2_, ctx_, vp);
|
||||
}
|
||||
};
|
||||
|
||||
template< typename Fn1, typename Fn2 >
|
||||
wrapper< Fn1, Fn2 >
|
||||
wrap( Fn1 && fn1, Fn2 && fn2,
|
||||
boost::context::execution_context const& ctx) {
|
||||
return wrapper< Fn1, Fn2 >(
|
||||
std::forward< Fn1 >( fn1),
|
||||
std::forward< Fn2 >( fn2),
|
||||
ctx);
|
||||
}
|
||||
#else
|
||||
template< typename Fn1, typename Fn2 >
|
||||
class wrapper {
|
||||
private:
|
||||
@@ -85,12 +41,12 @@ public:
|
||||
wrapper( wrapper && other) = default;
|
||||
wrapper & operator=( wrapper && other) = default;
|
||||
|
||||
boost::context::continuation
|
||||
operator()( boost::context::continuation && c) {
|
||||
boost::context::fiber
|
||||
operator()( boost::context::fiber && c) {
|
||||
return boost::context::detail::invoke(
|
||||
std::move( fn1_),
|
||||
fn2_,
|
||||
std::forward< boost::context::continuation >( c) );
|
||||
std::forward< boost::context::fiber >( c) );
|
||||
}
|
||||
};
|
||||
|
||||
@@ -101,7 +57,6 @@ wrap( Fn1 && fn1, Fn2 && fn2) {
|
||||
std::forward< Fn1 >( fn1),
|
||||
std::forward< Fn2 >( fn2) );
|
||||
}
|
||||
#endif
|
||||
|
||||
}}}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user