summaryrefslogtreecommitdiff
path: root/boost/coroutine2/detail/pull_control_block.ipp
diff options
context:
space:
mode:
Diffstat (limited to 'boost/coroutine2/detail/pull_control_block.ipp')
-rw-r--r--boost/coroutine2/detail/pull_control_block.ipp221
1 files changed, 131 insertions, 90 deletions
diff --git a/boost/coroutine2/detail/pull_control_block.ipp b/boost/coroutine2/detail/pull_control_block.ipp
index fd806ecb21..536e5e6a94 100644
--- a/boost/coroutine2/detail/pull_control_block.ipp
+++ b/boost/coroutine2/detail/pull_control_block.ipp
@@ -8,6 +8,7 @@
#define BOOST_COROUTINES2_DETAIL_PULL_CONTROL_BLOCK_IPP
#include <exception>
+#include <memory>
#include <boost/assert.hpp>
#include <boost/config.hpp>
@@ -33,42 +34,46 @@ template< typename StackAllocator, typename Fn >
pull_coroutine< T >::control_block::control_block( context::preallocated palloc, StackAllocator salloc,
Fn && fn_, bool preserve_fpu_) :
other( nullptr),
- caller( boost::context::execution_context::current() ),
- callee( palloc, salloc,
- [=,fn=std::forward< Fn >( fn_)] () mutable -> decltype( auto) {
- // create synthesized push_coroutine< T >
- typename push_coroutine< T >::control_block synthesized_cb( this);
- push_coroutine< T > synthesized( & synthesized_cb);
- other = & synthesized_cb;
- try {
- // call coroutine-fn with synthesized push_coroutine as argument
- fn( synthesized);
- } catch ( forced_unwind const&) {
- // do nothing for unwinding exception
- } catch (...) {
- // store other exceptions in exception-pointer
- except = std::current_exception();
- }
- // set termination flags
- state |= static_cast< int >( state_t::complete);
- // jump back to caller
- caller( preserve_fpu);
- BOOST_ASSERT_MSG( false, "pull_coroutine is complete");
- }),
+ ctx( std::allocator_arg, palloc, salloc,
+ [=,fn=std::forward< Fn >( fn_),ctx=boost::context::execution_context::current()] (void *) mutable -> void {
+ // create synthesized push_coroutine< T >
+ typename push_coroutine< T >::control_block synthesized_cb( this, ctx);
+ push_coroutine< T > synthesized( & synthesized_cb);
+ other = & synthesized_cb;
+ try {
+ // call coroutine-fn with synthesized push_coroutine as argument
+ fn( synthesized);
+ } catch ( forced_unwind const&) {
+ // do nothing for unwinding exception
+ } catch (...) {
+ // store other exceptions in exception-pointer
+ except = std::current_exception();
+ }
+ // set termination flags
+ state |= static_cast< int >( state_t::complete);
+ // jump back to ctx
+ other->ctx( nullptr, preserve_fpu);
+ BOOST_ASSERT_MSG( false, "pull_coroutine is complete");
+ }),
preserve_fpu( preserve_fpu_),
state( static_cast< int >( state_t::unwind) ),
- except() {
- callee( preserve_fpu);
+ except(),
+ bvalid( false),
+ storage() {
+ // enter coroutine-fn in order to have first value available after ctor (of `*this`) returns
+ set( reinterpret_cast< T * >( ctx( nullptr, preserve_fpu) ) );
}
template< typename T >
-pull_coroutine< T >::control_block::control_block( typename push_coroutine< T >::control_block * cb) :
+pull_coroutine< T >::control_block::control_block( typename push_coroutine< T >::control_block * cb,
+ boost::context::execution_context const& ctx_) :
other( cb),
- caller( other->callee),
- callee( other->caller),
+ ctx( ctx_),
preserve_fpu( other->preserve_fpu),
state( 0),
- except() {
+ except(),
+ bvalid( false),
+ storage() {
}
template< typename T >
@@ -77,14 +82,19 @@ pull_coroutine< T >::control_block::~control_block() {
0 != ( state & static_cast< int >( state_t::unwind) ) ) {
// set early-exit flag
state |= static_cast< int >( state_t::early_exit);
- callee( preserve_fpu);
+ ctx( nullptr, preserve_fpu);
+ }
+ // destroy data if it set
+ if ( bvalid) {
+ reinterpret_cast< T const* >( storage)->~T();
}
}
template< typename T >
void
pull_coroutine< T >::control_block::resume() {
- callee( preserve_fpu);
+ other->ctx = boost::context::execution_context::current();
+ set( reinterpret_cast< T * >( ctx( nullptr, preserve_fpu) ) );
if ( except) {
std::rethrow_exception( except);
}
@@ -95,9 +105,30 @@ pull_coroutine< T >::control_block::resume() {
}
template< typename T >
+void
+pull_coroutine< T >::control_block::set( T * t) {
+ // destroy data if it set
+ if ( bvalid) {
+ reinterpret_cast< T const* >( storage)->~T();
+ }
+ if ( nullptr != t) {
+ new ( storage) T( std::move( * t) ); // FIXME: differrentiation between move/copy
+ bvalid = true;
+ } else {
+ bvalid = false;
+ }
+}
+
+template< typename T >
+T &
+pull_coroutine< T >::control_block::get() {
+ return * reinterpret_cast< T * >( storage);
+}
+
+template< typename T >
bool
pull_coroutine< T >::control_block::valid() const noexcept {
- return nullptr != other && nullptr != other->t && 0 == ( state & static_cast< int >( state_t::complete) );
+ return nullptr != other && 0 == ( state & static_cast< int >( state_t::complete) ) && bvalid;
}
@@ -108,42 +139,44 @@ template< typename StackAllocator, typename Fn >
pull_coroutine< T & >::control_block::control_block( context::preallocated palloc, StackAllocator salloc,
Fn && fn_, bool preserve_fpu_) :
other( nullptr),
- caller( boost::context::execution_context::current() ),
- callee( palloc, salloc,
- [=,fn=std::forward< Fn >( fn_)] () mutable -> decltype( auto) {
- // create synthesized push_coroutine< T >
- typename push_coroutine< T & >::control_block synthesized_cb( this);
- push_coroutine< T & > synthesized( & synthesized_cb);
- other = & synthesized_cb;
- try {
- // call coroutine-fn with synthesized push_coroutine as argument
- fn( synthesized);
- } catch ( forced_unwind const&) {
- // do nothing for unwinding exception
- } catch (...) {
- // store other exceptions in exception-pointer
- except = std::current_exception();
- }
- // set termination flags
- state |= static_cast< int >( state_t::complete);
- // jump back to caller
- caller( preserve_fpu);
- BOOST_ASSERT_MSG( false, "pull_coroutine is complete");
- }),
+ ctx( std::allocator_arg, palloc, salloc,
+ [=,fn=std::forward< Fn >( fn_),ctx=boost::context::execution_context::current()] (void *) mutable -> void {
+ // create synthesized push_coroutine< T >
+ typename push_coroutine< T & >::control_block synthesized_cb( this, ctx);
+ push_coroutine< T & > synthesized( & synthesized_cb);
+ other = & synthesized_cb;
+ try {
+ // call coroutine-fn with synthesized push_coroutine as argument
+ fn( synthesized);
+ } catch ( forced_unwind const&) {
+ // do nothing for unwinding exception
+ } catch (...) {
+ // store other exceptions in exception-pointer
+ except = std::current_exception();
+ }
+ // set termination flags
+ state |= static_cast< int >( state_t::complete);
+ // jump back to ctx
+ other->ctx( nullptr, preserve_fpu);
+ BOOST_ASSERT_MSG( false, "pull_coroutine is complete");
+ }),
preserve_fpu( preserve_fpu_),
state( static_cast< int >( state_t::unwind) ),
- except() {
- callee( preserve_fpu);
+ except(),
+ t( nullptr) {
+ // enter coroutine-fn in order to have first value available after ctor (of `*this`) returns
+ t = reinterpret_cast< T * >( ctx( nullptr, preserve_fpu) );
}
template< typename T >
-pull_coroutine< T & >::control_block::control_block( typename push_coroutine< T & >::control_block * cb) :
+pull_coroutine< T & >::control_block::control_block( typename push_coroutine< T & >::control_block * cb,
+ boost::context::execution_context const& ctx_) :
other( cb),
- caller( other->callee),
- callee( other->caller),
+ ctx( ctx_),
preserve_fpu( other->preserve_fpu),
state( 0),
- except() {
+ except(),
+ t( nullptr) {
}
template< typename T >
@@ -152,14 +185,15 @@ pull_coroutine< T & >::control_block::~control_block() {
0 != ( state & static_cast< int >( state_t::unwind) ) ) {
// set early-exit flag
state |= static_cast< int >( state_t::early_exit);
- callee( preserve_fpu);
+ ctx( nullptr, preserve_fpu);
}
}
template< typename T >
void
pull_coroutine< T & >::control_block::resume() {
- callee( preserve_fpu);
+ other->ctx = boost::context::execution_context::current();
+ t = reinterpret_cast< T * >( ctx( nullptr, preserve_fpu) );
if ( except) {
std::rethrow_exception( except);
}
@@ -170,9 +204,15 @@ pull_coroutine< T & >::control_block::resume() {
}
template< typename T >
+T &
+pull_coroutine< T & >::control_block::get() {
+ return * reinterpret_cast< T * >( t);
+}
+
+template< typename T >
bool
pull_coroutine< T & >::control_block::valid() const noexcept {
- return nullptr != other && nullptr != other->t && 0 == ( state & static_cast< int >( state_t::complete) );
+ return nullptr != other && 0 == ( state & static_cast< int >( state_t::complete) ) && nullptr != t;
}
@@ -182,39 +222,39 @@ template< typename StackAllocator, typename Fn >
pull_coroutine< void >::control_block::control_block( context::preallocated palloc, StackAllocator salloc,
Fn && fn_, bool preserve_fpu_) :
other( nullptr),
- caller( boost::context::execution_context::current() ),
- callee( palloc, salloc,
- [=,fn=std::forward< Fn >( fn_)] () mutable -> decltype( auto) {
- // create synthesized push_coroutine< T >
- typename push_coroutine< void >::control_block synthesized_cb( this);
- push_coroutine< void > synthesized( & synthesized_cb);
- other = & synthesized_cb;
- try {
- // call coroutine-fn with synthesized push_coroutine as argument
- fn( synthesized);
- } catch ( forced_unwind const&) {
- // do nothing for unwinding exception
- } catch (...) {
- // store other exceptions in exception-pointer
- except = std::current_exception();
- }
- // set termination flags
- state |= static_cast< int >( state_t::complete);
- // jump back to caller
- caller( preserve_fpu);
- BOOST_ASSERT_MSG( false, "pull_coroutine is complete");
- }),
+ ctx( std::allocator_arg, palloc, salloc,
+ [=,fn=std::forward< Fn >( fn_),ctx=boost::context::execution_context::current()] (void *) mutable -> void {
+ // create synthesized push_coroutine< T >
+ typename push_coroutine< void >::control_block synthesized_cb( this, ctx);
+ push_coroutine< void > synthesized( & synthesized_cb);
+ other = & synthesized_cb;
+ try {
+ // call coroutine-fn with synthesized push_coroutine as argument
+ fn( synthesized);
+ } catch ( forced_unwind const&) {
+ // do nothing for unwinding exception
+ } catch (...) {
+ // store other exceptions in exception-pointer
+ except = std::current_exception();
+ }
+ // set termination flags
+ state |= static_cast< int >( state_t::complete);
+ // jump back to ctx
+ other->ctx( nullptr, preserve_fpu);
+ BOOST_ASSERT_MSG( false, "pull_coroutine is complete");
+ }),
preserve_fpu( preserve_fpu_),
state( static_cast< int >( state_t::unwind) ),
except() {
- callee( preserve_fpu);
+ // enter coroutine-fn in order to have first value available after ctor returns
+ ctx( nullptr, preserve_fpu);
}
inline
-pull_coroutine< void >::control_block::control_block( push_coroutine< void >::control_block * cb) :
+pull_coroutine< void >::control_block::control_block( push_coroutine< void >::control_block * cb,
+ boost::context::execution_context const& ctx_) :
other( cb),
- caller( other->callee),
- callee( other->caller),
+ ctx( ctx_),
preserve_fpu( other->preserve_fpu),
state( 0),
except() {
@@ -226,14 +266,15 @@ pull_coroutine< void >::control_block::~control_block() {
0 != ( state & static_cast< int >( state_t::unwind) ) ) {
// set early-exit flag
state |= static_cast< int >( state_t::early_exit);
- callee( preserve_fpu);
+ ctx( nullptr, preserve_fpu);
}
}
inline
void
pull_coroutine< void >::control_block::resume() {
- callee( preserve_fpu);
+ other->ctx = boost::context::execution_context::current();
+ ctx( nullptr, preserve_fpu);
if ( except) {
std::rethrow_exception( except);
}