From 727ec8444bfb34685a07e11e3ea2030eb445d239 Mon Sep 17 00:00:00 2001 From: Oliver Kowalke Date: Wed, 12 Feb 2014 17:51:33 +0100 Subject: [PATCH] add flag running - prevent from restarting a coroutine if already running --- include/boost/coroutine/detail/flags.hpp | 9 ++- .../detail/symmetric_coroutine_call.hpp | 6 +- .../detail/symmetric_coroutine_impl.hpp | 80 ++++++++++++------- include/boost/coroutine/detail/trampoline.hpp | 3 + 4 files changed, 60 insertions(+), 38 deletions(-) diff --git a/include/boost/coroutine/detail/flags.hpp b/include/boost/coroutine/detail/flags.hpp index 21ed18e..187a6fd 100644 --- a/include/boost/coroutine/detail/flags.hpp +++ b/include/boost/coroutine/detail/flags.hpp @@ -19,10 +19,11 @@ namespace detail { enum flag_t { - flag_complete = 1 << 1, - flag_unwind_stack = 1 << 2, - flag_force_unwind = 1 << 3, - flag_preserve_fpu = 1 << 4 + flag_running = 1 << 1, + flag_complete = 1 << 2, + flag_unwind_stack = 1 << 3, + flag_force_unwind = 1 << 4, + flag_preserve_fpu = 1 << 5 }; struct unwind_t diff --git a/include/boost/coroutine/detail/symmetric_coroutine_call.hpp b/include/boost/coroutine/detail/symmetric_coroutine_call.hpp index d9497f8..75b09cb 100644 --- a/include/boost/coroutine/detail/symmetric_coroutine_call.hpp +++ b/include/boost/coroutine/detail/symmetric_coroutine_call.hpp @@ -276,7 +276,7 @@ public: BOOST_EXPLICIT_OPERATOR_BOOL(); bool operator!() const BOOST_NOEXCEPT - { return 0 == impl_ || impl_->is_complete(); } + { return 0 == impl_ || impl_->is_complete() || impl_->is_running(); } void swap( symmetric_coroutine_call & other) BOOST_NOEXCEPT { @@ -539,7 +539,7 @@ public: BOOST_EXPLICIT_OPERATOR_BOOL(); bool operator!() const BOOST_NOEXCEPT - { return 0 == impl_ || impl_->is_complete(); } + { return 0 == impl_ || impl_->is_complete() || impl_->is_running(); } void swap( symmetric_coroutine_call & other) BOOST_NOEXCEPT { @@ -802,7 +802,7 @@ public: BOOST_EXPLICIT_OPERATOR_BOOL(); bool operator!() const BOOST_NOEXCEPT - { return 0 == impl_ || impl_->is_complete(); } + { return 0 == impl_ || impl_->is_complete() || impl_->is_running(); } void swap( symmetric_coroutine_call & other) BOOST_NOEXCEPT { diff --git a/include/boost/coroutine/detail/symmetric_coroutine_impl.hpp b/include/boost/coroutine/detail/symmetric_coroutine_impl.hpp index 21a3ac2..92ebdb7 100644 --- a/include/boost/coroutine/detail/symmetric_coroutine_impl.hpp +++ b/include/boost/coroutine/detail/symmetric_coroutine_impl.hpp @@ -51,6 +51,10 @@ private: void run_( param_type * to) BOOST_NOEXCEPT { + BOOST_ASSERT( ! is_running() ); + BOOST_ASSERT( ! is_complete() ); + + flags_ |= flag_running; caller_->jump( * callee_, reinterpret_cast< intptr_t >( to), @@ -60,13 +64,20 @@ private: template< typename Other > R * yield_to_( Other * other, typename Other::param_type * to) { + BOOST_ASSERT( ! is_complete() ); + BOOST_ASSERT( is_running() ); + BOOST_ASSERT( ! other->is_complete() ); + BOOST_ASSERT( ! other->is_running() ); + other->caller_ = caller_; + flags_ &= ~flag_running; param_type * from( reinterpret_cast< param_type * >( callee_->jump( * other->callee_, reinterpret_cast< intptr_t >( to), preserve_fpu() ) ) ); + flags_ |= flag_running; if ( from->do_unwind) throw forced_unwind(); BOOST_ASSERT( from->data); return from->data; @@ -93,6 +104,9 @@ public: bool preserve_fpu() const BOOST_NOEXCEPT { return 0 != ( flags_ & flag_preserve_fpu); } + bool is_running() const BOOST_NOEXCEPT + { return 0 != ( flags_ & flag_running); } + bool is_complete() const BOOST_NOEXCEPT { return 0 != ( flags_ & flag_complete); } @@ -114,8 +128,6 @@ public: void run( R r) BOOST_NOEXCEPT { - BOOST_ASSERT( ! is_complete() ); - param_type to( const_cast< R * >( & r) ); run_( & to); } @@ -123,7 +135,9 @@ public: R * yield() { BOOST_ASSERT( ! is_complete() ); + BOOST_ASSERT( is_running() ); + flags_ &= ~flag_running; param_type to; param_type * from( reinterpret_cast< param_type * >( @@ -131,6 +145,7 @@ public: * caller_, reinterpret_cast< intptr_t >( & to), preserve_fpu() ) ) ); + flags_ |= flag_running; if ( from->do_unwind) throw forced_unwind(); BOOST_ASSERT( from->data); return from->data; @@ -139,9 +154,6 @@ public: template< typename X > R * yield_to( symmetric_coroutine_impl< X > * other, X x) { - BOOST_ASSERT( ! is_complete() ); - BOOST_ASSERT( ! other->is_complete() ); - typename symmetric_coroutine_impl< X >::param_type to( & x); return yield_to_( other, & to); } @@ -149,9 +161,6 @@ public: template< typename X > R * yield_to( symmetric_coroutine_impl< X & > * other, X & x) { - BOOST_ASSERT( ! is_complete() ); - BOOST_ASSERT( ! other->is_complete() ); - typename symmetric_coroutine_impl< X & >::param_type to( & x); return yield_to_( other, & to); } @@ -159,9 +168,6 @@ public: template< typename X > R * yield_to( symmetric_coroutine_impl< X > * other) { - BOOST_ASSERT( ! is_complete() ); - BOOST_ASSERT( ! other->is_complete() ); - typename symmetric_coroutine_impl< X >::param_type to; return yield_to_( other, & to); } @@ -187,6 +193,10 @@ private: void run_( param_type * to) BOOST_NOEXCEPT { + BOOST_ASSERT( ! is_running() ); + BOOST_ASSERT( ! is_complete() ); + + flags_ |= flag_running; caller_->jump( * callee_, reinterpret_cast< intptr_t >( to), @@ -196,13 +206,20 @@ private: template< typename Other > R * yield_to_( Other * other, typename Other::param_type * to) { + BOOST_ASSERT( ! is_complete() ); + BOOST_ASSERT( is_running() ); + BOOST_ASSERT( ! other->is_complete() ); + BOOST_ASSERT( ! other->is_running() ); + other->caller_ = caller_; + flags_ &= ~flag_running; param_type * from( reinterpret_cast< param_type * >( callee_->jump( * other->callee_, reinterpret_cast< intptr_t >( to), preserve_fpu() ) ) ); + flags_ |= flag_running; if ( from->do_unwind) throw forced_unwind(); BOOST_ASSERT( from->data); return from->data; @@ -229,6 +246,9 @@ public: bool preserve_fpu() const BOOST_NOEXCEPT { return 0 != ( flags_ & flag_preserve_fpu); } + bool is_running() const BOOST_NOEXCEPT + { return 0 != ( flags_ & flag_running); } + bool is_complete() const BOOST_NOEXCEPT { return 0 != ( flags_ & flag_complete); } @@ -250,8 +270,6 @@ public: void run( R & arg) BOOST_NOEXCEPT { - BOOST_ASSERT( ! is_complete() ); - param_type to( & arg); run_( & to); } @@ -259,7 +277,9 @@ public: R * yield() { BOOST_ASSERT( ! is_complete() ); + BOOST_ASSERT( is_running() ); + flags_ &= ~flag_running; param_type to; param_type * from( reinterpret_cast< param_type * >( @@ -267,6 +287,7 @@ public: * caller_, reinterpret_cast< intptr_t >( & to), preserve_fpu() ) ) ); + flags_ |= flag_running; if ( from->do_unwind) throw forced_unwind(); BOOST_ASSERT( from->data); return from->data; @@ -275,9 +296,6 @@ public: template< typename X > R * yield_to( symmetric_coroutine_impl< X > * other, X x) { - BOOST_ASSERT( ! is_complete() ); - BOOST_ASSERT( ! other->is_complete() ); - typename symmetric_coroutine_impl< X >::param_type to( & x); return yield_to_( other, & to); } @@ -285,9 +303,6 @@ public: template< typename X > R * yield_to( symmetric_coroutine_impl< X & > * other, X & x) { - BOOST_ASSERT( ! is_complete() ); - BOOST_ASSERT( ! other->is_complete() ); - typename symmetric_coroutine_impl< X & >::param_type to( & x); return yield_to_( other, & to); } @@ -295,9 +310,6 @@ public: template< typename X > R * yield_to( symmetric_coroutine_impl< X > * other) { - BOOST_ASSERT( ! is_complete() ); - BOOST_ASSERT( ! other->is_complete() ); - typename symmetric_coroutine_impl< X >::param_type to; return yield_to_( other, & to); } @@ -324,13 +336,20 @@ private: template< typename Other > void yield_to_( Other * other, typename Other::param_type * to) { + BOOST_ASSERT( ! is_complete() ); + BOOST_ASSERT( is_running() ); + BOOST_ASSERT( ! other->is_complete() ); + BOOST_ASSERT( ! other->is_running() ); + other->caller_ = caller_; + flags_ &= ~flag_running; param_type * from( reinterpret_cast< param_type * >( callee_->jump( * other->callee_, reinterpret_cast< intptr_t >( to), preserve_fpu() ) ) ); + flags_ |= flag_running; if ( from->do_unwind) throw forced_unwind(); } @@ -355,6 +374,9 @@ public: bool preserve_fpu() const BOOST_NOEXCEPT { return 0 != ( flags_ & flag_preserve_fpu); } + bool is_running() const BOOST_NOEXCEPT + { return 0 != ( flags_ & flag_running); } + bool is_complete() const BOOST_NOEXCEPT { return 0 != ( flags_ & flag_complete); } @@ -376,9 +398,11 @@ public: void run() BOOST_NOEXCEPT { + BOOST_ASSERT( ! is_running() ); BOOST_ASSERT( ! is_complete() ); param_type to; + flags_ |= flag_running; caller_->jump( * callee_, reinterpret_cast< intptr_t >( & to), @@ -388,7 +412,9 @@ public: void yield() BOOST_NOEXCEPT { BOOST_ASSERT( ! is_complete() ); + BOOST_ASSERT( is_running() ); + flags_ &= ~flag_running; param_type to; param_type * from( reinterpret_cast< param_type * >( @@ -396,15 +422,13 @@ public: * caller_, reinterpret_cast< intptr_t >( & to), preserve_fpu() ) ) ); + flags_ |= flag_running; if ( from->do_unwind) throw forced_unwind(); } template< typename X > void yield_to( symmetric_coroutine_impl< X > * other, X x) { - BOOST_ASSERT( ! is_complete() ); - BOOST_ASSERT( ! other->is_complete() ); - typename symmetric_coroutine_impl< X >::param_type to( & x); yield_to_( other, & to); } @@ -412,9 +436,6 @@ public: template< typename X > void yield_to( symmetric_coroutine_impl< X & > * other, X & x) { - BOOST_ASSERT( ! is_complete() ); - BOOST_ASSERT( ! other->is_complete() ); - typename symmetric_coroutine_impl< X & >::param_type to( & x); yield_to_( other, & to); } @@ -422,9 +443,6 @@ public: template< typename X > void yield_to( symmetric_coroutine_impl< X > * other) { - BOOST_ASSERT( ! is_complete() ); - BOOST_ASSERT( ! other->is_complete() ); - typename symmetric_coroutine_impl< X >::param_type to; yield_to_( other, & to); } diff --git a/include/boost/coroutine/detail/trampoline.hpp b/include/boost/coroutine/detail/trampoline.hpp index da795cb..df0348a 100644 --- a/include/boost/coroutine/detail/trampoline.hpp +++ b/include/boost/coroutine/detail/trampoline.hpp @@ -62,6 +62,7 @@ void trampoline( intptr_t vp) // create yield_type Self yield( & c, from->data); + c.flags_ |= flag_running; try { fn( yield); } catch ( forced_unwind const&) @@ -71,6 +72,7 @@ void trampoline( intptr_t vp) } c.flags_ |= flag_complete; + c.flags_ &= ~flag_running; c.callee_->jump( * c.caller_, 0, c.preserve_fpu() ); BOOST_ASSERT_MSG( false, "coroutine is complete"); } @@ -112,6 +114,7 @@ void trampoline_void( intptr_t vp) } c.flags_ |= flag_complete; + c.flags_ &= ~flag_running; param_type to; c.callee_->jump( * c.caller_,