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 {
boost::context::execution_context ctx = cb->ctx;
// destroy control structure
cb->state |= state_t::destroy;
cb->~control_block();
}
@ -52,6 +53,7 @@ pull_coroutine< T >::control_block::control_block( context::preallocated palloc,
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
@ -62,6 +64,7 @@ pull_coroutine< T >::control_block::control_block( context::preallocated palloc,
// store other exceptions in exception-pointer
except = std::current_exception();
}
}
// set termination flags
state |= state_t::complete;
// jump back to ctx
@ -78,6 +81,7 @@ pull_coroutine< T >::control_block::control_block( context::preallocated palloc,
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
@ -88,6 +92,7 @@ pull_coroutine< T >::control_block::control_block( context::preallocated palloc,
// store other exceptions in exception-pointer
except = std::current_exception();
}
}
// set termination flags
state |= state_t::complete;
// jump back to ctx
@ -181,6 +186,7 @@ void
pull_coroutine< T & >::control_block::destroy( control_block * cb) noexcept {
boost::context::execution_context ctx = cb->ctx;
// destroy control structure
cb->state |= state_t::destroy;
cb->~control_block();
}
@ -197,6 +203,7 @@ pull_coroutine< T & >::control_block::control_block( context::preallocated pallo
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
@ -207,6 +214,7 @@ pull_coroutine< T & >::control_block::control_block( context::preallocated pallo
// store other exceptions in exception-pointer
except = std::current_exception();
}
}
// set termination flags
state |= state_t::complete;
// jump back to ctx
@ -223,6 +231,7 @@ pull_coroutine< T & >::control_block::control_block( context::preallocated pallo
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
@ -233,6 +242,7 @@ pull_coroutine< T & >::control_block::control_block( context::preallocated pallo
// store other exceptions in exception-pointer
except = std::current_exception();
}
}
// set termination flags
state |= state_t::complete;
// jump back to ctx
@ -305,6 +315,7 @@ void
pull_coroutine< void >::control_block::destroy( control_block * cb) noexcept {
boost::context::execution_context ctx = cb->ctx;
// destroy control structure
cb->state |= state_t::destroy;
cb->~control_block();
}
@ -320,6 +331,7 @@ pull_coroutine< void >::control_block::control_block( context::preallocated pall
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
@ -330,6 +342,7 @@ pull_coroutine< void >::control_block::control_block( context::preallocated pall
// store other exceptions in exception-pointer
except = std::current_exception();
}
}
// set termination flags
state |= state_t::complete;
// jump back to ctx
@ -346,6 +359,7 @@ pull_coroutine< void >::control_block::control_block( context::preallocated pall
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
@ -356,6 +370,7 @@ pull_coroutine< void >::control_block::control_block( context::preallocated pall
// store other exceptions in exception-pointer
except = std::current_exception();
}
}
// set termination flags
state |= state_t::complete;
// jump back to ctx

View File

@ -37,6 +37,7 @@ pull_coroutine< T >::control_block::destroy( control_block * cb) noexcept {
// destroy control structure
cb->~control_block();
// destroy coroutine's stack
cb->state |= state_t::destroy;
ctx( nullptr);
}
@ -53,6 +54,7 @@ pull_coroutine< T >::control_block::control_block( context::preallocated palloc,
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
@ -63,6 +65,7 @@ pull_coroutine< T >::control_block::control_block( context::preallocated palloc,
// store other exceptions in exception-pointer
except = std::current_exception();
}
}
// set termination flags
state |= state_t::complete;
// jump back to ctx
@ -80,6 +83,7 @@ pull_coroutine< T >::control_block::control_block( context::preallocated palloc,
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
@ -90,6 +94,7 @@ pull_coroutine< T >::control_block::control_block( context::preallocated palloc,
// store other exceptions in exception-pointer
except = std::current_exception();
}
}
// set termination flags
state |= state_t::complete;
// jump back to ctx
@ -184,6 +189,7 @@ pull_coroutine< T & >::control_block::destroy( control_block * cb) noexcept {
// destroy control structure
cb->~control_block();
// destroy coroutine's stack
cb->state |= state_t::destroy;
ctx( nullptr);
}
@ -200,6 +206,7 @@ pull_coroutine< T & >::control_block::control_block( context::preallocated pallo
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
@ -210,6 +217,7 @@ pull_coroutine< T & >::control_block::control_block( context::preallocated pallo
// store other exceptions in exception-pointer
except = std::current_exception();
}
}
// set termination flags
state |= state_t::complete;
// jump back to ctx
@ -227,6 +235,7 @@ pull_coroutine< T & >::control_block::control_block( context::preallocated pallo
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
@ -237,6 +246,7 @@ pull_coroutine< T & >::control_block::control_block( context::preallocated pallo
// store other exceptions in exception-pointer
except = std::current_exception();
}
}
// set termination flags
state |= state_t::complete;
// jump back to ctx
@ -306,6 +316,7 @@ pull_coroutine< void >::control_block::destroy( control_block * cb) noexcept {
// destroy control structure
cb->~control_block();
// destroy coroutine's stack
cb->state |= state_t::destroy;
ctx();
}
@ -321,6 +332,7 @@ pull_coroutine< void >::control_block::control_block( context::preallocated pall
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
@ -331,6 +343,7 @@ pull_coroutine< void >::control_block::control_block( context::preallocated pall
// store other exceptions in exception-pointer
except = std::current_exception();
}
}
// set termination flags
state |= state_t::complete;
// jump back to ctx
@ -346,6 +359,7 @@ pull_coroutine< void >::control_block::control_block( context::preallocated pall
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
@ -356,6 +370,7 @@ pull_coroutine< void >::control_block::control_block( context::preallocated pall
// store other exceptions in exception-pointer
except = std::current_exception();
}
}
// set termination flags
state |= state_t::complete;
// jump back to ctx

