diff --git a/include/boost/coroutine2/detail/pull_control_block.hpp b/include/boost/coroutine2/detail/pull_control_block.hpp index 6ca6fd6..1abb34a 100644 --- a/include/boost/coroutine2/detail/pull_control_block.hpp +++ b/include/boost/coroutine2/detail/pull_control_block.hpp @@ -27,6 +27,7 @@ struct pull_coroutine< T >::control_block { boost::context::execution_context callee; bool preserve_fpu; int state; + std::exception_ptr except; template< typename StackAllocator, typename Fn > control_block( context::preallocated, StackAllocator, Fn &&, bool); @@ -50,6 +51,7 @@ struct pull_coroutine< T & >::control_block { boost::context::execution_context callee; bool preserve_fpu; int state; + std::exception_ptr except; template< typename StackAllocator, typename Fn > control_block( context::preallocated, StackAllocator, Fn &&, bool); @@ -67,11 +69,12 @@ struct pull_coroutine< T & >::control_block { }; struct pull_coroutine< void >::control_block { - push_coroutine< void >::control_block * other; - boost::context::execution_context caller; - boost::context::execution_context callee; - bool preserve_fpu; - int state; + push_coroutine< void >::control_block * other; + boost::context::execution_context caller; + boost::context::execution_context callee; + bool preserve_fpu; + int state; + std::exception_ptr except; template< typename StackAllocator, typename Fn > control_block( context::preallocated, StackAllocator, Fn &&, bool); diff --git a/include/boost/coroutine2/detail/pull_control_block.ipp b/include/boost/coroutine2/detail/pull_control_block.ipp index 98a0ec1..0df5c4d 100644 --- a/include/boost/coroutine2/detail/pull_control_block.ipp +++ b/include/boost/coroutine2/detail/pull_control_block.ipp @@ -45,6 +45,9 @@ pull_coroutine< T >::control_block::control_block( context::preallocated palloc, 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); @@ -53,7 +56,8 @@ pull_coroutine< T >::control_block::control_block( context::preallocated palloc, BOOST_ASSERT_MSG( false, "pull_coroutine is complete"); }), preserve_fpu( preserve_fpu_), - state( static_cast< int >( state_t::unwind) ) { + state( static_cast< int >( state_t::unwind) ), + except() { callee( preserve_fpu); } @@ -63,7 +67,8 @@ pull_coroutine< T >::control_block::control_block( typename push_coroutine< T >: caller( other->callee), callee( other->caller), preserve_fpu( other->preserve_fpu), - state( 0) { + state( 0), + except() { } template< typename T > @@ -80,6 +85,9 @@ template< typename T > void pull_coroutine< T >::control_block::resume() { callee( preserve_fpu); + if ( except) { + std::rethrow_exception( except); + } // test early-exit-flag if ( 0 != ( ( other->state) & static_cast< int >( state_t::early_exit) ) ) { throw forced_unwind(); @@ -112,6 +120,9 @@ pull_coroutine< T & >::control_block::control_block( context::preallocated pallo 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); @@ -120,7 +131,8 @@ pull_coroutine< T & >::control_block::control_block( context::preallocated pallo BOOST_ASSERT_MSG( false, "pull_coroutine is complete"); }), preserve_fpu( preserve_fpu_), - state( static_cast< int >( state_t::unwind) ) { + state( static_cast< int >( state_t::unwind) ), + except() { callee( preserve_fpu); } @@ -130,7 +142,8 @@ pull_coroutine< T & >::control_block::control_block( typename push_coroutine< T caller( other->callee), callee( other->caller), preserve_fpu( other->preserve_fpu), - state( 0) { + state( 0), + except() { } template< typename T > @@ -147,6 +160,9 @@ template< typename T > void pull_coroutine< T & >::control_block::resume() { callee( preserve_fpu); + if ( except) { + std::rethrow_exception( except); + } // test early-exit-flag if ( 0 != ( ( other->state) & static_cast< int >( state_t::early_exit) ) ) { throw forced_unwind(); @@ -178,6 +194,9 @@ pull_coroutine< void >::control_block::control_block( context::preallocated pall 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); @@ -186,7 +205,8 @@ pull_coroutine< void >::control_block::control_block( context::preallocated pall BOOST_ASSERT_MSG( false, "pull_coroutine is complete"); }), preserve_fpu( preserve_fpu_), - state( static_cast< int >( state_t::unwind) ) { + state( static_cast< int >( state_t::unwind) ), + except() { callee( preserve_fpu); } @@ -196,7 +216,8 @@ pull_coroutine< void >::control_block::control_block( push_coroutine< void >::co caller( other->callee), callee( other->caller), preserve_fpu( other->preserve_fpu), - state( 0) { + state( 0), + except() { } inline @@ -213,6 +234,9 @@ inline void pull_coroutine< void >::control_block::resume() { callee( preserve_fpu); + if ( except) { + std::rethrow_exception( except); + } // test early-exit-flag if ( 0 != ( ( other->state) & static_cast< int >( state_t::early_exit) ) ) { throw forced_unwind(); diff --git a/include/boost/coroutine2/detail/push_control_block.hpp b/include/boost/coroutine2/detail/push_control_block.hpp index a0d8601..e6c86ff 100644 --- a/include/boost/coroutine2/detail/push_control_block.hpp +++ b/include/boost/coroutine2/detail/push_control_block.hpp @@ -27,6 +27,7 @@ struct push_coroutine< T >::control_block { boost::context::execution_context callee; bool preserve_fpu; int state; + std::exception_ptr except; T * t; template< typename StackAllocator, typename Fn > @@ -53,6 +54,7 @@ struct push_coroutine< T & >::control_block { boost::context::execution_context callee; bool preserve_fpu; int state; + std::exception_ptr except; T * t; template< typename StackAllocator, typename Fn > @@ -71,11 +73,12 @@ struct push_coroutine< T & >::control_block { }; struct push_coroutine< void >::control_block { - pull_coroutine< void >::control_block * other; - boost::context::execution_context caller; - boost::context::execution_context callee; - bool preserve_fpu; - int state; + pull_coroutine< void >::control_block * other; + boost::context::execution_context caller; + boost::context::execution_context callee; + bool preserve_fpu; + int state; + std::exception_ptr except; template< typename StackAllocator, typename Fn > control_block( context::preallocated, StackAllocator, Fn &&, bool); diff --git a/include/boost/coroutine2/detail/push_control_block.ipp b/include/boost/coroutine2/detail/push_control_block.ipp index 54ae7d2..c73a8e0 100644 --- a/include/boost/coroutine2/detail/push_control_block.ipp +++ b/include/boost/coroutine2/detail/push_control_block.ipp @@ -46,6 +46,9 @@ push_coroutine< T >::control_block::control_block( context::preallocated palloc, 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); @@ -54,6 +57,7 @@ push_coroutine< T >::control_block::control_block( context::preallocated palloc, }), preserve_fpu( preserve_fpu_), state( static_cast< int >( state_t::unwind) ), + except(), t( nullptr) { } @@ -64,6 +68,7 @@ push_coroutine< T >::control_block::control_block( typename pull_coroutine< T >: callee( other->caller), preserve_fpu( other->preserve_fpu), state( 0), + except(), t( nullptr) { } @@ -86,6 +91,9 @@ push_coroutine< T >::control_block::resume( T const& t_) { t = & tmp; callee( preserve_fpu); t = nullptr; + if ( except) { + std::rethrow_exception( except); + } // test early-exit-flag if ( 0 != ( ( other->state) & static_cast< int >( state_t::early_exit) ) ) { throw forced_unwind(); @@ -101,6 +109,9 @@ push_coroutine< T >::control_block::resume( T && t_) { t = & tmp; callee( preserve_fpu); t = nullptr; + if ( except) { + std::rethrow_exception( except); + } // test early-exit-flag if ( 0 != ( ( other->state) & static_cast< int >( state_t::early_exit) ) ) { throw forced_unwind(); @@ -133,6 +144,9 @@ push_coroutine< T & >::control_block::control_block( context::preallocated pallo 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); @@ -141,6 +155,7 @@ push_coroutine< T & >::control_block::control_block( context::preallocated pallo }), preserve_fpu( preserve_fpu_), state( static_cast< int >( state_t::unwind) ), + except(), t( nullptr) { } @@ -151,6 +166,7 @@ push_coroutine< T & >::control_block::control_block( typename pull_coroutine< T callee( other->caller), preserve_fpu( other->preserve_fpu), state( 0), + except(), t( nullptr) { } @@ -170,6 +186,9 @@ push_coroutine< T & >::control_block::resume( T & t_) { t = & t_; callee( preserve_fpu); t = nullptr; + if ( except) { + std::rethrow_exception( except); + } // test early-exit-flag if ( 0 != ( ( other->state) & static_cast< int >( state_t::early_exit) ) ) { throw forced_unwind(); @@ -200,6 +219,9 @@ push_coroutine< void >::control_block::control_block( context::preallocated pall 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); @@ -207,7 +229,8 @@ push_coroutine< void >::control_block::control_block( context::preallocated pall BOOST_ASSERT_MSG( false, "push_coroutine is complete"); }), preserve_fpu( preserve_fpu_), - state( static_cast< int >( state_t::unwind) ) { + state( static_cast< int >( state_t::unwind) ), + except() { } inline @@ -216,7 +239,8 @@ push_coroutine< void >::control_block::control_block( pull_coroutine< void >::co caller( other->callee), callee( other->caller), preserve_fpu( other->preserve_fpu), - state( 0) { + state( 0), + except() { } inline @@ -233,6 +257,9 @@ inline void push_coroutine< void >::control_block::resume() { callee( preserve_fpu); + if ( except) { + std::rethrow_exception( except); + } // test early-exit-flag if ( 0 != ( ( other->state) & static_cast< int >( state_t::early_exit) ) ) { throw forced_unwind();