add flag running - prevent from restarting a coroutine if already

running
This commit is contained in:
Oliver Kowalke
2014-02-12 17:51:33 +01:00
parent 3b6a6f5659
commit 727ec8444b
4 changed files with 60 additions and 38 deletions

View File

@@ -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

View File

@@ -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
{

View File

@@ -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);
}

View File

@@ -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_,