View File

@ -37,6 +37,7 @@ void
push_coroutine< T >::control_block::destroy( control_block * cb) noexcept {
boost::context::execution_context ctx = cb->ctx;
// destroy control structure
cb->state |= state_t::destroy;
cb->~control_block();
}
@ -53,6 +54,7 @@ push_coroutine< T >::control_block::control_block( context::preallocated palloc,
typename pull_coroutine< T >::control_block synthesized_cb{ this, ctx };
pull_coroutine< T > synthesized{ & synthesized_cb };
other = & synthesized_cb;
if ( state_t::none == ( state & state_t::destroy) ) {
try {
// jump back to ctor
T * t = static_cast< T * >( ctx() );
@ -67,6 +69,7 @@ push_coroutine< T >::control_block::control_block( context::preallocated palloc,
// store other exceptions in exception-pointer
except = std::current_exception();
}
}
// set termination flags
state |= state_t::complete;
// jump back to ctx
@ -83,6 +86,7 @@ push_coroutine< T >::control_block::control_block( context::preallocated palloc,
typename pull_coroutine< T >::control_block synthesized_cb{ this, ctx };
pull_coroutine< T > synthesized{ & synthesized_cb };
other = & synthesized_cb;
if ( state_t::none == ( state & state_t::destroy) ) {
try {
// jump back to ctor
T * t = static_cast< T * >( ctx() );
@ -97,6 +101,7 @@ push_coroutine< T >::control_block::control_block( context::preallocated palloc,
// store other exceptions in exception-pointer
except = std::current_exception();
}
}
// set termination flags
state |= state_t::complete;
// jump back to ctx
@ -173,6 +178,7 @@ void
push_coroutine< T & >::control_block::destroy( control_block * cb) noexcept {
boost::context::execution_context ctx = cb->ctx;
// destroy control structure
cb->state |= state_t::destroy;
cb->~control_block();
}
@ -189,6 +195,7 @@ push_coroutine< T & >::control_block::control_block( context::preallocated pallo
typename pull_coroutine< T & >::control_block synthesized_cb{ this, ctx };
pull_coroutine< T & > synthesized{ & synthesized_cb };
other = & synthesized_cb;
if ( state_t::none == ( state & state_t::destroy) ) {
try {
// jump back to ctor
T * t = static_cast< T * >( ctx() );
@ -203,6 +210,7 @@ push_coroutine< T & >::control_block::control_block( context::preallocated pallo
// store other exceptions in exception-pointer
except = std::current_exception();
}
}
// set termination flags
state |= state_t::complete;
// jump back to ctx
@ -219,6 +227,7 @@ push_coroutine< T & >::control_block::control_block( context::preallocated pallo
typename pull_coroutine< T & >::control_block synthesized_cb{ this, ctx };
pull_coroutine< T & > synthesized{ & synthesized_cb };
other = & synthesized_cb;
if ( state_t::none == ( state & state_t::destroy) ) {
try {
// jump back to ctor
T * t = static_cast< T * >( ctx() );
@ -233,6 +242,7 @@ push_coroutine< T & >::control_block::control_block( context::preallocated pallo
// store other exceptions in exception-pointer
except = std::current_exception();
}
}
// set termination flags
state |= state_t::complete;
// jump back to ctx
@ -298,6 +308,7 @@ void
push_coroutine< void >::control_block::destroy( control_block * cb) noexcept {
boost::context::execution_context ctx = cb->ctx;
// destroy control structure
cb->state |= state_t::destroy;
cb->~control_block();
}
@ -313,6 +324,7 @@ push_coroutine< void >::control_block::control_block( context::preallocated pall
typename pull_coroutine< void >::control_block synthesized_cb{ this, ctx };
pull_coroutine< void > synthesized{ & synthesized_cb };
other = & synthesized_cb;
if ( state_t::none == ( state & state_t::destroy) ) {
try {
// jump back to ctor
ctx();
@ -325,6 +337,7 @@ push_coroutine< void >::control_block::control_block( context::preallocated pall
// store other exceptions in exception-pointer
except = std::current_exception();
}
}
// set termination flags
state |= state_t::complete;
// jump back to ctx
@ -341,6 +354,7 @@ push_coroutine< void >::control_block::control_block( context::preallocated pall
typename pull_coroutine< void >::control_block synthesized_cb{ this, ctx };
pull_coroutine< void > synthesized{ & synthesized_cb };
other = & synthesized_cb;
if ( state_t::none == ( state & state_t::destroy) ) {
try {
// jump back to ctor
ctx();
@ -353,6 +367,7 @@ push_coroutine< void >::control_block::control_block( context::preallocated pall
// store other exceptions in exception-pointer
except = std::current_exception();
}
}
// set termination flags
state |= state_t::complete;
// jump back to ctx

View File

@ -36,6 +36,7 @@ push_coroutine< T >::control_block::destroy( control_block * cb) noexcept {
// destroy control structure
cb->~control_block();
// destroy coroutine's stack
cb->state |= state_t::destroy;
ctx( nullptr);
}
@ -54,6 +55,7 @@ push_coroutine< T >::control_block::control_block( context::preallocated palloc,
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
@ -64,6 +66,7 @@ push_coroutine< T >::control_block::control_block( context::preallocated palloc,
// store other exceptions in exception-pointer
except = std::current_exception();
}
}
// set termination flags
state |= state_t::complete;
// jump back to ctx
@ -83,6 +86,7 @@ push_coroutine< T >::control_block::control_block( context::preallocated palloc,
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
@ -93,6 +97,7 @@ push_coroutine< T >::control_block::control_block( context::preallocated palloc,
// store other exceptions in exception-pointer
except = std::current_exception();
}
}
// set termination flags
state |= state_t::complete;
// jump back to ctx
@ -161,6 +166,7 @@ push_coroutine< T & >::control_block::destroy( control_block * cb) noexcept {
// destroy control structure
cb->~control_block();
// destroy coroutine's stack
cb->state |= state_t::destroy;
ctx( nullptr);
}
@ -179,6 +185,7 @@ push_coroutine< T & >::control_block::control_block( context::preallocated pallo
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
@ -189,6 +196,7 @@ push_coroutine< T & >::control_block::control_block( context::preallocated pallo
// store other exceptions in exception-pointer
except = std::current_exception();
}
}
// set termination flags
state |= state_t::complete;
// jump back to ctx
@ -208,6 +216,7 @@ push_coroutine< T & >::control_block::control_block( context::preallocated pallo
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
@ -218,6 +227,7 @@ push_coroutine< T & >::control_block::control_block( context::preallocated pallo
// store other exceptions in exception-pointer
except = std::current_exception();
}
}
// set termination flags
state |= state_t::complete;
// jump back to ctx
@ -275,6 +285,7 @@ push_coroutine< void >::control_block::destroy( control_block * cb) noexcept {
// destroy control structure
cb->~control_block();
// destroy coroutine's stack
cb->state |= state_t::destroy;
ctx();
}
@ -289,6 +300,7 @@ push_coroutine< void >::control_block::control_block( context::preallocated pall
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
@ -299,6 +311,7 @@ push_coroutine< void >::control_block::control_block( context::preallocated pall
// store other exceptions in exception-pointer
except = std::current_exception();
}
}
// set termination flags
state |= state_t::complete;
// jump back to ctx
@ -314,6 +327,7 @@ push_coroutine< void >::control_block::control_block( context::preallocated pall
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
@ -324,6 +338,7 @@ push_coroutine< void >::control_block::control_block( context::preallocated pall
// store other exceptions in exception-pointer
except = std::current_exception();
}
}
// set termination flags
state |= state_t::complete;
// jump back to ctx

View File

@ -25,7 +25,8 @@ namespace detail {
enum class state_t : unsigned int {
none = 0,
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)
{
value1 = 7;
X x_;
c();
c();
@ -452,6 +453,14 @@ void test_unwind()
BOOST_CHECK_EQUAL( ( int) 7, 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()