mirror of
https://github.com/boostorg/coroutine2.git
synced 2025-05-09 23:24:01 +00:00
Merge branch 'develop'
This commit is contained in:
commit
2c74f97f17
@ -40,6 +40,6 @@ exe parser
|
|||||||
: parser.cpp
|
: parser.cpp
|
||||||
;
|
;
|
||||||
|
|
||||||
exe segmented
|
#exe segmented
|
||||||
: segmented.cpp
|
# : segmented.cpp
|
||||||
;
|
# ;
|
||||||
|
@ -36,15 +36,9 @@ void bar( int i)
|
|||||||
int main() {
|
int main() {
|
||||||
int count = 384;
|
int count = 384;
|
||||||
|
|
||||||
#if defined(BOOST_USE_SEGMENTED_STACKS)
|
|
||||||
std::cout << "using segmented_stack stacks: allocates " << count << " * 4kB == " << 4 * count << "kB on stack, ";
|
std::cout << "using segmented_stack stacks: allocates " << count << " * 4kB == " << 4 * count << "kB on stack, ";
|
||||||
std::cout << "initial stack size = " << boost::context::segmented_stack::traits_type::default_size() / 1024 << "kB" << std::endl;
|
std::cout << "initial stack size = " << boost::context::segmented_stack::traits_type::default_size() / 1024 << "kB" << std::endl;
|
||||||
std::cout << "application should not fail" << std::endl;
|
std::cout << "application should not fail" << std::endl;
|
||||||
#else
|
|
||||||
std::cout << "using standard stacks: allocates " << count << " * 4kB == " << 4 * count << "kB on stack, ";
|
|
||||||
std::cout << "initial stack size = " << boost::context::fixedsize_stack::traits_type::default_size() / 1024 << "kB" << std::endl;
|
|
||||||
std::cout << "application might fail" << std::endl;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
boost::coroutines2::coroutine< void >::push_type sink(
|
boost::coroutines2::coroutine< void >::push_type sink(
|
||||||
[&]( boost::coroutines2::coroutine< void >::pull_type & source) {
|
[&]( boost::coroutines2::coroutine< void >::pull_type & source) {
|
||||||
|
@ -34,8 +34,8 @@ class push_coroutine;
|
|||||||
# include <boost/coroutine2/detail/pull_control_block_ecv1.hpp>
|
# include <boost/coroutine2/detail/pull_control_block_ecv1.hpp>
|
||||||
# include <boost/coroutine2/detail/push_control_block_ecv1.hpp>
|
# include <boost/coroutine2/detail/push_control_block_ecv1.hpp>
|
||||||
# else
|
# else
|
||||||
# include <boost/coroutine2/detail/pull_control_block_ecv2.hpp>
|
# include <boost/coroutine2/detail/pull_control_block_cc.hpp>
|
||||||
# include <boost/coroutine2/detail/push_control_block_ecv2.hpp>
|
# include <boost/coroutine2/detail/push_control_block_cc.hpp>
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
# include <boost/coroutine2/detail/pull_coroutine.ipp>
|
# include <boost/coroutine2/detail/pull_coroutine.ipp>
|
||||||
@ -45,8 +45,8 @@ class push_coroutine;
|
|||||||
# include <boost/coroutine2/detail/pull_control_block_ecv1.ipp>
|
# include <boost/coroutine2/detail/pull_control_block_ecv1.ipp>
|
||||||
# include <boost/coroutine2/detail/push_control_block_ecv1.ipp>
|
# include <boost/coroutine2/detail/push_control_block_ecv1.ipp>
|
||||||
# else
|
# else
|
||||||
# include <boost/coroutine2/detail/pull_control_block_ecv2.ipp>
|
# include <boost/coroutine2/detail/pull_control_block_cc.ipp>
|
||||||
# include <boost/coroutine2/detail/push_control_block_ecv2.ipp>
|
# include <boost/coroutine2/detail/push_control_block_cc.ipp>
|
||||||
# endif
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -12,8 +12,6 @@
|
|||||||
#include <boost/assert.hpp>
|
#include <boost/assert.hpp>
|
||||||
#include <boost/config.hpp>
|
#include <boost/config.hpp>
|
||||||
|
|
||||||
#include <boost/context/execution_context.hpp>
|
|
||||||
|
|
||||||
#ifdef BOOST_HAS_ABI_HEADERS
|
#ifdef BOOST_HAS_ABI_HEADERS
|
||||||
# include BOOST_ABI_PREFIX
|
# include BOOST_ABI_PREFIX
|
||||||
#endif
|
#endif
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
|
|
||||||
// Copyright Oliver Kowalke 2014.
|
// Copyright Oliver Kowalke 2016.
|
||||||
// Distributed under the Boost Software License, Version 1.0.
|
// Distributed under the Boost Software License, Version 1.0.
|
||||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||||
// http://www.boost.org/LICENSE_1_0.txt)
|
// http://www.boost.org/LICENSE_1_0.txt)
|
||||||
@ -11,7 +11,7 @@
|
|||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
|
|
||||||
#include <boost/config.hpp>
|
#include <boost/config.hpp>
|
||||||
#include <boost/context/execution_context.hpp>
|
#include <boost/context/continuation.hpp>
|
||||||
|
|
||||||
#include <boost/coroutine2/detail/state.hpp>
|
#include <boost/coroutine2/detail/state.hpp>
|
||||||
|
|
||||||
@ -25,7 +25,7 @@ namespace detail {
|
|||||||
|
|
||||||
template< typename T >
|
template< typename T >
|
||||||
struct pull_coroutine< T >::control_block {
|
struct pull_coroutine< T >::control_block {
|
||||||
boost::context::execution_context< T * > ctx;
|
boost::context::continuation c;
|
||||||
typename push_coroutine< T >::control_block * other;
|
typename push_coroutine< T >::control_block * other;
|
||||||
state_t state;
|
state_t state;
|
||||||
std::exception_ptr except;
|
std::exception_ptr except;
|
||||||
@ -37,7 +37,7 @@ struct pull_coroutine< T >::control_block {
|
|||||||
template< typename StackAllocator, typename Fn >
|
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::execution_context< T * > &) noexcept;
|
control_block( typename push_coroutine< T >::control_block *, boost::context::continuation &) noexcept;
|
||||||
|
|
||||||
~control_block();
|
~control_block();
|
||||||
|
|
||||||
@ -48,7 +48,9 @@ struct pull_coroutine< T >::control_block {
|
|||||||
|
|
||||||
void resume();
|
void resume();
|
||||||
|
|
||||||
void set( T *);
|
void set( T const&);
|
||||||
|
void set( T &&);
|
||||||
|
void reset();
|
||||||
|
|
||||||
T & get() noexcept;
|
T & get() noexcept;
|
||||||
|
|
||||||
@ -57,18 +59,27 @@ struct pull_coroutine< T >::control_block {
|
|||||||
|
|
||||||
template< typename T >
|
template< typename T >
|
||||||
struct pull_coroutine< T & >::control_block {
|
struct pull_coroutine< T & >::control_block {
|
||||||
boost::context::execution_context< T * > ctx;
|
struct holder {
|
||||||
typename push_coroutine< T & >::control_block * other;
|
T & t;
|
||||||
state_t state;
|
|
||||||
std::exception_ptr except;
|
holder( T & t_) :
|
||||||
T * t;
|
t{ t_ } {
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
boost::context::continuation c;
|
||||||
|
typename push_coroutine< T & >::control_block * other;
|
||||||
|
state_t state;
|
||||||
|
std::exception_ptr except;
|
||||||
|
bool bvalid;
|
||||||
|
typename std::aligned_storage< sizeof( holder), alignof( holder) >::type storage;
|
||||||
|
|
||||||
static void destroy( control_block * cb) noexcept;
|
static void destroy( control_block * cb) noexcept;
|
||||||
|
|
||||||
template< typename StackAllocator, typename Fn >
|
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::execution_context< T * > &) noexcept;
|
control_block( typename push_coroutine< T & >::control_block *, boost::context::continuation &) noexcept;
|
||||||
|
|
||||||
control_block( control_block &) = delete;
|
control_block( control_block &) = delete;
|
||||||
control_block & operator=( control_block &) = delete;
|
control_block & operator=( control_block &) = delete;
|
||||||
@ -77,13 +88,16 @@ struct pull_coroutine< T & >::control_block {
|
|||||||
|
|
||||||
void resume();
|
void resume();
|
||||||
|
|
||||||
|
void set( T &);
|
||||||
|
void reset();
|
||||||
|
|
||||||
T & get() noexcept;
|
T & get() noexcept;
|
||||||
|
|
||||||
bool valid() const noexcept;
|
bool valid() const noexcept;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct pull_coroutine< void >::control_block {
|
struct pull_coroutine< void >::control_block {
|
||||||
boost::context::execution_context< void > ctx;
|
boost::context::continuation c;
|
||||||
push_coroutine< void >::control_block * other;
|
push_coroutine< void >::control_block * other;
|
||||||
state_t state;
|
state_t state;
|
||||||
std::exception_ptr except;
|
std::exception_ptr except;
|
||||||
@ -93,7 +107,7 @@ struct pull_coroutine< void >::control_block {
|
|||||||
template< typename StackAllocator, typename Fn >
|
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::execution_context< void > &) noexcept;
|
control_block( push_coroutine< void >::control_block *, boost::context::continuation &) noexcept;
|
||||||
|
|
||||||
control_block( control_block &) = delete;
|
control_block( control_block &) = delete;
|
||||||
control_block & operator=( control_block &) = delete;
|
control_block & operator=( control_block &) = delete;
|
460
include/boost/coroutine2/detail/pull_control_block_cc.ipp
Normal file
460
include/boost/coroutine2/detail/pull_control_block_cc.ipp
Normal file
@ -0,0 +1,460 @@
|
|||||||
|
|
||||||
|
// Copyright Oliver Kowalke 2016.
|
||||||
|
// 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 <algorithm>
|
||||||
|
#include <exception>
|
||||||
|
#include <memory>
|
||||||
|
#include <tuple>
|
||||||
|
|
||||||
|
#include <boost/assert.hpp>
|
||||||
|
#include <boost/config.hpp>
|
||||||
|
|
||||||
|
#include <boost/context/continuation.hpp>
|
||||||
|
|
||||||
|
#include <boost/coroutine2/detail/config.hpp>
|
||||||
|
#include <boost/coroutine2/detail/forced_unwind.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::continuation c = std::move( cb->c);
|
||||||
|
// destroy control structure
|
||||||
|
cb->~control_block();
|
||||||
|
// destroy coroutine's stack
|
||||||
|
cb->state |= state_t::destroy;
|
||||||
|
boost::context::resume( std::move( c) );
|
||||||
|
}
|
||||||
|
|
||||||
|
template< typename T >
|
||||||
|
template< typename StackAllocator, typename Fn >
|
||||||
|
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,
|
||||||
|
std::move(
|
||||||
|
std::bind(
|
||||||
|
[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 boost::context::resume( std::move( other->c) );
|
||||||
|
},
|
||||||
|
std::forward< Fn >( fn),
|
||||||
|
std::placeholders::_1) ) );
|
||||||
|
#else
|
||||||
|
c = boost::context::callcc(
|
||||||
|
std::allocator_arg, palloc, salloc,
|
||||||
|
[this,fn_=std::forward< Fn >( 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 boost::context::resume( std::move( other->c) );
|
||||||
|
});
|
||||||
|
#endif
|
||||||
|
if ( boost::context::data_available( c) ) {
|
||||||
|
set( boost::context::transfer_data< T >( c) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template< typename T >
|
||||||
|
pull_coroutine< T >::control_block::control_block( typename push_coroutine< T >::control_block * cb,
|
||||||
|
boost::context::continuation & c_) noexcept :
|
||||||
|
c{ std::move( c_) },
|
||||||
|
other{ cb },
|
||||||
|
state{ state_t::none },
|
||||||
|
except{},
|
||||||
|
bvalid{ false },
|
||||||
|
storage{} {
|
||||||
|
}
|
||||||
|
|
||||||
|
template< typename T >
|
||||||
|
pull_coroutine< T >::control_block::~control_block() {
|
||||||
|
// destroy data if 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() {
|
||||||
|
c = boost::context::resume( std::move( c) );
|
||||||
|
if ( boost::context::data_available( c) ) {
|
||||||
|
set( boost::context::transfer_data< T >( c) );
|
||||||
|
} else {
|
||||||
|
reset();
|
||||||
|
}
|
||||||
|
if ( except) {
|
||||||
|
std::rethrow_exception( except);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template< typename T >
|
||||||
|
void
|
||||||
|
pull_coroutine< T >::control_block::set( T const& t) {
|
||||||
|
// destroy data if set
|
||||||
|
if ( bvalid) {
|
||||||
|
reinterpret_cast< T * >( std::addressof( storage) )->~T();
|
||||||
|
}
|
||||||
|
::new ( static_cast< void * >( std::addressof( storage) ) ) T( t);
|
||||||
|
bvalid = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
template< typename T >
|
||||||
|
void
|
||||||
|
pull_coroutine< T >::control_block::set( T && t) {
|
||||||
|
// destroy data if set
|
||||||
|
if ( bvalid) {
|
||||||
|
reinterpret_cast< T * >( std::addressof( storage) )->~T();
|
||||||
|
}
|
||||||
|
::new ( static_cast< void * >( std::addressof( storage) ) ) T( std::move( 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 {
|
||||||
|
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::continuation c = std::move( cb->c);
|
||||||
|
// destroy control structure
|
||||||
|
cb->~control_block();
|
||||||
|
// destroy coroutine's stack
|
||||||
|
cb->state |= state_t::destroy;
|
||||||
|
boost::context::resume( std::move( c) );
|
||||||
|
}
|
||||||
|
|
||||||
|
template< typename T >
|
||||||
|
template< typename StackAllocator, typename Fn >
|
||||||
|
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,
|
||||||
|
std::move(
|
||||||
|
std::bind(
|
||||||
|
[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 boost::context::resume( std::move( other->c) );
|
||||||
|
},
|
||||||
|
std::forward< Fn >( fn),
|
||||||
|
std::placeholders::_1) ) );
|
||||||
|
#else
|
||||||
|
c = boost::context::callcc(
|
||||||
|
std::allocator_arg, palloc, salloc,
|
||||||
|
[this,fn_=std::forward< Fn >( 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 boost::context::resume( std::move( other->c) );
|
||||||
|
});
|
||||||
|
#endif
|
||||||
|
if ( boost::context::data_available( c) ) {
|
||||||
|
set( boost::context::transfer_data< T & >( c) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template< typename T >
|
||||||
|
pull_coroutine< T & >::control_block::control_block( typename push_coroutine< T & >::control_block * cb,
|
||||||
|
boost::context::continuation & c_) noexcept :
|
||||||
|
c{ std::move( c_) },
|
||||||
|
other{ cb },
|
||||||
|
state{ state_t::none },
|
||||||
|
except{},
|
||||||
|
bvalid{ false },
|
||||||
|
storage{} {
|
||||||
|
}
|
||||||
|
|
||||||
|
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() {
|
||||||
|
c = boost::context::resume( std::move( c) );
|
||||||
|
if ( boost::context::data_available( c) ) {
|
||||||
|
set( boost::context::transfer_data< T & >( c) );
|
||||||
|
} else {
|
||||||
|
reset();
|
||||||
|
}
|
||||||
|
if ( except) {
|
||||||
|
std::rethrow_exception( except);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template< typename T >
|
||||||
|
void
|
||||||
|
pull_coroutine< T & >::control_block::set( T & t) {
|
||||||
|
::new ( static_cast< void * >( std::addressof( storage) ) ) holder{ 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 {
|
||||||
|
return reinterpret_cast< holder * >( std::addressof( storage) )->t;
|
||||||
|
}
|
||||||
|
|
||||||
|
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< void >
|
||||||
|
|
||||||
|
inline
|
||||||
|
void
|
||||||
|
pull_coroutine< void >::control_block::destroy( control_block * cb) noexcept {
|
||||||
|
boost::context::continuation c = std::move( cb->c);
|
||||||
|
// destroy control structure
|
||||||
|
cb->~control_block();
|
||||||
|
// destroy coroutine's stack
|
||||||
|
cb->state |= state_t::destroy;
|
||||||
|
boost::context::resume( std::move( c) );
|
||||||
|
}
|
||||||
|
|
||||||
|
template< typename StackAllocator, typename Fn >
|
||||||
|
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,
|
||||||
|
std::move(
|
||||||
|
std::bind(
|
||||||
|
[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 boost::context::resume( std::move( other->c) );
|
||||||
|
},
|
||||||
|
std::forward< Fn >( fn),
|
||||||
|
std::placeholders::_1) ) );
|
||||||
|
#else
|
||||||
|
c = boost::context::callcc(
|
||||||
|
std::allocator_arg, palloc, salloc,
|
||||||
|
[this,fn_=std::forward< Fn >( 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 to ctx
|
||||||
|
return boost::context::resume( std::move( other->c) );
|
||||||
|
});
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
inline
|
||||||
|
pull_coroutine< void >::control_block::control_block( push_coroutine< void >::control_block * cb,
|
||||||
|
boost::context::continuation & c_) noexcept :
|
||||||
|
c{ std::move( c_) },
|
||||||
|
other{ cb },
|
||||||
|
state{ state_t::none },
|
||||||
|
except{} {
|
||||||
|
}
|
||||||
|
|
||||||
|
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() {
|
||||||
|
c = boost::context::resume( std::move( c) );
|
||||||
|
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
|
@ -1,422 +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 <algorithm>
|
|
||||||
#include <exception>
|
|
||||||
#include <memory>
|
|
||||||
#include <tuple>
|
|
||||||
|
|
||||||
#include <boost/assert.hpp>
|
|
||||||
#include <boost/config.hpp>
|
|
||||||
|
|
||||||
#include <boost/context/execution_context.hpp>
|
|
||||||
|
|
||||||
#include <boost/coroutine2/detail/config.hpp>
|
|
||||||
#include <boost/coroutine2/detail/forced_unwind.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< T * > ctx = std::move( cb->ctx);
|
|
||||||
// destroy control structure
|
|
||||||
cb->~control_block();
|
|
||||||
// destroy coroutine's stack
|
|
||||||
cb->state |= state_t::destroy;
|
|
||||||
ctx( nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
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,
|
|
||||||
std::move(
|
|
||||||
std::bind(
|
|
||||||
[this]( typename std::decay< Fn >::type & fn_, boost::context::execution_context< T * > && ctx, T *) mutable {
|
|
||||||
// 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 ( 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 to ctx
|
|
||||||
auto result = other->ctx( nullptr);
|
|
||||||
other->ctx = std::move( std::get< 0 >( result) );
|
|
||||||
return std::move( other->ctx);
|
|
||||||
},
|
|
||||||
std::forward< Fn >( fn),
|
|
||||||
std::placeholders::_1,
|
|
||||||
std::placeholders::_2))},
|
|
||||||
#else
|
|
||||||
ctx{ std::allocator_arg, palloc, salloc,
|
|
||||||
[this,fn_=std::forward< Fn >( fn)]( boost::context::execution_context< T * > && ctx, T *) mutable {
|
|
||||||
// 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 ( 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 to ctx
|
|
||||||
auto result = other->ctx( nullptr);
|
|
||||||
other->ctx = std::move( std::get< 0 >( result) );
|
|
||||||
return std::move( other->ctx);
|
|
||||||
}},
|
|
||||||
#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
|
|
||||||
resume();
|
|
||||||
}
|
|
||||||
|
|
||||||
template< typename T >
|
|
||||||
pull_coroutine< T >::control_block::control_block( typename push_coroutine< T >::control_block * cb,
|
|
||||||
boost::context::execution_context< T * > & ctx_) noexcept :
|
|
||||||
ctx{ std::move( ctx_) },
|
|
||||||
other{ cb },
|
|
||||||
state{ state_t::none },
|
|
||||||
except{},
|
|
||||||
bvalid{ false },
|
|
||||||
storage{} {
|
|
||||||
}
|
|
||||||
|
|
||||||
template< typename T >
|
|
||||||
pull_coroutine< T >::control_block::~control_block() {
|
|
||||||
// destroy data if 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() {
|
|
||||||
auto result = ctx( nullptr);
|
|
||||||
ctx = std::move( std::get< 0 >( result) );
|
|
||||||
set( std::get< 1 >( result) );
|
|
||||||
if ( except) {
|
|
||||||
std::rethrow_exception( except);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template< typename T >
|
|
||||||
void
|
|
||||||
pull_coroutine< T >::control_block::set( T * t) {
|
|
||||||
// destroy data if 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< T * > ctx = std::move( cb->ctx);
|
|
||||||
// destroy control structure
|
|
||||||
cb->~control_block();
|
|
||||||
// destroy coroutine's stack
|
|
||||||
cb->state |= state_t::destroy;
|
|
||||||
ctx( nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
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,
|
|
||||||
std::move(
|
|
||||||
std::bind(
|
|
||||||
[this]( typename std::decay< Fn >::type & fn_, boost::context::execution_context< T *> && ctx, T *) mutable {
|
|
||||||
// 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 ( 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 to ctx
|
|
||||||
auto result = other->ctx( nullptr);
|
|
||||||
other->ctx = std::move( std::get< 0 >( result) );
|
|
||||||
return std::move( other->ctx);
|
|
||||||
},
|
|
||||||
std::forward< Fn >( fn),
|
|
||||||
std::placeholders::_1,
|
|
||||||
std::placeholders::_2))},
|
|
||||||
#else
|
|
||||||
ctx{ std::allocator_arg, palloc, salloc,
|
|
||||||
[this,fn_=std::forward< Fn >( fn)]( boost::context::execution_context< T * > && ctx, T *) mutable {
|
|
||||||
// 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 ( 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 to ctx
|
|
||||||
auto result = other->ctx( nullptr);
|
|
||||||
other->ctx = std::move( std::get< 0 >( result) );
|
|
||||||
return std::move( other->ctx);
|
|
||||||
}},
|
|
||||||
#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
|
|
||||||
resume();
|
|
||||||
}
|
|
||||||
|
|
||||||
template< typename T >
|
|
||||||
pull_coroutine< T & >::control_block::control_block( typename push_coroutine< T & >::control_block * cb,
|
|
||||||
boost::context::execution_context< T * > & ctx_) noexcept :
|
|
||||||
ctx{ std::move( ctx_) },
|
|
||||||
other{ cb },
|
|
||||||
state{ state_t::none },
|
|
||||||
except{},
|
|
||||||
t{ nullptr } {
|
|
||||||
}
|
|
||||||
|
|
||||||
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() {
|
|
||||||
auto result = ctx( nullptr);
|
|
||||||
ctx = std::move( std::get< 0 >( result) );
|
|
||||||
t = std::get< 1 >( result);
|
|
||||||
if ( except) {
|
|
||||||
std::rethrow_exception( except);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template< typename T >
|
|
||||||
T &
|
|
||||||
pull_coroutine< T & >::control_block::get() noexcept {
|
|
||||||
return * 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< void > ctx = std::move( cb->ctx);
|
|
||||||
// destroy control structure
|
|
||||||
cb->~control_block();
|
|
||||||
// destroy coroutine's stack
|
|
||||||
cb->state |= state_t::destroy;
|
|
||||||
ctx();
|
|
||||||
}
|
|
||||||
|
|
||||||
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,
|
|
||||||
std::move(
|
|
||||||
std::bind(
|
|
||||||
[this]( typename std::decay< Fn >::type & fn_, boost::context::execution_context< void > && ctx) mutable {
|
|
||||||
// create synthesized push_coroutine< void >
|
|
||||||
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 ( 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 to ctx
|
|
||||||
other->ctx = other->ctx();
|
|
||||||
return std::move( other->ctx);
|
|
||||||
},
|
|
||||||
std::forward< Fn >( fn),
|
|
||||||
std::placeholders::_1))},
|
|
||||||
#else
|
|
||||||
ctx{ std::allocator_arg, palloc, salloc,
|
|
||||||
[this,fn_=std::forward< Fn >( fn)]( boost::context::execution_context< void > && ctx) mutable {
|
|
||||||
// create synthesized push_coroutine< void >
|
|
||||||
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 ( 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 to ctx
|
|
||||||
other->ctx = other->ctx();
|
|
||||||
return std::move( other->ctx);
|
|
||||||
}},
|
|
||||||
#endif
|
|
||||||
other{ nullptr },
|
|
||||||
state{ state_t::unwind },
|
|
||||||
except{} {
|
|
||||||
// enter coroutine-fn in order to have first value available after ctor (of `*this`) returns
|
|
||||||
resume();
|
|
||||||
}
|
|
||||||
|
|
||||||
inline
|
|
||||||
pull_coroutine< void >::control_block::control_block( push_coroutine< void >::control_block * cb,
|
|
||||||
boost::context::execution_context< void > & ctx_) noexcept :
|
|
||||||
ctx{ std::move( ctx_) },
|
|
||||||
other{ cb },
|
|
||||||
state{ state_t::none },
|
|
||||||
except{} {
|
|
||||||
}
|
|
||||||
|
|
||||||
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() {
|
|
||||||
ctx = 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
|
|
@ -92,7 +92,7 @@ public:
|
|||||||
typedef typename iterator::pointer pointer_t;
|
typedef typename iterator::pointer pointer_t;
|
||||||
typedef typename iterator::reference reference_t;
|
typedef typename iterator::reference reference_t;
|
||||||
|
|
||||||
constexpr iterator() noexcept = default;
|
iterator() noexcept = default;
|
||||||
|
|
||||||
explicit iterator( pull_coroutine< T > * c) noexcept :
|
explicit iterator( pull_coroutine< T > * c) noexcept :
|
||||||
c_{ c } {
|
c_{ c } {
|
||||||
@ -204,7 +204,7 @@ public:
|
|||||||
typedef typename iterator::pointer pointer_t;
|
typedef typename iterator::pointer pointer_t;
|
||||||
typedef typename iterator::reference reference_t;
|
typedef typename iterator::reference reference_t;
|
||||||
|
|
||||||
constexpr iterator() noexcept = default;
|
iterator() noexcept = default;
|
||||||
|
|
||||||
explicit iterator( pull_coroutine< T & > * c) noexcept :
|
explicit iterator( pull_coroutine< T & > * c) noexcept :
|
||||||
c_{ c } {
|
c_{ c } {
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
#include <exception>
|
#include <exception>
|
||||||
|
|
||||||
#include <boost/config.hpp>
|
#include <boost/config.hpp>
|
||||||
#include <boost/context/execution_context.hpp>
|
#include <boost/context/continuation.hpp>
|
||||||
|
|
||||||
#include <boost/coroutine2/detail/state.hpp>
|
#include <boost/coroutine2/detail/state.hpp>
|
||||||
|
|
||||||
@ -24,7 +24,7 @@ namespace detail {
|
|||||||
|
|
||||||
template< typename T >
|
template< typename T >
|
||||||
struct push_coroutine< T >::control_block {
|
struct push_coroutine< T >::control_block {
|
||||||
boost::context::execution_context< T * > ctx;
|
boost::context::continuation c;
|
||||||
typename pull_coroutine< T >::control_block * other;
|
typename pull_coroutine< T >::control_block * other;
|
||||||
state_t state;
|
state_t state;
|
||||||
std::exception_ptr except;
|
std::exception_ptr except;
|
||||||
@ -34,7 +34,7 @@ struct push_coroutine< T >::control_block {
|
|||||||
template< typename StackAllocator, typename Fn >
|
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::execution_context< T * > &) noexcept;
|
control_block( typename pull_coroutine< T >::control_block *, boost::context::continuation &) noexcept;
|
||||||
|
|
||||||
control_block( control_block &) = delete;
|
control_block( control_block &) = delete;
|
||||||
control_block & operator=( control_block &) = delete;
|
control_block & operator=( control_block &) = delete;
|
||||||
@ -50,7 +50,7 @@ struct push_coroutine< T >::control_block {
|
|||||||
|
|
||||||
template< typename T >
|
template< typename T >
|
||||||
struct push_coroutine< T & >::control_block {
|
struct push_coroutine< T & >::control_block {
|
||||||
boost::context::execution_context< T * > ctx;
|
boost::context::continuation c;
|
||||||
typename pull_coroutine< T & >::control_block * other;
|
typename pull_coroutine< T & >::control_block * other;
|
||||||
state_t state;
|
state_t state;
|
||||||
std::exception_ptr except;
|
std::exception_ptr except;
|
||||||
@ -60,7 +60,7 @@ struct push_coroutine< T & >::control_block {
|
|||||||
template< typename StackAllocator, typename Fn >
|
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::execution_context< T * > &) noexcept;
|
control_block( typename pull_coroutine< T & >::control_block *, boost::context::continuation &) noexcept;
|
||||||
|
|
||||||
control_block( control_block &) = delete;
|
control_block( control_block &) = delete;
|
||||||
control_block & operator=( 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 {
|
struct push_coroutine< void >::control_block {
|
||||||
boost::context::execution_context< void > ctx;
|
boost::context::continuation c;
|
||||||
pull_coroutine< void >::control_block * other;
|
pull_coroutine< void >::control_block * other;
|
||||||
state_t state;
|
state_t state;
|
||||||
std::exception_ptr except;
|
std::exception_ptr except;
|
||||||
@ -83,7 +83,7 @@ struct push_coroutine< void >::control_block {
|
|||||||
template< typename StackAllocator, typename Fn >
|
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::execution_context< void > &) noexcept;
|
control_block( pull_coroutine< void >::control_block *, boost::context::continuation &) noexcept;
|
||||||
|
|
||||||
control_block( control_block &) = delete;
|
control_block( control_block &) = delete;
|
||||||
control_block & operator=( control_block &) = delete;
|
control_block & operator=( control_block &) = delete;
|
408
include/boost/coroutine2/detail/push_control_block_cc.ipp
Normal file
408
include/boost/coroutine2/detail/push_control_block_cc.ipp
Normal file
@ -0,0 +1,408 @@
|
|||||||
|
|
||||||
|
// 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 <memory>
|
||||||
|
|
||||||
|
#include <boost/assert.hpp>
|
||||||
|
#include <boost/config.hpp>
|
||||||
|
|
||||||
|
#include <boost/context/continuation.hpp>
|
||||||
|
|
||||||
|
#include <boost/coroutine2/detail/config.hpp>
|
||||||
|
#include <boost/coroutine2/detail/forced_unwind.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::continuation c = std::move( cb->c);
|
||||||
|
// destroy control structure
|
||||||
|
cb->~control_block();
|
||||||
|
// destroy coroutine's stack
|
||||||
|
cb->state |= state_t::destroy;
|
||||||
|
boost::context::resume( std::move( c) );
|
||||||
|
}
|
||||||
|
|
||||||
|
template< typename T >
|
||||||
|
template< typename StackAllocator, typename Fn >
|
||||||
|
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,
|
||||||
|
std::move(
|
||||||
|
std::bind(
|
||||||
|
[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 = boost::context::resume( std::move( other->c) );
|
||||||
|
// set transferred value
|
||||||
|
if ( boost::context::data_available( other->c) ) {
|
||||||
|
synthesized_cb.set( boost::context::transfer_data< T >( other->c) );
|
||||||
|
} 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 boost::context::resume( std::move( other->c) );
|
||||||
|
},
|
||||||
|
std::forward< Fn >( fn),
|
||||||
|
std::placeholders::_1) ) );
|
||||||
|
#else
|
||||||
|
c = boost::context::callcc(
|
||||||
|
std::allocator_arg, palloc, salloc,
|
||||||
|
[this,fn_=std::forward< Fn >( 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 = boost::context::resume( std::move( other->c) );
|
||||||
|
// set transferred value
|
||||||
|
if ( boost::context::data_available( other->c) ) {
|
||||||
|
synthesized_cb.set( boost::context::transfer_data< T >( other->c) );
|
||||||
|
} 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 boost::context::resume( std::move( other->c) );
|
||||||
|
});
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
template< typename T >
|
||||||
|
push_coroutine< T >::control_block::control_block( typename pull_coroutine< T >::control_block * cb,
|
||||||
|
boost::context::continuation & c_) noexcept :
|
||||||
|
c{ std::move( c_) },
|
||||||
|
other{ cb },
|
||||||
|
state{ state_t::none },
|
||||||
|
except{} {
|
||||||
|
}
|
||||||
|
|
||||||
|
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& data) {
|
||||||
|
// pass an pointer to other context
|
||||||
|
c = boost::context::resume( std::move( c), data);
|
||||||
|
if ( except) {
|
||||||
|
std::rethrow_exception( except);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template< typename T >
|
||||||
|
void
|
||||||
|
push_coroutine< T >::control_block::resume( T && data) {
|
||||||
|
// pass an pointer to other context
|
||||||
|
c = boost::context::resume( std::move( c), std::move( data) );
|
||||||
|
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::continuation c = std::move( cb->c);
|
||||||
|
// destroy control structure
|
||||||
|
cb->~control_block();
|
||||||
|
// destroy coroutine's stack
|
||||||
|
cb->state |= state_t::destroy;
|
||||||
|
boost::context::resume( std::move( c) );
|
||||||
|
}
|
||||||
|
|
||||||
|
template< typename T >
|
||||||
|
template< typename StackAllocator, typename Fn >
|
||||||
|
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,
|
||||||
|
std::move(
|
||||||
|
std::bind(
|
||||||
|
[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 = boost::context::resume( std::move( other->c) );
|
||||||
|
// set transferred value
|
||||||
|
if ( boost::context::data_available( other->c) ) {
|
||||||
|
synthesized_cb.set( boost::context::transfer_data< T & >( other->c) );
|
||||||
|
} 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 boost::context::resume( std::move( other->c) );
|
||||||
|
},
|
||||||
|
std::forward< Fn >( fn),
|
||||||
|
std::placeholders::_1) ) );
|
||||||
|
#else
|
||||||
|
c = boost::context::callcc(
|
||||||
|
std::allocator_arg, palloc, salloc,
|
||||||
|
[this,fn_=std::forward< Fn >( 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 = boost::context::resume( std::move( other->c) );
|
||||||
|
// set transferred value
|
||||||
|
if ( boost::context::data_available( other->c) ) {
|
||||||
|
synthesized_cb.set( boost::context::transfer_data< T & >( other->c) );
|
||||||
|
} 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 boost::context::resume( std::move( other->c) );
|
||||||
|
});
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
template< typename T >
|
||||||
|
push_coroutine< T & >::control_block::control_block( typename pull_coroutine< T & >::control_block * cb,
|
||||||
|
boost::context::continuation & c_) noexcept :
|
||||||
|
c{ std::move( c_) },
|
||||||
|
other{ cb },
|
||||||
|
state{ state_t::none },
|
||||||
|
except{} {
|
||||||
|
}
|
||||||
|
|
||||||
|
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) {
|
||||||
|
// pass an pointer to other context
|
||||||
|
c = boost::context::resume( std::move( c), std::ref( 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::continuation c = std::move( cb->c);
|
||||||
|
// destroy control structure
|
||||||
|
cb->~control_block();
|
||||||
|
// destroy coroutine's stack
|
||||||
|
cb->state |= state_t::destroy;
|
||||||
|
boost::context::resume( std::move( c) );
|
||||||
|
}
|
||||||
|
|
||||||
|
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{} {
|
||||||
|
#if defined(BOOST_NO_CXX14_GENERIC_LAMBDAS)
|
||||||
|
c = boost::context::callcc(
|
||||||
|
std::allocator_arg, palloc, salloc,
|
||||||
|
std::move(
|
||||||
|
std::bind(
|
||||||
|
[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 = boost::context::resume( std::move( other->c) );
|
||||||
|
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 boost::context::resume( std::move( other->c) );
|
||||||
|
},
|
||||||
|
std::forward< Fn >( fn),
|
||||||
|
std::placeholders::_1) ) );
|
||||||
|
#else
|
||||||
|
c = boost::context::callcc(
|
||||||
|
std::allocator_arg, palloc, salloc,
|
||||||
|
[this,fn_=std::forward< Fn >( 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 = boost::context::resume( std::move( other->c) );
|
||||||
|
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 boost::context::resume( std::move( other->c) );
|
||||||
|
});
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
inline
|
||||||
|
push_coroutine< void >::control_block::control_block( pull_coroutine< void >::control_block * cb,
|
||||||
|
boost::context::continuation & c_) noexcept :
|
||||||
|
c{ std::move( c_) },
|
||||||
|
other{ cb },
|
||||||
|
state{ state_t::none },
|
||||||
|
except{} {
|
||||||
|
}
|
||||||
|
|
||||||
|
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() {
|
||||||
|
c = boost::context::resume( std::move( c) );
|
||||||
|
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
|
@ -1,392 +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 <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/forced_unwind.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< T * > ctx = std::move( cb->ctx);
|
|
||||||
// destroy control structure
|
|
||||||
cb->~control_block();
|
|
||||||
// destroy coroutine's stack
|
|
||||||
cb->state |= state_t::destroy;
|
|
||||||
ctx( nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
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,
|
|
||||||
std::move(
|
|
||||||
std::bind(
|
|
||||||
[this]( typename std::decay< Fn >::type & fn_, boost::context::execution_context< T * > && ctx, T * data) mutable {
|
|
||||||
// create synthesized pull_coroutine< T >
|
|
||||||
typename pull_coroutine< T >::control_block synthesized_cb{ this, ctx };
|
|
||||||
pull_coroutine< T > synthesized{ & synthesized_cb };
|
|
||||||
other = & synthesized_cb;
|
|
||||||
// set transferred value
|
|
||||||
synthesized_cb.set( data);
|
|
||||||
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 to ctx
|
|
||||||
auto result = other->ctx( nullptr);
|
|
||||||
other->ctx = std::move( std::get< 0 >( result) );
|
|
||||||
return std::move( other->ctx);
|
|
||||||
},
|
|
||||||
std::forward< Fn >( fn),
|
|
||||||
std::placeholders::_1,
|
|
||||||
std::placeholders::_2))},
|
|
||||||
#else
|
|
||||||
ctx{ std::allocator_arg, palloc, salloc,
|
|
||||||
[this,fn_=std::forward< Fn >( fn)]( boost::context::execution_context< T * > && ctx, T * data) mutable {
|
|
||||||
// create synthesized pull_coroutine< T >
|
|
||||||
typename pull_coroutine< T >::control_block synthesized_cb{ this, ctx };
|
|
||||||
pull_coroutine< T > synthesized{ & synthesized_cb };
|
|
||||||
other = & synthesized_cb;
|
|
||||||
// set transferred value
|
|
||||||
synthesized_cb.set( data);
|
|
||||||
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 to ctx
|
|
||||||
auto result = other->ctx( nullptr);
|
|
||||||
other->ctx = std::move( std::get< 0 >( result) );
|
|
||||||
return std::move( other->ctx);
|
|
||||||
}},
|
|
||||||
#endif
|
|
||||||
other{ nullptr },
|
|
||||||
state{ state_t::unwind },
|
|
||||||
except{} {
|
|
||||||
}
|
|
||||||
|
|
||||||
template< typename T >
|
|
||||||
push_coroutine< T >::control_block::control_block( typename pull_coroutine< T >::control_block * cb,
|
|
||||||
boost::context::execution_context< T * > & ctx_) noexcept :
|
|
||||||
ctx{ std::move( ctx_) },
|
|
||||||
other{ cb },
|
|
||||||
state{ state_t::none },
|
|
||||||
except{} {
|
|
||||||
}
|
|
||||||
|
|
||||||
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& data) {
|
|
||||||
// pass an pointer to other context
|
|
||||||
auto result = ctx( const_cast< T * >( & data) );
|
|
||||||
ctx = std::move( std::get< 0 >( result) );
|
|
||||||
if ( except) {
|
|
||||||
std::rethrow_exception( except);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template< typename T >
|
|
||||||
void
|
|
||||||
push_coroutine< T >::control_block::resume( T && data) {
|
|
||||||
// pass an pointer to other context
|
|
||||||
auto result = ctx( std::addressof( data) );
|
|
||||||
ctx = std::move( std::get< 0 >( result) );
|
|
||||||
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< T * > ctx = std::move( cb->ctx);
|
|
||||||
// destroy control structure
|
|
||||||
cb->~control_block();
|
|
||||||
// destroy coroutine's stack
|
|
||||||
cb->state |= state_t::destroy;
|
|
||||||
ctx( nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
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,
|
|
||||||
std::move(
|
|
||||||
std::bind(
|
|
||||||
[this]( typename std::decay< Fn >::type & fn_, boost::context::execution_context< T * > && ctx, T * data) mutable {
|
|
||||||
// create synthesized pull_coroutine< T & >
|
|
||||||
typename pull_coroutine< T & >::control_block synthesized_cb{ this, ctx };
|
|
||||||
pull_coroutine< T & > synthesized{ & synthesized_cb };
|
|
||||||
other = & synthesized_cb;
|
|
||||||
// set transferred value
|
|
||||||
synthesized_cb.t = data;
|
|
||||||
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 to ctx
|
|
||||||
auto result = other->ctx( nullptr);
|
|
||||||
other->ctx = std::move( std::get< 0 >( result) );
|
|
||||||
return std::move( other->ctx);
|
|
||||||
},
|
|
||||||
std::forward< Fn >( fn),
|
|
||||||
std::placeholders::_1,
|
|
||||||
std::placeholders::_2))},
|
|
||||||
#else
|
|
||||||
ctx{ std::allocator_arg, palloc, salloc,
|
|
||||||
[this,fn_=std::forward< Fn >( fn)]( boost::context::execution_context< T * > && ctx, T * data) mutable {
|
|
||||||
// create synthesized pull_coroutine< T & >
|
|
||||||
typename pull_coroutine< T & >::control_block synthesized_cb{ this, ctx };
|
|
||||||
pull_coroutine< T & > synthesized{ & synthesized_cb };
|
|
||||||
other = & synthesized_cb;
|
|
||||||
// set transferred value
|
|
||||||
synthesized_cb.t = data;
|
|
||||||
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 to ctx
|
|
||||||
auto result = other->ctx( nullptr);
|
|
||||||
other->ctx = std::move( std::get< 0 >( result) );
|
|
||||||
return std::move( other->ctx);
|
|
||||||
}},
|
|
||||||
#endif
|
|
||||||
other{ nullptr },
|
|
||||||
state{ state_t::unwind },
|
|
||||||
except{} {
|
|
||||||
}
|
|
||||||
|
|
||||||
template< typename T >
|
|
||||||
push_coroutine< T & >::control_block::control_block( typename pull_coroutine< T & >::control_block * cb,
|
|
||||||
boost::context::execution_context< T * > & ctx_) noexcept :
|
|
||||||
ctx{ std::move( ctx_) },
|
|
||||||
other{ cb },
|
|
||||||
state{ state_t::none },
|
|
||||||
except{} {
|
|
||||||
}
|
|
||||||
|
|
||||||
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) {
|
|
||||||
// pass an pointer to other context
|
|
||||||
auto result = ctx( const_cast< typename std::remove_const< T >::type * >( std::addressof( t) ) );
|
|
||||||
ctx = std::move( std::get< 0 >( result) );
|
|
||||||
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< void > ctx = std::move( cb->ctx);
|
|
||||||
// destroy control structure
|
|
||||||
cb->~control_block();
|
|
||||||
// destroy coroutine's stack
|
|
||||||
cb->state |= state_t::destroy;
|
|
||||||
ctx();
|
|
||||||
}
|
|
||||||
|
|
||||||
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,
|
|
||||||
std::move(
|
|
||||||
std::bind(
|
|
||||||
[this]( typename std::decay< Fn >::type & fn_, boost::context::execution_context< void > && ctx) mutable {
|
|
||||||
// create synthesized pull_coroutine< void >
|
|
||||||
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 {
|
|
||||||
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 to ctx
|
|
||||||
other->ctx = other->ctx();
|
|
||||||
return std::move( other->ctx);
|
|
||||||
},
|
|
||||||
std::forward< Fn >( fn),
|
|
||||||
std::placeholders::_1))},
|
|
||||||
#else
|
|
||||||
ctx{ std::allocator_arg, palloc, salloc,
|
|
||||||
[this,fn_=std::forward< Fn >( fn)]( boost::context::execution_context< void > && ctx) mutable {
|
|
||||||
// create synthesized pull_coroutine< void >
|
|
||||||
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 {
|
|
||||||
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 to ctx
|
|
||||||
other->ctx = other->ctx();
|
|
||||||
return std::move( other->ctx);
|
|
||||||
}},
|
|
||||||
#endif
|
|
||||||
other{ nullptr },
|
|
||||||
state{ state_t::unwind },
|
|
||||||
except{} {
|
|
||||||
}
|
|
||||||
|
|
||||||
inline
|
|
||||||
push_coroutine< void >::control_block::control_block( pull_coroutine< void >::control_block * cb,
|
|
||||||
boost::context::execution_context< void > & ctx_) noexcept :
|
|
||||||
ctx{ std::move( ctx_) },
|
|
||||||
other{ cb },
|
|
||||||
state{ state_t::none },
|
|
||||||
except{} {
|
|
||||||
}
|
|
||||||
|
|
||||||
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() {
|
|
||||||
ctx = 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
|
|
@ -72,14 +72,14 @@ public:
|
|||||||
push_coroutine< T > * c_{ nullptr };
|
push_coroutine< T > * c_{ nullptr };
|
||||||
|
|
||||||
public:
|
public:
|
||||||
constexpr iterator() noexcept = default;
|
iterator() noexcept = default;
|
||||||
|
|
||||||
explicit iterator( push_coroutine< T > * c) noexcept :
|
explicit iterator( push_coroutine< T > * c) noexcept :
|
||||||
c_{ c } {
|
c_{ c } {
|
||||||
}
|
}
|
||||||
|
|
||||||
iterator & operator=( T t) {
|
iterator & operator=( T t) {
|
||||||
BOOST_ASSERT( c_);
|
BOOST_ASSERT( nullptr != c_);
|
||||||
if ( ! ( * c_)( t) ) {
|
if ( ! ( * c_)( t) ) {
|
||||||
c_ = nullptr;
|
c_ = nullptr;
|
||||||
}
|
}
|
||||||
@ -150,14 +150,14 @@ public:
|
|||||||
push_coroutine< T & > * c_{ nullptr };
|
push_coroutine< T & > * c_{ nullptr };
|
||||||
|
|
||||||
public:
|
public:
|
||||||
constexpr iterator() noexcept = default;
|
iterator() noexcept = default;
|
||||||
|
|
||||||
explicit iterator( push_coroutine< T & > * c) noexcept :
|
explicit iterator( push_coroutine< T & > * c) noexcept :
|
||||||
c_{ c } {
|
c_{ c } {
|
||||||
}
|
}
|
||||||
|
|
||||||
iterator & operator=( T & t) {
|
iterator & operator=( T & t) {
|
||||||
BOOST_ASSERT( c_);
|
BOOST_ASSERT( nullptr != c_);
|
||||||
if ( ! ( * c_)( t) ) {
|
if ( ! ( * c_)( t) ) {
|
||||||
c_ = nullptr;
|
c_ = nullptr;
|
||||||
}
|
}
|
||||||
|
@ -24,7 +24,7 @@ int value1 = 0;
|
|||||||
std::string value2 = "";
|
std::string value2 = "";
|
||||||
bool value3 = false;
|
bool value3 = false;
|
||||||
double value4 = .0;
|
double value4 = .0;
|
||||||
int * value5 = 0;
|
int * value5 = nullptr;
|
||||||
int& value6 = value1;
|
int& value6 = value1;
|
||||||
int& value7 = value1;
|
int& value7 = value1;
|
||||||
int value8 = 0;
|
int value8 = 0;
|
||||||
@ -171,7 +171,7 @@ void f91( coro::coroutine< int const* >::pull_type & c)
|
|||||||
|
|
||||||
void f10( coro::coroutine< int & >::pull_type & c)
|
void f10( coro::coroutine< int & >::pull_type & c)
|
||||||
{
|
{
|
||||||
int const& i = c.get();
|
int & i = c.get();
|
||||||
value5 = const_cast< int * >( & i);
|
value5 = const_cast< int * >( & i);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -370,7 +370,7 @@ void test_fp()
|
|||||||
|
|
||||||
void test_ptr()
|
void test_ptr()
|
||||||
{
|
{
|
||||||
value5 = 0;
|
value5 = nullptr;
|
||||||
|
|
||||||
int a = 3;
|
int a = 3;
|
||||||
coro::coroutine< int * >::push_type coro( f9);
|
coro::coroutine< int * >::push_type coro( f9);
|
||||||
@ -382,7 +382,7 @@ void test_ptr()
|
|||||||
|
|
||||||
void test_const_ptr()
|
void test_const_ptr()
|
||||||
{
|
{
|
||||||
value5 = 0;
|
value5 = nullptr;
|
||||||
|
|
||||||
int a = 3;
|
int a = 3;
|
||||||
coro::coroutine< int const* >::push_type coro( f91);
|
coro::coroutine< int const* >::push_type coro( f91);
|
||||||
@ -394,19 +394,20 @@ void test_const_ptr()
|
|||||||
|
|
||||||
void test_ref()
|
void test_ref()
|
||||||
{
|
{
|
||||||
value5 = 0;
|
value5 = nullptr;
|
||||||
|
|
||||||
int a = 3;
|
int a_ = 3;
|
||||||
|
int & a = a_;
|
||||||
coro::coroutine< int & >::push_type coro( f10);
|
coro::coroutine< int & >::push_type coro( f10);
|
||||||
BOOST_CHECK( coro);
|
BOOST_CHECK( coro);
|
||||||
coro( a);
|
coro( std::ref( a) );
|
||||||
BOOST_CHECK( ! coro);
|
BOOST_CHECK( ! coro);
|
||||||
BOOST_CHECK_EQUAL( & a, value5);
|
BOOST_CHECK_EQUAL( & a, value5);
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_const_ref()
|
void test_const_ref()
|
||||||
{
|
{
|
||||||
value5 = 0;
|
value5 = nullptr;
|
||||||
|
|
||||||
int a = 3;
|
int a = 3;
|
||||||
coro::coroutine< int const& >::push_type coro( f101);
|
coro::coroutine< int const& >::push_type coro( f101);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user