do not enter coro-fn for push-coro's at destruction

- fixes #12221
This commit is contained in:
oliver Kowalke 2016-05-23 08:31:13 +02:00
parent b5ac9ba526
commit 0f24727718
6 changed files with 307 additions and 237 deletions

View File

@ -36,6 +36,7 @@ void
pull_coroutine< T >::control_block::destroy( control_block * cb) noexcept { pull_coroutine< T >::control_block::destroy( control_block * cb) noexcept {
boost::context::execution_context ctx = cb->ctx; boost::context::execution_context ctx = cb->ctx;
// destroy control structure // destroy control structure
cb->state |= state_t::destroy;
cb->~control_block(); cb->~control_block();
} }
@ -52,15 +53,17 @@ pull_coroutine< T >::control_block::control_block( context::preallocated palloc,
typename push_coroutine< T >::control_block synthesized_cb{ this, ctx }; typename push_coroutine< T >::control_block synthesized_cb{ this, ctx };
push_coroutine< T > synthesized{ & synthesized_cb }; push_coroutine< T > synthesized{ & synthesized_cb };
other = & synthesized_cb; other = & synthesized_cb;
try { if ( state_t::none == ( state & state_t::destroy) ) {
auto fn = std::move( fn_); try {
// call coroutine-fn with synthesized push_coroutine as argument auto fn = std::move( fn_);
fn( synthesized); // call coroutine-fn with synthesized push_coroutine as argument
} catch ( forced_unwind const&) { fn( synthesized);
// do nothing for unwinding exception } catch ( forced_unwind const&) {
} catch (...) { // do nothing for unwinding exception
// store other exceptions in exception-pointer } catch (...) {
except = std::current_exception(); // store other exceptions in exception-pointer
except = std::current_exception();
}
} }
// set termination flags // set termination flags
state |= state_t::complete; state |= state_t::complete;
@ -78,15 +81,17 @@ pull_coroutine< T >::control_block::control_block( context::preallocated palloc,
typename push_coroutine< T >::control_block synthesized_cb{ this, ctx }; typename push_coroutine< T >::control_block synthesized_cb{ this, ctx };
push_coroutine< T > synthesized{ & synthesized_cb }; push_coroutine< T > synthesized{ & synthesized_cb };
other = & synthesized_cb; other = & synthesized_cb;
try { if ( state_t::none == ( state & state_t::destroy) ) {
auto fn = std::move( fn_); try {
// call coroutine-fn with synthesized push_coroutine as argument auto fn = std::move( fn_);
fn( synthesized); // call coroutine-fn with synthesized push_coroutine as argument
} catch ( forced_unwind const&) { fn( synthesized);
// do nothing for unwinding exception } catch ( forced_unwind const&) {
} catch (...) { // do nothing for unwinding exception
// store other exceptions in exception-pointer } catch (...) {
except = std::current_exception(); // store other exceptions in exception-pointer
except = std::current_exception();
}
} }
// set termination flags // set termination flags
state |= state_t::complete; state |= state_t::complete;
@ -181,6 +186,7 @@ void
pull_coroutine< T & >::control_block::destroy( control_block * cb) noexcept { pull_coroutine< T & >::control_block::destroy( control_block * cb) noexcept {
boost::context::execution_context ctx = cb->ctx; boost::context::execution_context ctx = cb->ctx;
// destroy control structure // destroy control structure
cb->state |= state_t::destroy;
cb->~control_block(); cb->~control_block();
} }
@ -197,15 +203,17 @@ pull_coroutine< T & >::control_block::control_block( context::preallocated pallo
typename push_coroutine< T & >::control_block synthesized_cb{ this, ctx }; typename push_coroutine< T & >::control_block synthesized_cb{ this, ctx };
push_coroutine< T & > synthesized{ & synthesized_cb }; push_coroutine< T & > synthesized{ & synthesized_cb };
other = & synthesized_cb; other = & synthesized_cb;
try { if ( state_t::none == ( state & state_t::destroy) ) {
auto fn = std::move( fn_); try {
// call coroutine-fn with synthesized push_coroutine as argument auto fn = std::move( fn_);
fn( synthesized); // call coroutine-fn with synthesized push_coroutine as argument
} catch ( forced_unwind const&) { fn( synthesized);
// do nothing for unwinding exception } catch ( forced_unwind const&) {
} catch (...) { // do nothing for unwinding exception
// store other exceptions in exception-pointer } catch (...) {
except = std::current_exception(); // store other exceptions in exception-pointer
except = std::current_exception();
}
} }
// set termination flags // set termination flags
state |= state_t::complete; state |= state_t::complete;
@ -223,15 +231,17 @@ pull_coroutine< T & >::control_block::control_block( context::preallocated pallo
typename push_coroutine< T & >::control_block synthesized_cb{ this, ctx }; typename push_coroutine< T & >::control_block synthesized_cb{ this, ctx };
push_coroutine< T & > synthesized{ & synthesized_cb }; push_coroutine< T & > synthesized{ & synthesized_cb };
other = & synthesized_cb; other = & synthesized_cb;
try { if ( state_t::none == ( state & state_t::destroy) ) {
auto fn = std::move( fn_); try {
// call coroutine-fn with synthesized push_coroutine as argument auto fn = std::move( fn_);
fn( synthesized); // call coroutine-fn with synthesized push_coroutine as argument
} catch ( forced_unwind const&) { fn( synthesized);
// do nothing for unwinding exception } catch ( forced_unwind const&) {
} catch (...) { // do nothing for unwinding exception
// store other exceptions in exception-pointer } catch (...) {
except = std::current_exception(); // store other exceptions in exception-pointer
except = std::current_exception();
}
} }
// set termination flags // set termination flags
state |= state_t::complete; state |= state_t::complete;
@ -305,6 +315,7 @@ void
pull_coroutine< void >::control_block::destroy( control_block * cb) noexcept { pull_coroutine< void >::control_block::destroy( control_block * cb) noexcept {
boost::context::execution_context ctx = cb->ctx; boost::context::execution_context ctx = cb->ctx;
// destroy control structure // destroy control structure
cb->state |= state_t::destroy;
cb->~control_block(); cb->~control_block();
} }
@ -320,15 +331,17 @@ pull_coroutine< void >::control_block::control_block( context::preallocated pall
typename push_coroutine< void >::control_block synthesized_cb{ this, ctx }; typename push_coroutine< void >::control_block synthesized_cb{ this, ctx };
push_coroutine< void > synthesized{ & synthesized_cb }; push_coroutine< void > synthesized{ & synthesized_cb };
other = & synthesized_cb; other = & synthesized_cb;
try { if ( state_t::none == ( state & state_t::destroy) ) {
auto fn = std::move( fn_); try {
// call coroutine-fn with synthesized push_coroutine as argument auto fn = std::move( fn_);
fn( synthesized); // call coroutine-fn with synthesized push_coroutine as argument
} catch ( forced_unwind const&) { fn( synthesized);
// do nothing for unwinding exception } catch ( forced_unwind const&) {
} catch (...) { // do nothing for unwinding exception
// store other exceptions in exception-pointer } catch (...) {
except = std::current_exception(); // store other exceptions in exception-pointer
except = std::current_exception();
}
} }
// set termination flags // set termination flags
state |= state_t::complete; state |= state_t::complete;
@ -346,15 +359,17 @@ pull_coroutine< void >::control_block::control_block( context::preallocated pall
typename push_coroutine< void >::control_block synthesized_cb{ this, ctx }; typename push_coroutine< void >::control_block synthesized_cb{ this, ctx };
push_coroutine< void > synthesized{ & synthesized_cb }; push_coroutine< void > synthesized{ & synthesized_cb };
other = & synthesized_cb; other = & synthesized_cb;
try { if ( state_t::none == ( state & state_t::destroy) ) {
auto fn = std::move( fn_); try {
// call coroutine-fn with synthesized push_coroutine as argument auto fn = std::move( fn_);
fn( synthesized); // call coroutine-fn with synthesized push_coroutine as argument
} catch ( forced_unwind const&) { fn( synthesized);
// do nothing for unwinding exception } catch ( forced_unwind const&) {
} catch (...) { // do nothing for unwinding exception
// store other exceptions in exception-pointer } catch (...) {
except = std::current_exception(); // store other exceptions in exception-pointer
except = std::current_exception();
}
} }
// set termination flags // set termination flags
state |= state_t::complete; state |= state_t::complete;

View File

@ -37,6 +37,7 @@ pull_coroutine< T >::control_block::destroy( control_block * cb) noexcept {
// destroy control structure // destroy control structure
cb->~control_block(); cb->~control_block();
// destroy coroutine's stack // destroy coroutine's stack
cb->state |= state_t::destroy;
ctx( nullptr); ctx( nullptr);
} }
@ -53,15 +54,17 @@ pull_coroutine< T >::control_block::control_block( context::preallocated palloc,
typename push_coroutine< T >::control_block synthesized_cb{ this, ctx }; typename push_coroutine< T >::control_block synthesized_cb{ this, ctx };
push_coroutine< T > synthesized{ & synthesized_cb }; push_coroutine< T > synthesized{ & synthesized_cb };
other = & synthesized_cb; other = & synthesized_cb;
try { if ( state_t::none == ( state & state_t::destroy) ) {
auto fn = std::move( fn_); try {
// call coroutine-fn with synthesized push_coroutine as argument auto fn = std::move( fn_);
fn( synthesized); // call coroutine-fn with synthesized push_coroutine as argument
} catch ( boost::context::detail::forced_unwind const&) { fn( synthesized);
throw; } catch ( boost::context::detail::forced_unwind const&) {
} catch (...) { throw;
// store other exceptions in exception-pointer } catch (...) {
except = std::current_exception(); // store other exceptions in exception-pointer
except = std::current_exception();
}
} }
// set termination flags // set termination flags
state |= state_t::complete; state |= state_t::complete;
@ -80,15 +83,17 @@ pull_coroutine< T >::control_block::control_block( context::preallocated palloc,
typename push_coroutine< T >::control_block synthesized_cb{ this, ctx }; typename push_coroutine< T >::control_block synthesized_cb{ this, ctx };
push_coroutine< T > synthesized{ & synthesized_cb }; push_coroutine< T > synthesized{ & synthesized_cb };
other = & synthesized_cb; other = & synthesized_cb;
try { if ( state_t::none == ( state & state_t::destroy) ) {
auto fn = std::move( fn_); try {
// call coroutine-fn with synthesized push_coroutine as argument auto fn = std::move( fn_);
fn( synthesized); // call coroutine-fn with synthesized push_coroutine as argument
} catch ( boost::context::detail::forced_unwind const&) { fn( synthesized);
throw; } catch ( boost::context::detail::forced_unwind const&) {
} catch (...) { throw;
// store other exceptions in exception-pointer } catch (...) {
except = std::current_exception(); // store other exceptions in exception-pointer
except = std::current_exception();
}
} }
// set termination flags // set termination flags
state |= state_t::complete; state |= state_t::complete;
@ -184,6 +189,7 @@ pull_coroutine< T & >::control_block::destroy( control_block * cb) noexcept {
// destroy control structure // destroy control structure
cb->~control_block(); cb->~control_block();
// destroy coroutine's stack // destroy coroutine's stack
cb->state |= state_t::destroy;
ctx( nullptr); ctx( nullptr);
} }
@ -200,15 +206,17 @@ pull_coroutine< T & >::control_block::control_block( context::preallocated pallo
typename push_coroutine< T & >::control_block synthesized_cb{ this, ctx }; typename push_coroutine< T & >::control_block synthesized_cb{ this, ctx };
push_coroutine< T & > synthesized{ & synthesized_cb }; push_coroutine< T & > synthesized{ & synthesized_cb };
other = & synthesized_cb; other = & synthesized_cb;
try { if ( state_t::none == ( state & state_t::destroy) ) {
auto fn = std::move( fn_); try {
// call coroutine-fn with synthesized push_coroutine as argument auto fn = std::move( fn_);
fn( synthesized); // call coroutine-fn with synthesized push_coroutine as argument
} catch ( boost::context::detail::forced_unwind const&) { fn( synthesized);
throw; } catch ( boost::context::detail::forced_unwind const&) {
} catch (...) { throw;
// store other exceptions in exception-pointer } catch (...) {
except = std::current_exception(); // store other exceptions in exception-pointer
except = std::current_exception();
}
} }
// set termination flags // set termination flags
state |= state_t::complete; state |= state_t::complete;
@ -227,15 +235,17 @@ pull_coroutine< T & >::control_block::control_block( context::preallocated pallo
typename push_coroutine< T & >::control_block synthesized_cb{ this, ctx }; typename push_coroutine< T & >::control_block synthesized_cb{ this, ctx };
push_coroutine< T & > synthesized{ & synthesized_cb }; push_coroutine< T & > synthesized{ & synthesized_cb };
other = & synthesized_cb; other = & synthesized_cb;
try { if ( state_t::none == ( state & state_t::destroy) ) {
auto fn = std::move( fn_); try {
// call coroutine-fn with synthesized push_coroutine as argument auto fn = std::move( fn_);
fn( synthesized); // call coroutine-fn with synthesized push_coroutine as argument
} catch ( boost::context::detail::forced_unwind const&) { fn( synthesized);
throw; } catch ( boost::context::detail::forced_unwind const&) {
} catch (...) { throw;
// store other exceptions in exception-pointer } catch (...) {
except = std::current_exception(); // store other exceptions in exception-pointer
except = std::current_exception();
}
} }
// set termination flags // set termination flags
state |= state_t::complete; state |= state_t::complete;
@ -306,6 +316,7 @@ pull_coroutine< void >::control_block::destroy( control_block * cb) noexcept {
// destroy control structure // destroy control structure
cb->~control_block(); cb->~control_block();
// destroy coroutine's stack // destroy coroutine's stack
cb->state |= state_t::destroy;
ctx(); ctx();
} }
@ -321,15 +332,17 @@ pull_coroutine< void >::control_block::control_block( context::preallocated pall
typename push_coroutine< void >::control_block synthesized_cb{ this, ctx }; typename push_coroutine< void >::control_block synthesized_cb{ this, ctx };
push_coroutine< void > synthesized{ & synthesized_cb }; push_coroutine< void > synthesized{ & synthesized_cb };
other = & synthesized_cb; other = & synthesized_cb;
try { if ( state_t::none == ( state & state_t::destroy) ) {
auto fn = std::move( fn_); try {
// call coroutine-fn with synthesized push_coroutine as argument auto fn = std::move( fn_);
fn( synthesized); // call coroutine-fn with synthesized push_coroutine as argument
} catch ( boost::context::detail::forced_unwind const&) { fn( synthesized);
throw; } catch ( boost::context::detail::forced_unwind const&) {
} catch (...) { throw;
// store other exceptions in exception-pointer } catch (...) {
except = std::current_exception(); // store other exceptions in exception-pointer
except = std::current_exception();
}
} }
// set termination flags // set termination flags
state |= state_t::complete; state |= state_t::complete;
@ -346,15 +359,17 @@ pull_coroutine< void >::control_block::control_block( context::preallocated pall
typename push_coroutine< void >::control_block synthesized_cb{ this, ctx }; typename push_coroutine< void >::control_block synthesized_cb{ this, ctx };
push_coroutine< void > synthesized{ & synthesized_cb }; push_coroutine< void > synthesized{ & synthesized_cb };
other = & synthesized_cb; other = & synthesized_cb;
try { if ( state_t::none == ( state & state_t::destroy) ) {
auto fn = std::move( fn_); try {
// call coroutine-fn with synthesized push_coroutine as argument auto fn = std::move( fn_);
fn( synthesized); // call coroutine-fn with synthesized push_coroutine as argument
} catch ( boost::context::detail::forced_unwind const&) { fn( synthesized);
throw; } catch ( boost::context::detail::forced_unwind const&) {
} catch (...) { throw;
// store other exceptions in exception-pointer } catch (...) {
except = std::current_exception(); // store other exceptions in exception-pointer
except = std::current_exception();
}
} }
// set termination flags // set termination flags
state |= state_t::complete; state |= state_t::complete;

View File

@ -37,6 +37,7 @@ void
push_coroutine< T >::control_block::destroy( control_block * cb) noexcept { push_coroutine< T >::control_block::destroy( control_block * cb) noexcept {
boost::context::execution_context ctx = cb->ctx; boost::context::execution_context ctx = cb->ctx;
// destroy control structure // destroy control structure
cb->state |= state_t::destroy;
cb->~control_block(); cb->~control_block();
} }
@ -53,19 +54,21 @@ push_coroutine< T >::control_block::control_block( context::preallocated palloc,
typename pull_coroutine< T >::control_block synthesized_cb{ this, ctx }; typename pull_coroutine< T >::control_block synthesized_cb{ this, ctx };
pull_coroutine< T > synthesized{ & synthesized_cb }; pull_coroutine< T > synthesized{ & synthesized_cb };
other = & synthesized_cb; other = & synthesized_cb;
try { if ( state_t::none == ( state & state_t::destroy) ) {
// jump back to ctor try {
T * t = static_cast< T * >( ctx() ); // jump back to ctor
// set transferred value T * t = static_cast< T * >( ctx() );
synthesized_cb.set( t); // set transferred value
auto fn = std::move( fn_); synthesized_cb.set( t);
// call coroutine-fn with synthesized pull_coroutine as argument auto fn = std::move( fn_);
fn( synthesized); // call coroutine-fn with synthesized pull_coroutine as argument
} catch ( forced_unwind const&) { fn( synthesized);
// do nothing for unwinding exception } catch ( forced_unwind const&) {
} catch (...) { // do nothing for unwinding exception
// store other exceptions in exception-pointer } catch (...) {
except = std::current_exception(); // store other exceptions in exception-pointer
except = std::current_exception();
}
} }
// set termination flags // set termination flags
state |= state_t::complete; state |= state_t::complete;
@ -83,19 +86,21 @@ push_coroutine< T >::control_block::control_block( context::preallocated palloc,
typename pull_coroutine< T >::control_block synthesized_cb{ this, ctx }; typename pull_coroutine< T >::control_block synthesized_cb{ this, ctx };
pull_coroutine< T > synthesized{ & synthesized_cb }; pull_coroutine< T > synthesized{ & synthesized_cb };
other = & synthesized_cb; other = & synthesized_cb;
try { if ( state_t::none == ( state & state_t::destroy) ) {
// jump back to ctor try {
T * t = static_cast< T * >( ctx() ); // jump back to ctor
// set transferred value T * t = static_cast< T * >( ctx() );
synthesized_cb.set( t); // set transferred value
auto fn = std::move( fn_); synthesized_cb.set( t);
// call coroutine-fn with synthesized pull_coroutine as argument auto fn = std::move( fn_);
fn( synthesized); // call coroutine-fn with synthesized pull_coroutine as argument
} catch ( forced_unwind const&) { fn( synthesized);
// do nothing for unwinding exception } catch ( forced_unwind const&) {
} catch (...) { // do nothing for unwinding exception
// store other exceptions in exception-pointer } catch (...) {
except = std::current_exception(); // store other exceptions in exception-pointer
except = std::current_exception();
}
} }
// set termination flags // set termination flags
state |= state_t::complete; state |= state_t::complete;
@ -173,6 +178,7 @@ void
push_coroutine< T & >::control_block::destroy( control_block * cb) noexcept { push_coroutine< T & >::control_block::destroy( control_block * cb) noexcept {
boost::context::execution_context ctx = cb->ctx; boost::context::execution_context ctx = cb->ctx;
// destroy control structure // destroy control structure
cb->state |= state_t::destroy;
cb->~control_block(); cb->~control_block();
} }
@ -189,19 +195,21 @@ push_coroutine< T & >::control_block::control_block( context::preallocated pallo
typename pull_coroutine< T & >::control_block synthesized_cb{ this, ctx }; typename pull_coroutine< T & >::control_block synthesized_cb{ this, ctx };
pull_coroutine< T & > synthesized{ & synthesized_cb }; pull_coroutine< T & > synthesized{ & synthesized_cb };
other = & synthesized_cb; other = & synthesized_cb;
try { if ( state_t::none == ( state & state_t::destroy) ) {
// jump back to ctor try {
T * t = static_cast< T * >( ctx() ); // jump back to ctor
// set transferred value T * t = static_cast< T * >( ctx() );
synthesized_cb.t = t; // set transferred value
auto fn = std::move( fn_); synthesized_cb.t = t;
// call coroutine-fn with synthesized pull_coroutine as argument auto fn = std::move( fn_);
fn( synthesized); // call coroutine-fn with synthesized pull_coroutine as argument
} catch ( forced_unwind const&) { fn( synthesized);
// do nothing for unwinding exception } catch ( forced_unwind const&) {
} catch (...) { // do nothing for unwinding exception
// store other exceptions in exception-pointer } catch (...) {
except = std::current_exception(); // store other exceptions in exception-pointer
except = std::current_exception();
}
} }
// set termination flags // set termination flags
state |= state_t::complete; state |= state_t::complete;
@ -219,19 +227,21 @@ push_coroutine< T & >::control_block::control_block( context::preallocated pallo
typename pull_coroutine< T & >::control_block synthesized_cb{ this, ctx }; typename pull_coroutine< T & >::control_block synthesized_cb{ this, ctx };
pull_coroutine< T & > synthesized{ & synthesized_cb }; pull_coroutine< T & > synthesized{ & synthesized_cb };
other = & synthesized_cb; other = & synthesized_cb;
try { if ( state_t::none == ( state & state_t::destroy) ) {
// jump back to ctor try {
T * t = static_cast< T * >( ctx() ); // jump back to ctor
// set transferred value T * t = static_cast< T * >( ctx() );
synthesized_cb.t = t; // set transferred value
auto fn = std::move( fn_); synthesized_cb.t = t;
// call coroutine-fn with synthesized pull_coroutine as argument auto fn = std::move( fn_);
fn( synthesized); // call coroutine-fn with synthesized pull_coroutine as argument
} catch ( forced_unwind const&) { fn( synthesized);
// do nothing for unwinding exception } catch ( forced_unwind const&) {
} catch (...) { // do nothing for unwinding exception
// store other exceptions in exception-pointer } catch (...) {
except = std::current_exception(); // store other exceptions in exception-pointer
except = std::current_exception();
}
} }
// set termination flags // set termination flags
state |= state_t::complete; state |= state_t::complete;
@ -298,6 +308,7 @@ void
push_coroutine< void >::control_block::destroy( control_block * cb) noexcept { push_coroutine< void >::control_block::destroy( control_block * cb) noexcept {
boost::context::execution_context ctx = cb->ctx; boost::context::execution_context ctx = cb->ctx;
// destroy control structure // destroy control structure
cb->state |= state_t::destroy;
cb->~control_block(); cb->~control_block();
} }
@ -313,17 +324,19 @@ push_coroutine< void >::control_block::control_block( context::preallocated pall
typename pull_coroutine< void >::control_block synthesized_cb{ this, ctx }; typename pull_coroutine< void >::control_block synthesized_cb{ this, ctx };
pull_coroutine< void > synthesized{ & synthesized_cb }; pull_coroutine< void > synthesized{ & synthesized_cb };
other = & synthesized_cb; other = & synthesized_cb;
try { if ( state_t::none == ( state & state_t::destroy) ) {
// jump back to ctor try {
ctx(); // jump back to ctor
auto fn = std::move( fn_); ctx();
// call coroutine-fn with synthesized pull_coroutine as argument auto fn = std::move( fn_);
fn( synthesized); // call coroutine-fn with synthesized pull_coroutine as argument
} catch ( forced_unwind const&) { fn( synthesized);
// do nothing for unwinding exception } catch ( forced_unwind const&) {
} catch (...) { // do nothing for unwinding exception
// store other exceptions in exception-pointer } catch (...) {
except = std::current_exception(); // store other exceptions in exception-pointer
except = std::current_exception();
}
} }
// set termination flags // set termination flags
state |= state_t::complete; state |= state_t::complete;
@ -341,17 +354,19 @@ push_coroutine< void >::control_block::control_block( context::preallocated pall
typename pull_coroutine< void >::control_block synthesized_cb{ this, ctx }; typename pull_coroutine< void >::control_block synthesized_cb{ this, ctx };
pull_coroutine< void > synthesized{ & synthesized_cb }; pull_coroutine< void > synthesized{ & synthesized_cb };
other = & synthesized_cb; other = & synthesized_cb;
try { if ( state_t::none == ( state & state_t::destroy) ) {
// jump back to ctor try {
ctx(); // jump back to ctor
auto fn = std::move( fn_); ctx();
// call coroutine-fn with synthesized pull_coroutine as argument auto fn = std::move( fn_);
fn( synthesized); // call coroutine-fn with synthesized pull_coroutine as argument
} catch ( forced_unwind const&) { fn( synthesized);
// do nothing for unwinding exception } catch ( forced_unwind const&) {
} catch (...) { // do nothing for unwinding exception
// store other exceptions in exception-pointer } catch (...) {
except = std::current_exception(); // store other exceptions in exception-pointer
except = std::current_exception();
}
} }
// set termination flags // set termination flags
state |= state_t::complete; state |= state_t::complete;

View File

@ -36,6 +36,7 @@ push_coroutine< T >::control_block::destroy( control_block * cb) noexcept {
// destroy control structure // destroy control structure
cb->~control_block(); cb->~control_block();
// destroy coroutine's stack // destroy coroutine's stack
cb->state |= state_t::destroy;
ctx( nullptr); ctx( nullptr);
} }
@ -54,15 +55,17 @@ push_coroutine< T >::control_block::control_block( context::preallocated palloc,
other = & synthesized_cb; other = & synthesized_cb;
// set transferred value // set transferred value
synthesized_cb.set( data); synthesized_cb.set( data);
try { if ( state_t::none == ( state & state_t::destroy) ) {
auto fn = std::move( fn_); try {
// call coroutine-fn with synthesized pull_coroutine as argument auto fn = std::move( fn_);
fn( synthesized); // call coroutine-fn with synthesized pull_coroutine as argument
} catch ( boost::context::detail::forced_unwind const&) { fn( synthesized);
throw; } catch ( boost::context::detail::forced_unwind const&) {
} catch (...) { throw;
// store other exceptions in exception-pointer } catch (...) {
except = std::current_exception(); // store other exceptions in exception-pointer
except = std::current_exception();
}
} }
// set termination flags // set termination flags
state |= state_t::complete; state |= state_t::complete;
@ -83,15 +86,17 @@ push_coroutine< T >::control_block::control_block( context::preallocated palloc,
other = & synthesized_cb; other = & synthesized_cb;
// set transferred value // set transferred value
synthesized_cb.set( data); synthesized_cb.set( data);
try { if ( state_t::none == ( state & state_t::destroy) ) {
auto fn = std::move( fn_); try {
// call coroutine-fn with synthesized pull_coroutine as argument auto fn = std::move( fn_);
fn( synthesized); // call coroutine-fn with synthesized pull_coroutine as argument
} catch ( boost::context::detail::forced_unwind const&) { fn( synthesized);
throw; } catch ( boost::context::detail::forced_unwind const&) {
} catch (...) { throw;
// store other exceptions in exception-pointer } catch (...) {
except = std::current_exception(); // store other exceptions in exception-pointer
except = std::current_exception();
}
} }
// set termination flags // set termination flags
state |= state_t::complete; state |= state_t::complete;
@ -161,6 +166,7 @@ push_coroutine< T & >::control_block::destroy( control_block * cb) noexcept {
// destroy control structure // destroy control structure
cb->~control_block(); cb->~control_block();
// destroy coroutine's stack // destroy coroutine's stack
cb->state |= state_t::destroy;
ctx( nullptr); ctx( nullptr);
} }
@ -179,15 +185,17 @@ push_coroutine< T & >::control_block::control_block( context::preallocated pallo
other = & synthesized_cb; other = & synthesized_cb;
// set transferred value // set transferred value
synthesized_cb.t = data; synthesized_cb.t = data;
try { if ( state_t::none == ( state & state_t::destroy) ) {
auto fn = std::move( fn_); try {
// call coroutine-fn with synthesized pull_coroutine as argument auto fn = std::move( fn_);
fn( synthesized); // call coroutine-fn with synthesized pull_coroutine as argument
} catch ( boost::context::detail::forced_unwind const&) { fn( synthesized);
throw; } catch ( boost::context::detail::forced_unwind const&) {
} catch (...) { throw;
// store other exceptions in exception-pointer } catch (...) {
except = std::current_exception(); // store other exceptions in exception-pointer
except = std::current_exception();
}
} }
// set termination flags // set termination flags
state |= state_t::complete; state |= state_t::complete;
@ -208,15 +216,17 @@ push_coroutine< T & >::control_block::control_block( context::preallocated pallo
other = & synthesized_cb; other = & synthesized_cb;
// set transferred value // set transferred value
synthesized_cb.t = data; synthesized_cb.t = data;
try { if ( state_t::none == ( state & state_t::destroy) ) {
auto fn = std::move( fn_); try {
// call coroutine-fn with synthesized pull_coroutine as argument auto fn = std::move( fn_);
fn( synthesized); // call coroutine-fn with synthesized pull_coroutine as argument
} catch ( boost::context::detail::forced_unwind const&) { fn( synthesized);
throw; } catch ( boost::context::detail::forced_unwind const&) {
} catch (...) { throw;
// store other exceptions in exception-pointer } catch (...) {
except = std::current_exception(); // store other exceptions in exception-pointer
except = std::current_exception();
}
} }
// set termination flags // set termination flags
state |= state_t::complete; state |= state_t::complete;
@ -275,6 +285,7 @@ push_coroutine< void >::control_block::destroy( control_block * cb) noexcept {
// destroy control structure // destroy control structure
cb->~control_block(); cb->~control_block();
// destroy coroutine's stack // destroy coroutine's stack
cb->state |= state_t::destroy;
ctx(); ctx();
} }
@ -289,15 +300,17 @@ push_coroutine< void >::control_block::control_block( context::preallocated pall
typename pull_coroutine< void >::control_block synthesized_cb{ this, ctx }; typename pull_coroutine< void >::control_block synthesized_cb{ this, ctx };
pull_coroutine< void > synthesized{ & synthesized_cb }; pull_coroutine< void > synthesized{ & synthesized_cb };
other = & synthesized_cb; other = & synthesized_cb;
try { if ( state_t::none == ( state & state_t::destroy) ) {
auto fn = std::move( fn_); try {
// call coroutine-fn with synthesized pull_coroutine as argument auto fn = std::move( fn_);
fn( synthesized); // call coroutine-fn with synthesized pull_coroutine as argument
} catch ( boost::context::detail::forced_unwind const&) { fn( synthesized);
throw; } catch ( boost::context::detail::forced_unwind const&) {
} catch (...) { throw;
// store other exceptions in exception-pointer } catch (...) {
except = std::current_exception(); // store other exceptions in exception-pointer
except = std::current_exception();
}
} }
// set termination flags // set termination flags
state |= state_t::complete; state |= state_t::complete;
@ -314,15 +327,17 @@ push_coroutine< void >::control_block::control_block( context::preallocated pall
typename pull_coroutine< void >::control_block synthesized_cb{ this, ctx}; typename pull_coroutine< void >::control_block synthesized_cb{ this, ctx};
pull_coroutine< void > synthesized{ & synthesized_cb }; pull_coroutine< void > synthesized{ & synthesized_cb };
other = & synthesized_cb; other = & synthesized_cb;
try { if ( state_t::none == ( state & state_t::destroy) ) {
auto fn = std::move( fn_); try {
// call coroutine-fn with synthesized pull_coroutine as argument auto fn = std::move( fn_);
fn( synthesized); // call coroutine-fn with synthesized pull_coroutine as argument
} catch ( boost::context::detail::forced_unwind const&) { fn( synthesized);
throw; } catch ( boost::context::detail::forced_unwind const&) {
} catch (...) { throw;
// store other exceptions in exception-pointer } catch (...) {
except = std::current_exception(); // store other exceptions in exception-pointer
except = std::current_exception();
}
} }
// set termination flags // set termination flags
state |= state_t::complete; state |= state_t::complete;

View File

@ -25,7 +25,8 @@ namespace detail {
enum class state_t : unsigned int { enum class state_t : unsigned int {
none = 0, none = 0,
complete = 1 << 1, complete = 1 << 1,
unwind = 1 << 2 unwind = 1 << 2,
destroy = 1 << 3
}; };

View File

@ -188,6 +188,7 @@ void f11( coro::coroutine< std::tuple< int, int > >::pull_type & c)
void f12( coro::coroutine< void >::pull_type & c) void f12( coro::coroutine< void >::pull_type & c)
{ {
value1 = 7;
X x_; X x_;
c(); c();
c(); c();
@ -452,6 +453,14 @@ void test_unwind()
BOOST_CHECK_EQUAL( ( int) 7, value1); BOOST_CHECK_EQUAL( ( int) 7, value1);
} }
BOOST_CHECK_EQUAL( ( int) 0, value1); BOOST_CHECK_EQUAL( ( int) 0, value1);
int i = 0;
{
coro::coroutine< void >::push_type coro(
[&i](coro::coroutine< void >::pull_type &) mutable {
i = 7;
});
}
BOOST_CHECK_EQUAL( ( int) 0, i);
} }
void test_exceptions() void test_exceptions()