2
0
mirror of https://github.com/boostorg/fiber.git synced 2026-02-18 01:52:24 +00:00

some fixes

This commit is contained in:
Oliver Kowalke
2014-09-24 19:18:44 +02:00
parent 244c539a2e
commit 7fb469cd10
39 changed files with 728 additions and 1139 deletions

View File

@@ -10,7 +10,7 @@
#include <boost/utility.hpp>
#include <boost/fiber/detail/config.hpp>
#include <boost/fiber/detail/worker_fiber.hpp>
#include <boost/fiber/detail/fiber_base.hpp>
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_PREFIX
@@ -28,11 +28,11 @@ struct sched_algorithm
{
virtual ~sched_algorithm() {}
virtual void awakened( detail::worker_fiber *) = 0;
virtual void awakened( detail::fiber_base *) = 0;
virtual detail::worker_fiber * pick_next() = 0;
virtual detail::fiber_base * pick_next() = 0;
virtual void priority( detail::worker_fiber *, int) BOOST_NOEXCEPT = 0;
virtual void priority( detail::fiber_base *, int) BOOST_NOEXCEPT = 0;
};
}}

View File

@@ -72,71 +72,40 @@ public:
template< typename LockType >
void wait( LockType & lt)
{
detail::fiber_base * n( fm_active() );
detail::fiber_base * f( fm_active() );
try
{
if ( n)
{
// lock spinlock
unique_lock< detail::spinlock > lk( splk_);
// lock spinlock
unique_lock< detail::spinlock > lk( splk_);
BOOST_ASSERT( waiting_.end() == std::find( waiting_.begin(), waiting_.end(), n) );
// store this fiber in waiting-queue
// in order notify (resume) this fiber later
waiting_.push_back( n);
BOOST_ASSERT( waiting_.end() == std::find( waiting_.begin(), waiting_.end(), f) );
// store this fiber in waiting-queue
// in order notify (resume) this fiber later
waiting_.push_back( f);
// unlock external
lt.unlock();
// unlock external
lt.unlock();
// suspend this fiber
// locked spinlock will be released if this fiber
// was stored inside schedulers's waiting-queue
fm_wait( lk);
// suspend this fiber
// locked spinlock will be released if this fiber
// was stored inside schedulers's waiting-queue
fm_wait( lk);
// this fiber was notified and resumed
// check if fiber was interrupted
this_fiber::interruption_point();
// this fiber was notified and resumed
// check if fiber was interrupted
this_fiber::interruption_point();
// lock external again before returning
lt.lock();
}
else
{
// notification for main-fiber
detail::main_fiber mf;
n = & mf;
// lock spinlock
unique_lock< detail::spinlock > lk( splk_);
BOOST_ASSERT( waiting_.end() == std::find( waiting_.begin(), waiting_.end(), n) );
// store this main-notifier in waiting-queue
// in order to be notified later
waiting_.push_back( n);
// unlock external
lt.unlock();
// release spinlock
lk.unlock();
// loop until main-notifier gets notified
while ( ! n->is_ready() )
// run scheduler
fm_run();
// lock external again before returning
lt.lock();
}
// lock external again before returning
lt.lock();
}
catch (...)
{
unique_lock< detail::spinlock > lk( splk_);
std::deque< detail::fiber_base * >::iterator wit = std::find( waiting_.begin(), waiting_.end(), n);
if (wit != waiting_.end())
std::deque< detail::fiber_base * >::iterator i( std::find( waiting_.begin(), waiting_.end(), f) );
if ( waiting_.end() != i)
{
// remove fiber from waiting-list
waiting_.erase( wit );
waiting_.erase( i);
}
throw;
}
@@ -149,17 +118,15 @@ public:
chrono::high_resolution_clock::time_point timeout_time(
detail::convert_tp( timeout_time_) );
detail::fiber_base * n( fm_active() );
detail::fiber_base * f( fm_active() );
try
{
if ( n)
{
// lock spinlock
unique_lock< detail::spinlock > lk( splk_);
// store this fiber in waiting-queue
// in order notify (resume) this fiber later
waiting_.push_back( n);
waiting_.push_back( f);
// unlock external
lt.unlock();
@@ -172,7 +139,7 @@ public:
// this fiber was not notified before timeout
// lock spinlock again
unique_lock< detail::spinlock > lk( splk_);
std::deque< detail::fiber_base * >::iterator wit = std::find( waiting_.begin(), waiting_.end(), n);
std::deque< detail::fiber_base * >::iterator wit = std::find( waiting_.begin(), waiting_.end(), f);
if (wit != waiting_.end())
{
// remove fiber from waiting-list
@@ -187,60 +154,15 @@ public:
// lock external again before returning
lt.lock();
}
else
{
// notification for main-fiber
detail::main_fiber mf;
n = & mf;
// lock spinlock
unique_lock< detail::spinlock > lk( splk_);
// store this fiber in order to be notified later
waiting_.push_back( n);
// unlock external
lt.unlock();
// release spinlock
lk.unlock();
// loop until main-notifier gets notified
while ( ! n->is_ready() )
{
// check timepoint
if ( ! ( chrono::high_resolution_clock::now() < timeout_time) )
{
// timeout happend before notified
// lock spinlock
unique_lock< detail::spinlock > lk( splk_);
std::deque< detail::fiber_base * >::iterator wit = std::find( waiting_.begin(), waiting_.end(), n);
if (wit != waiting_.end())
{
// remove fiber from waiting-list
waiting_.erase(wit);
}
status = cv_status::timeout;
break;
}
// run scheduler
fm_run();
}
// lock external again before returning
lt.lock();
}
}
catch (...)
{
unique_lock< detail::spinlock > lk( splk_);
std::deque< detail::fiber_base * >::iterator wit = std::find( waiting_.begin(), waiting_.end(), n);
if (wit != waiting_.end())
std::deque< detail::fiber_base * >::iterator i( std::find( waiting_.begin(), waiting_.end(), f) );
if ( waiting_.end() != i)
{
// remove fiber from waiting-list
waiting_.erase( wit );
waiting_.erase( i);
}
throw;
}

View File

@@ -7,16 +7,24 @@
#ifndef BOOST_FIBERS_DETAIL_FIBER_BASE_H
#define BOOST_FIBERS_DETAIL_FIBER_BASE_H
//#include <atomic>
#include <cstddef>
#include <iostream>
#include <map>
#include <vector>
#include <boost/assert.hpp>
#include <boost/atomic.hpp>
#include <boost/chrono/system_clocks.hpp>
#include <boost/config.hpp>
#include <boost/context/all.hpp>
#include <boost/cstdint.hpp>
#include <boost/exception/all.hpp>
#include <boost/utility.hpp>
#include <boost/fiber/detail/config.hpp>
#include <boost/fiber/detail/flags.hpp>
#include <boost/fiber/detail/fss.hpp>
#include <boost/fiber/detail/spinlock.hpp>
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_PREFIX
@@ -33,6 +41,48 @@ namespace detail {
class BOOST_FIBERS_DECL fiber_base : private noncopyable
{
private:
enum state_t
{
READY = 0,
RUNNING,
WAITING,
TERMINATED
};
struct BOOST_FIBERS_DECL fss_data
{
void * vp;
fss_cleanup_function::ptr_t cleanup_function;
fss_data() :
vp( 0), cleanup_function( 0)
{}
fss_data( void * vp_, fss_cleanup_function::ptr_t const& fn) :
vp( vp_), cleanup_function( fn)
{ BOOST_ASSERT( cleanup_function); }
void do_cleanup()
{ ( * cleanup_function)( vp); }
};
typedef std::map< uintptr_t, fss_data > fss_data_t;
atomic< std::size_t > use_count_;
context::fcontext_t ctx_;
fss_data_t fss_data_;
fiber_base * nxt_;
chrono::high_resolution_clock::time_point tp_;
atomic< state_t > state_;
atomic< int > flags_;
atomic< int > priority_;
spinlock splk_;
std::vector< fiber_base * > waiting_;
protected:
exception_ptr except_;
public:
class id
{
@@ -83,16 +133,149 @@ public:
{ return 0 == impl_; }
};
fiber_base()
fiber_base( context::fcontext_t ctx) :
use_count_( 1), // allocated on stack
ctx_( ctx),
fss_data_(),
nxt_( 0),
tp_( (chrono::high_resolution_clock::time_point::max)() ),
state_( READY),
flags_( 0),
priority_( 0),
waiting_(),
except_()
{}
virtual ~fiber_base() {};
virtual ~fiber_base()
{
BOOST_ASSERT( is_terminated() );
BOOST_ASSERT( waiting_.empty() );
}
virtual bool is_ready() const BOOST_NOEXCEPT = 0;
id get_id() const BOOST_NOEXCEPT
{ return id( const_cast< fiber_base * >( this) ); }
virtual void set_ready() BOOST_NOEXCEPT = 0;
int priority() const BOOST_NOEXCEPT
{ return priority_; }
virtual id get_id() const BOOST_NOEXCEPT = 0;
void priority( int prio) BOOST_NOEXCEPT
{ priority_ = prio; }
bool join( fiber_base *);
bool interruption_blocked() const BOOST_NOEXCEPT
{ return 0 != ( flags_.load() & flag_interruption_blocked); }
void interruption_blocked( bool blck) BOOST_NOEXCEPT;
bool interruption_requested() const BOOST_NOEXCEPT
{ return 0 != ( flags_.load() & flag_interruption_requested); }
void request_interruption( bool req) BOOST_NOEXCEPT;
bool thread_affinity() const BOOST_NOEXCEPT
{ return 0 != ( flags_.load() & flag_thread_affinity); }
void thread_affinity( bool req) BOOST_NOEXCEPT;
bool is_terminated() const BOOST_NOEXCEPT
{ return TERMINATED == state_; }
bool is_ready() const BOOST_NOEXCEPT
{ return READY == state_; }
bool is_running() const BOOST_NOEXCEPT
{ return RUNNING == state_; }
bool is_waiting() const BOOST_NOEXCEPT
{ return WAITING == state_; }
void set_terminated() BOOST_NOEXCEPT
{
state_t previous = state_.exchange( TERMINATED);
BOOST_ASSERT( RUNNING == previous);
(void)previous;
}
void set_ready() BOOST_NOEXCEPT
{
state_t previous = state_.exchange( READY);
BOOST_ASSERT( WAITING == previous || RUNNING == previous || READY == previous);
(void)previous;
}
void set_running() BOOST_NOEXCEPT
{
state_t previous = state_.exchange( RUNNING);
BOOST_ASSERT( READY == previous);
(void)previous;
}
void set_waiting() BOOST_NOEXCEPT
{
state_t previous = state_.exchange( WAITING);
BOOST_ASSERT( RUNNING == previous);
(void)previous;
}
void * get_fss_data( void const* vp) const;
void set_fss_data(
void const* vp,
fss_cleanup_function::ptr_t const& cleanup_fn,
void * data,
bool cleanup_existing);
exception_ptr get_exception() const BOOST_NOEXCEPT
{ return except_; }
void set_exception( exception_ptr except) BOOST_NOEXCEPT
{ except_ = except; }
void resume( fiber_base * current, bool preserve_fpu_)
{
BOOST_ASSERT( 0 != current);
BOOST_ASSERT( is_running() ); // set by the scheduler-algorithm
context::jump_fcontext(
& current->ctx_, ctx_, reinterpret_cast< intptr_t >( this), preserve_fpu_);
}
fiber_base * next() const BOOST_NOEXCEPT
{ return nxt_; }
void next( fiber_base * nxt) BOOST_NOEXCEPT
{ nxt_ = nxt; }
void next_reset() BOOST_NOEXCEPT
{ nxt_ = 0; }
chrono::high_resolution_clock::time_point const& time_point() const BOOST_NOEXCEPT
{ return tp_; }
void time_point( chrono::high_resolution_clock::time_point const& tp)
{ tp_ = tp; }
void time_point_reset()
{ tp_ = (chrono::high_resolution_clock::time_point::max)(); }
void release();
virtual void deallocate() = 0;
friend void intrusive_ptr_add_ref( fiber_base * f)
{ ++f->use_count_; }
friend void intrusive_ptr_release( fiber_base * f)
{
BOOST_ASSERT( 0 != f);
if ( 0 == --f->use_count_)
{
BOOST_ASSERT( f->is_terminated() );
f->deallocate();
}
}
};
}}}

View File

@@ -15,7 +15,7 @@
#include <boost/utility.hpp>
#include <boost/fiber/detail/config.hpp>
#include <boost/fiber/detail/worker_fiber.hpp>
#include <boost/fiber/detail/fiber_base.hpp>
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_PREFIX
@@ -36,7 +36,7 @@ public:
bool empty() const BOOST_NOEXCEPT
{ return 0 == head_; }
void push( worker_fiber * item) BOOST_NOEXCEPT
void push( fiber_base * item) BOOST_NOEXCEPT
{
BOOST_ASSERT( 0 != item);
BOOST_ASSERT( 0 == item->next() );
@@ -50,11 +50,11 @@ public:
}
}
worker_fiber * pop() BOOST_NOEXCEPT
fiber_base * pop() BOOST_NOEXCEPT
{
BOOST_ASSERT( ! empty() );
worker_fiber * item = head_;
fiber_base * item = head_;
head_ = head_->next();
if ( 0 == head_) tail_ = 0;
item->next_reset();
@@ -68,8 +68,8 @@ public:
}
private:
worker_fiber * head_;
worker_fiber * tail_;
fiber_base * head_;
fiber_base * tail_;
};
}}}

View File

@@ -23,29 +23,14 @@ namespace detail {
class main_fiber : public fiber_base
{
public:
static main_fiber * make_pointer( main_fiber & n) {
return & n;
main_fiber() :
fiber_base( 0) // main-fiber represents main-context
{
thread_affinity( true);
set_running();
}
main_fiber() :
fiber_base(),
ready_( false)
{}
bool is_ready() const BOOST_NOEXCEPT
{ return ready_; }
void set_ready() BOOST_NOEXCEPT
{ ready_ = true; }
id get_id() const BOOST_NOEXCEPT
{ return id( const_cast< main_fiber * >( this) ); }
private:
atomic< bool > ready_;
main_fiber( main_fiber const&);
main_fiber & operator=( main_fiber const&);
void deallocate() {}
};
}}}

View File

@@ -141,7 +141,7 @@ private:
public:
template< typename F >
static worker_fiber * extract( F const& f) BOOST_NOEXCEPT
static fiber_base * extract( F const& f) BOOST_NOEXCEPT
{ return f.impl_.get(); }
static fiber_manager * instance()

View File

@@ -1,80 +0,0 @@
// Copyright Oliver Kowalke 2009.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_FIBERS_DETAIL_SETUP_H
#define BOOST_FIBERS_DETAIL_SETUP_H
#include <boost/assert.hpp>
#include <boost/config.hpp>
#include <boost/move/move.hpp>
#include <boost/type_traits/decay.hpp>
#include <boost/type_traits/is_convertible.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/fiber/detail/config.hpp>
#include <boost/fiber/detail/worker_fiber.hpp>
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_PREFIX
#endif
namespace boost {
namespace fibers {
namespace detail {
template< typename Fn >
struct setup
{
typedef typename worker_fiber::coro_t coro_t;
struct dummy {};
Fn fn;
typename coro_t::call_type * caller;
worker_fiber * f;
#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
setup( Fn fn_,
coro_t::call_type * caller_) :
fn( boost::forward< Fn >( fn_) ),
caller( caller_),
f( 0)
{ BOOST_ASSERT( 0 != caller); }
#endif
setup( BOOST_RV_REF( Fn) fn_,
coro_t::call_type * caller_,
typename disable_if<
is_same< typename decay< Fn >::type, setup >,
dummy*
>::type = 0) :
#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
fn( fn_),
#else
fn( boost::forward< Fn >( fn_) ),
#endif
caller( caller_),
f( 0)
{ BOOST_ASSERT( 0 != caller); }
worker_fiber * allocate()
{
// enter fiber-fn (trampoline<>)
// and pas this as argument
( * caller)( this);
// jumped back; move coroutine to worker_fiber
f->caller_ = boost::move( * caller);
return f;
}
};
}}}
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_SUFFIX
#endif
#endif // BOOST_FIBERS_DETAIL_SETUP_H

View File

@@ -1,92 +0,0 @@
// Copyright Oliver Kowalke 2009.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_FIBERS_DETAIL_TRAMPOLINE_H
#define BOOST_FIBERS_DETAIL_TRAMPOLINE_H
#include <cstddef>
#include <exception>
#include <boost/assert.hpp>
#include <boost/config.hpp>
#include <boost/coroutine/exceptions.hpp>
#include <boost/coroutine/symmetric_coroutine.hpp>
#include <boost/cstdint.hpp>
#include <boost/exception_ptr.hpp>
#include <boost/move/move.hpp>
#include <boost/fiber/detail/config.hpp>
#include <boost/fiber/detail/setup.hpp>
#include <boost/fiber/detail/worker_fiber.hpp>
#include <boost/fiber/exceptions.hpp>
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_PREFIX
#endif
namespace boost {
namespace fibers {
namespace detail {
namespace coro = boost::coroutines;
template< typename Fn >
void trampoline( typename worker_fiber::coro_t::yield_type & yield)
{
BOOST_ASSERT( yield);
void * p( yield.get() );
BOOST_ASSERT( p);
setup< Fn > * from( static_cast< setup< Fn > * >( p) );
// allocate instance of worker-fiber on its stack
worker_fiber f( & yield);
// return address of worker-fiber instance
from->f = & f;
try
{
// allocate fiber-function on worker-fiber's stack
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
Fn fn( boost::forward< Fn >( from->fn) );
#else
Fn fn( boost::move( from->fn) );
#endif
// after setup return to caller
f.set_running();
f.suspend();
// start executing fiber-function
BOOST_ASSERT( f.is_running() );
fn();
BOOST_ASSERT( f.is_running() );
}
catch ( coro::detail::forced_unwind const&)
{
f.set_terminated();
f.release();
throw;
}
catch ( fiber_interrupted const&)
{ f.set_exception( current_exception() ); }
catch (...)
{ std::terminate(); }
f.set_terminated();
f.release();
f.suspend();
BOOST_ASSERT_MSG( false, "fiber already terminated");
}
}}}
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_SUFFIX
#endif
#endif // BOOST_FIBERS_DETAIL_TRAMPOLINE_H

View File

@@ -16,7 +16,7 @@
#include <boost/utility.hpp>
#include <boost/fiber/detail/config.hpp>
#include <boost/fiber/detail/worker_fiber.hpp>
#include <boost/fiber/detail/fiber_base.hpp>
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_PREFIX
@@ -37,7 +37,7 @@ public:
bool empty() const BOOST_NOEXCEPT
{ return 0 == head_; }
void push( worker_fiber * item) BOOST_NOEXCEPT
void push( fiber_base * item) BOOST_NOEXCEPT
{
BOOST_ASSERT( 0 != item);
BOOST_ASSERT( 0 == item->next() );
@@ -46,10 +46,10 @@ public:
head_ = tail_ = item;
else
{
worker_fiber * f = head_, * prev = 0;
fiber_base * f = head_, * prev = 0;
do
{
worker_fiber * nxt = f->next();
fiber_base * nxt = f->next();
if ( item->time_point() <= f->time_point() )
{
if ( head_ == f)
@@ -84,7 +84,7 @@ public:
}
}
worker_fiber * top() const BOOST_NOEXCEPT
fiber_base * top() const BOOST_NOEXCEPT
{
BOOST_ASSERT( ! empty() );
@@ -96,11 +96,11 @@ public:
{
BOOST_ASSERT( sched_algo);
worker_fiber * f = head_, * prev = 0;
fiber_base * f = head_, * prev = 0;
chrono::high_resolution_clock::time_point now( chrono::high_resolution_clock::now() );
while ( 0 != f)
{
worker_fiber * nxt = f->next();
fiber_base * nxt = f->next();
if ( fn( f, now) )
{
if ( f == head_)
@@ -137,8 +137,8 @@ public:
}
private:
worker_fiber * head_;
worker_fiber * tail_;
fiber_base * head_;
fiber_base * tail_;
};
}}}

View File

@@ -7,28 +7,19 @@
#ifndef BOOST_FIBERS_DETAIL_WORKER_FIBER_H
#define BOOST_FIBERS_DETAIL_WORKER_FIBER_H
#include <cstddef>
#include <map>
#include <vector>
#include <exception> // std::terminate()
#include <boost/assert.hpp>
#include <boost/atomic.hpp>
#include <boost/chrono/system_clocks.hpp>
#include <boost/config.hpp>
#include <boost/cstdint.hpp>
#include <boost/coroutine/symmetric_coroutine.hpp>
#include <boost/exception_ptr.hpp>
#include <boost/intrusive_ptr.hpp>
#include <boost/context/all.hpp>
#include <boost/move/move.hpp>
#include <boost/utility.hpp>
#include <boost/fiber/attributes.hpp>
#include <boost/fiber/detail/config.hpp>
#include <boost/fiber/detail/fiber_base.hpp>
#include <boost/fiber/detail/flags.hpp>
#include <boost/fiber/detail/fss.hpp>
#include <boost/fiber/detail/spinlock.hpp>
#include <boost/fiber/exceptions.hpp>
#include <boost/fiber/fiber_manager.hpp>
#include <boost/fiber/stack_context.hpp>
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_PREFIX
@@ -43,219 +34,87 @@ namespace boost {
namespace fibers {
namespace detail {
namespace coro = boost::coroutines;
class BOOST_FIBERS_DECL worker_fiber : public fiber_base
template< typename Fn, typename StackAllocator >
class worker_fiber : public fiber_base
{
public:
typedef coro::symmetric_coroutine<
void *
> coro_t;
private:
template< typename Fn >
friend struct setup;
Fn fn_;
StackAllocator salloc_;
stack_context sctx_;
enum state_t
void run_()
{
READY = 0,
RUNNING,
WAITING,
TERMINATED
};
struct BOOST_FIBERS_DECL fss_data
{
void * vp;
fss_cleanup_function::ptr_t cleanup_function;
fss_data() :
vp( 0), cleanup_function( 0)
try
{
BOOST_ASSERT( is_running() );
fn_();
BOOST_ASSERT( is_running() );
}
#if 0
catch( forced_unwind const&)
{}
fss_data(
void * vp_,
fss_cleanup_function::ptr_t const& fn) :
vp( vp_), cleanup_function( fn)
{ BOOST_ASSERT( cleanup_function); }
void do_cleanup()
{ ( * cleanup_function)( vp); }
};
typedef std::map< uintptr_t, fss_data > fss_data_t;
static void * null_ptr;
atomic< std::size_t > use_count_;
fss_data_t fss_data_;
worker_fiber * nxt_;
chrono::high_resolution_clock::time_point tp_;
coro_t::yield_type * callee_;
coro_t::call_type caller_;
atomic< state_t > state_;
atomic< int > flags_;
atomic< int > priority_;
exception_ptr except_;
spinlock splk_;
std::vector< worker_fiber * > waiting_;
#endif
catch( fiber_interrupted const& )
{
except_ = current_exception();
}
catch( ... )
{
std::terminate();
}
set_terminated();
release(); // notify joining fibers
fibers::fm_run();
BOOST_ASSERT_MSG( false, "fiber already terminated");
}
public:
worker_fiber( coro_t::yield_type *);
static void entry_func( intptr_t);
~worker_fiber();
#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
worker_fiber( Fn fn, void * sp, std::size_t size,
StackAllocator const& salloc, stack_context const& sctx) :
fiber_base( context::make_fcontext( sp, size, & worker_fiber::entry_func) ),
fn_( boost::forward< Fn >( fn) ),
salloc_( salloc),
sctx_( sctx)
{}
#endif
id get_id() const BOOST_NOEXCEPT
{ return id( const_cast< worker_fiber * >( this) ); }
int priority() const BOOST_NOEXCEPT
{ return priority_; }
void priority( int prio) BOOST_NOEXCEPT
{ priority_ = prio; }
bool join( worker_fiber *);
bool interruption_blocked() const BOOST_NOEXCEPT
{ return 0 != ( flags_.load() & flag_interruption_blocked); }
void interruption_blocked( bool blck) BOOST_NOEXCEPT;
bool interruption_requested() const BOOST_NOEXCEPT
{ return 0 != ( flags_.load() & flag_interruption_requested); }
void request_interruption( bool req) BOOST_NOEXCEPT;
bool thread_affinity() const BOOST_NOEXCEPT
{ return 0 != ( flags_.load() & flag_thread_affinity); }
void thread_affinity( bool req) BOOST_NOEXCEPT;
bool is_terminated() const BOOST_NOEXCEPT
{ return TERMINATED == state_; }
bool is_ready() const BOOST_NOEXCEPT
{ return READY == state_; }
bool is_running() const BOOST_NOEXCEPT
{ return RUNNING == state_; }
bool is_waiting() const BOOST_NOEXCEPT
{ return WAITING == state_; }
void set_terminated() BOOST_NOEXCEPT
{
state_t previous = state_.exchange( TERMINATED);
BOOST_ASSERT( RUNNING == previous);
(void)previous;
}
void set_ready() BOOST_NOEXCEPT
{
state_t previous = state_.exchange( READY);
BOOST_ASSERT( WAITING == previous || RUNNING == previous || READY == previous);
(void)previous;
}
void set_running() BOOST_NOEXCEPT
{
state_t previous = state_.exchange( RUNNING);
BOOST_ASSERT( READY == previous);
(void)previous;
}
void set_waiting() BOOST_NOEXCEPT
{
state_t previous = state_.exchange( WAITING);
BOOST_ASSERT( RUNNING == previous);
(void)previous;
}
void * get_fss_data( void const* vp) const;
void set_fss_data(
void const* vp,
fss_cleanup_function::ptr_t const& cleanup_fn,
void * data,
bool cleanup_existing);
exception_ptr get_exception() const BOOST_NOEXCEPT
{ return except_; }
void set_exception( exception_ptr except) BOOST_NOEXCEPT
{ except_ = except; }
void resume( worker_fiber * f)
{
BOOST_ASSERT( caller_);
BOOST_ASSERT( is_running() ); // set by the scheduler-algorithm
if ( 0 == f)
{
// called from main-fiber
caller_( null_ptr);
}
else
{
// caller from worker-fiber f
BOOST_ASSERT( f->callee_);
( * f->callee_)( caller_, null_ptr);
}
}
void suspend()
{
BOOST_ASSERT( callee_);
BOOST_ASSERT( * callee_);
( * callee_)();
BOOST_ASSERT( is_running() ); // set by the scheduler-algorithm
}
worker_fiber * next() const BOOST_NOEXCEPT
{ return nxt_; }
void next( worker_fiber * nxt) BOOST_NOEXCEPT
{ nxt_ = nxt; }
void next_reset() BOOST_NOEXCEPT
{ nxt_ = 0; }
chrono::high_resolution_clock::time_point const& time_point() const BOOST_NOEXCEPT
{ return tp_; }
void time_point( chrono::high_resolution_clock::time_point const& tp)
{ tp_ = tp; }
void time_point_reset()
{ tp_ = (chrono::high_resolution_clock::time_point::max)(); }
void release();
worker_fiber( BOOST_RV_REF( Fn) fn, void * sp, std::size_t size,
StackAllocator const& salloc, stack_context const& sctx) :
fiber_base( context::make_fcontext( sp, size, & worker_fiber::entry_func) ),
#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
fn_( fn),
#else
fn_( boost::forward< Fn >( fn) ),
#endif
salloc_( salloc),
sctx_( sctx)
{}
void deallocate()
{
callee_ = 0;
// destroyes coroutine and deallocates stack
coro_t::call_type tmp( boost::move( caller_) );
}
friend void intrusive_ptr_add_ref( worker_fiber * f)
{ ++f->use_count_; }
friend void intrusive_ptr_release( worker_fiber * f)
{
BOOST_ASSERT( 0 != f);
if ( 0 == --f->use_count_)
{
BOOST_ASSERT( f->is_terminated() );
f->deallocate();
}
// FIXME: correct?
StackAllocator salloc( salloc_);
stack_context sctx( sctx_);
// call destructor of worker_fiber
this->~worker_fiber();
// deallocate stack
salloc.deallocate( sctx);
}
};
template< typename Fn, typename StackAllocator >
void
worker_fiber< Fn, StackAllocator >::entry_func( intptr_t param)
{
worker_fiber< Fn, StackAllocator > * f(
reinterpret_cast< worker_fiber< Fn, StackAllocator > * >( param) );
BOOST_ASSERT( 0 != f);
f->run_();
}
}}}
# if defined(BOOST_MSVC)

View File

@@ -9,12 +9,11 @@
#include <algorithm>
#include <cstddef>
#include <exception>
#include <exception> // std::terminate()
#include <memory>
#include <boost/assert.hpp>
#include <boost/config.hpp>
#include <boost/coroutine/symmetric_coroutine.hpp>
#include <boost/intrusive_ptr.hpp>
#include <boost/move/move.hpp>
#include <boost/thread/detail/memory.hpp> // boost::allocator_arg_t
@@ -23,10 +22,10 @@
#include <boost/fiber/attributes.hpp>
#include <boost/fiber/detail/config.hpp>
#include <boost/fiber/detail/setup.hpp>
#include <boost/fiber/detail/trampoline.hpp>
#include <boost/fiber/detail/fiber_base.hpp>
#include <boost/fiber/detail/worker_fiber.hpp>
#include <boost/fiber/stack_allocator.hpp>
#include <boost/fiber/stack_context.hpp>
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_PREFIX
@@ -40,8 +39,6 @@
namespace boost {
namespace fibers {
namespace coro = boost::coroutines;
namespace detail {
class scheduler;
@@ -53,8 +50,7 @@ class BOOST_FIBERS_DECL fiber : private noncopyable
private:
friend class detail::scheduler;
typedef detail::worker_fiber base_t;
typedef base_t::coro_t coro_t;
typedef detail::fiber_base base_t;
typedef intrusive_ptr< base_t > ptr_t;
ptr_t impl_;
@@ -65,49 +61,73 @@ private:
typedef void ( * fiber_fn)();
template< typename StackAllocator >
void setup_( StackAllocator const& stack_alloc, attributes const& attrs, fiber_fn fn)
base_t * make_fiber_( StackAllocator salloc, attributes const& attrs, fiber_fn fn)
{
coro_t::call_type coro( detail::trampoline< fiber_fn >, attrs, stack_alloc);
detail::setup< fiber_fn > s( boost::forward< fiber_fn >( fn), & coro);
impl_.reset( s.allocate() );
BOOST_ASSERT( impl_);
typedef detail::worker_fiber< fiber_fn, StackAllocator > wrk_t;
// create a stack-context
stack_context sctx;
// allocate fiber-stack
salloc.allocate( sctx, attrs.size);
BOOST_ASSERT( 0 < sctx.sp);
// reserve space for worker_fiber on top of stack
std::size_t size = sctx.size - sizeof( wrk_t);
void * sp = static_cast< char * >( sctx.sp) - sizeof( wrk_t);
// placement new for worker_fiber
return new( sp) wrk_t( boost::forward< fiber_fn >( fn), sp, size, salloc, sctx);
}
#endif
#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
template< typename StackAllocator, typename Fn >
void setup_( StackAllocator const& stack_alloc, attributes const& attrs, Fn fn)
base_t * make_fiber_( StackAllocator salloc, attributes const& attrs, Fn fn)
{
typename coro_t::call_type coro( detail::trampoline< Fn >, attrs, stack_alloc);
detail::setup< Fn > s( boost::forward< Fn >( fn), & coro);
impl_.reset( s.allocate() );
BOOST_ASSERT( impl_);
typedef detail::worker_fiber< Fn, StackAllocator > wrk_t;
// create a stack-context
stack_context sctx;
// allocate fiber-stack
salloc.allocate( sctx, attrs.size);
BOOST_ASSERT( 0 < sctx.sp);
// reserve space for worker_fiber on top of stack
std::size_t size = sctx.size - sizeof( wrk_t);
void * sp = static_cast< char * >( sctx.sp) - sizeof( wrk_t);
// placement new for worker_fiber
return new( sp) wrk_t( boost::forward< Fn >( fn), sp, size, salloc, sctx);
}
#endif
template< typename StackAllocator, typename Fn >
void setup_( StackAllocator const& stack_alloc, attributes const& attrs, BOOST_RV_REF( Fn) fn)
base_t * make_fiber_( StackAllocator salloc, attributes const& attrs, BOOST_RV_REF( Fn) fn)
{
typename coro_t::call_type coro( detail::trampoline< Fn >, attrs, stack_alloc);
typedef detail::worker_fiber< Fn, StackAllocator > wrk_t;
// create a stack-context
stack_context sctx;
// allocate fiber-stack
salloc.allocate( sctx, attrs.size);
BOOST_ASSERT( 0 < sctx.sp);
// reserve space for worker_fiber on top of stack
std::size_t size = sctx.size - sizeof( wrk_t);
void * sp = static_cast< char * >( sctx.sp) - sizeof( wrk_t);
// placement new for worker_fiber
#ifdef BOOST_NO_RVALUE_REFERENCES
detail::setup< Fn > s( fn, & coro);
return new( sp) wrk_t( fn, sp, size, salloc, sctx);
#else
detail::setup< Fn > s( boost::forward< Fn >( fn), & coro);
return new( sp) wrk_t( boost::forward< Fn >( fn), sp, size, salloc, sctx);
#endif
impl_.reset( s.allocate() );
BOOST_ASSERT( impl_);
}
void start_();
public:
typedef detail::worker_fiber::id id;
typedef detail::fiber_base::id id;
fiber() BOOST_NOEXCEPT :
impl_()
{}
explicit fiber( detail::worker_fiber * impl) BOOST_NOEXCEPT :
explicit fiber( detail::fiber_base * impl) BOOST_NOEXCEPT :
impl_( impl)
{}
@@ -116,33 +136,33 @@ public:
impl_()
{
attributes attrs;
stack_allocator stack_alloc;
setup_( stack_alloc, attrs, fn);
stack_allocator salloc;
impl_.reset( make_fiber_( salloc, attrs, fn) );
start_();
}
fiber( attributes const& attrs, fiber_fn fn) :
impl_()
{
stack_allocator stack_alloc;
setup_( stack_alloc, attrs, fn);
stack_allocator salloc;
impl_.reset( make_fiber_( salloc, attrs, fn) );
start_();
}
template< typename StackAllocator >
fiber( boost::allocator_arg_t, StackAllocator const& stack_alloc, fiber_fn fn) :
fiber( boost::allocator_arg_t, StackAllocator salloc, fiber_fn fn) :
impl_()
{
attributes attrs;
setup_( stack_alloc, attrs, fn);
impl_.reset( make_fiber_( salloc, attrs, fn) );
start_();
}
template< typename StackAllocator >
fiber( boost::allocator_arg_t, StackAllocator const& stack_alloc, attributes const& attrs, fiber_fn fn) :
fiber( boost::allocator_arg_t, StackAllocator salloc, attributes const& attrs, fiber_fn fn) :
impl_()
{
setup_( stack_alloc, attrs, fn);
impl_.reset( make_fiber_( salloc, attrs, fn) );
start_();
}
#endif
@@ -153,8 +173,8 @@ public:
impl_()
{
attributes attrs;
stack_allocator stack_alloc;
setup_( stack_alloc, attrs, fn);
stack_allocator salloc;
impl_.reset( make_fiber_( salloc, attrs, fn) );
start_();
}
@@ -162,25 +182,25 @@ public:
fiber( attributes const& attrs, Fn fn) :
impl_()
{
stack_allocator stack_alloc;
setup_( stack_alloc, attrs, fn);
stack_allocator salloc;
impl_.reset( make_fiber_( salloc, attrs, fn) );
start_();
}
template< typename StackAllocator, typename Fn >
fiber( boost::allocator_arg_t, StackAllocator const& stack_alloc, Fn fn) :
fiber( boost::allocator_arg_t, StackAllocator salloc, Fn fn) :
impl_()
{
attributes attrs;
setup_( stack_alloc, attrs, fn);
impl_.reset( make_fiber_( salloc, attrs, fn) );
start_();
}
template< typename StackAllocator, typename Fn >
fiber( boost::allocator_arg_t, StackAllocator const& stack_alloc, attributes const& attrs, Fn fn) :
fiber( boost::allocator_arg_t, StackAllocator salloc, attributes const& attrs, Fn fn) :
impl_()
{
setup_( stack_alloc, attrs, fn);
impl_.reset( make_fiber_( salloc, attrs, fn) );
start_();
}
#endif
@@ -190,11 +210,11 @@ public:
impl_()
{
attributes attrs;
stack_allocator stack_alloc;
stack_allocator salloc;
#ifdef BOOST_NO_RVALUE_REFERENCES
setup_( stack_alloc, attrs, fn);
impl_.reset( make_fiber_( salloc, attrs, fn) );
#else
setup_( stack_alloc, attrs, boost::forward< Fn >( fn) );
impl_.reset( make_fiber_( salloc, attrs, boost::forward< Fn >( fn) ) );
#endif
start_();
}
@@ -203,36 +223,36 @@ public:
fiber( attributes const& attrs, BOOST_RV_REF( Fn) fn) :
impl_()
{
stack_allocator stack_alloc;
stack_allocator salloc;
#ifdef BOOST_NO_RVALUE_REFERENCES
setup_( stack_alloc, attrs, fn);
impl_.reset( make_fiber_( salloc, attrs, fn) );
#else
setup_( stack_alloc, attrs, boost::forward< Fn >( fn) );
impl_.reset( make_fiber_( salloc, attrs, boost::forward< Fn >( fn) ) );
#endif
start_();
}
template< typename StackAllocator, typename Fn >
fiber( boost::allocator_arg_t, StackAllocator const& stack_alloc, BOOST_RV_REF( Fn) fn) :
fiber( boost::allocator_arg_t, StackAllocator salloc, BOOST_RV_REF( Fn) fn) :
impl_()
{
attributes attrs;
#ifdef BOOST_NO_RVALUE_REFERENCES
setup_( stack_alloc, attrs, fn);
impl_.reset( make_fiber_( salloc, attrs, fn) );
#else
setup_( stack_alloc, attrs, boost::forward< Fn >( fn) );
impl_.reset( make_fiber_( salloc, attrs, boost::forward< Fn >( fn) ) );
#endif
start_();
}
template< typename StackAllocator, typename Fn >
fiber( boost::allocator_arg_t, StackAllocator const& stack_alloc, attributes const& attrs, BOOST_RV_REF( Fn) fn) :
fiber( boost::allocator_arg_t, StackAllocator salloc, attributes const& attrs, BOOST_RV_REF( Fn) fn) :
impl_()
{
#ifdef BOOST_NO_RVALUE_REFERENCES
setup_( stack_alloc, attrs, fn);
impl_.reset( make_fiber_( salloc, attrs, fn) );
#else
setup_( stack_alloc, attrs, boost::forward< Fn >( fn) );
impl_.reset( make_fiber_( salloc, attrs, boost::forward< Fn >( fn) ) );
#endif
start_();
}
@@ -243,8 +263,9 @@ public:
impl_()
{
attributes attrs;
stack_allocator stack_alloc;
setup_( stack_alloc, attrs, std::bind( std::forward< Fn >( fn), std::forward< Args >( args) ... ) );
stack_allocator salloc;
impl_.reset(
make_fiber_( salloc, attrs, std::bind( std::forward< Fn >( fn), std::forward< Args >( args) ... ) ) );
start_();
}
@@ -252,26 +273,29 @@ public:
fiber( attributes const& attrs, BOOST_RV_REF( Fn) fn, BOOST_RV_REF( Args) ... args) :
impl_()
{
stack_allocator stack_alloc;
setup_( stack_alloc, attrs, std::bind( std::forward< Fn >( fn), std::forward< Args >( args) ... ) );
stack_allocator salloc;
impl_.reset(
make_fiber_( salloc, attrs, std::bind( std::forward< Fn >( fn), std::forward< Args >( args) ... ) ) );
start_();
}
template< typename StackAllocator, typename Fn, class ... Args >
fiber( boost::allocator_arg_t, StackAllocator const& stack_alloc, BOOST_RV_REF( Fn) fn, BOOST_RV_REF( Args) ... args) :
fiber( boost::allocator_arg_t, StackAllocator salloc, BOOST_RV_REF( Fn) fn, BOOST_RV_REF( Args) ... args) :
impl_()
{
attributes attrs;
setup_( stack_alloc, attrs, std::bind( std::forward< Fn >( fn), std::forward< Args >( args) ... ) );
impl_.reset(
make_fiber_( salloc, attrs, std::bind( std::forward< Fn >( fn), std::forward< Args >( args) ... ) ) );
start_();
}
template< typename StackAllocator, typename Fn, class ... Args >
fiber( boost::allocator_arg_t, StackAllocator const& stack_alloc, attributes const& attrs,
fiber( boost::allocator_arg_t, StackAllocator salloc, attributes const& attrs,
BOOST_RV_REF( Fn) fn, BOOST_RV_REF( Args) ... args) :
impl_()
{
setup_( stack_alloc, attrs, std::bind( std::forward< Fn >( fn), std::forward< Args >( args) ... ) );
impl_.reset(
make_fiber_( salloc, attrs, std::bind( std::forward< Fn >( fn), std::forward< Args >( args) ... ) ) );
start_();
}
#endif

View File

@@ -16,11 +16,10 @@
#include <boost/fiber/algorithm.hpp>
#include <boost/fiber/detail/config.hpp>
#include <boost/fiber/detail/convert.hpp>
#include <boost/fiber/detail/fiber_base.hpp>
#include <boost/fiber/detail/main_fiber.hpp>
#include <boost/fiber/detail/spinlock.hpp>
#include <boost/fiber/detail/waiting_queue.hpp>
#include <boost/fiber/detail/worker_fiber.hpp>
#include <boost/fiber/fiber.hpp>
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_PREFIX
@@ -42,21 +41,22 @@ struct fiber_manager : private noncopyable
typedef detail::waiting_queue wqueue_t;
scoped_ptr< sched_algorithm > def_algo_;
sched_algorithm * sched_algo_;
wqueue_t wqueue_;
chrono::high_resolution_clock::duration wait_interval_;
detail::worker_fiber * active_fiber_;
scoped_ptr< sched_algorithm > def_algo;
sched_algorithm * sched_algo;
wqueue_t wqueue;
bool preserve_fpu;
detail::main_fiber main_fiber_;
chrono::high_resolution_clock::duration wait_interval;
detail::fiber_base * active_fiber;
};
void fm_resume_( detail::worker_fiber *);
void fm_resume_( detail::fiber_base *);
void fm_set_sched_algo( sched_algorithm *);
void fm_spawn( detail::worker_fiber *);
void fm_spawn( detail::fiber_base *);
void fm_priority( detail::worker_fiber *, int) BOOST_NOEXCEPT;
void fm_priority( detail::fiber_base *, int) BOOST_NOEXCEPT;
void fm_wait_interval( chrono::high_resolution_clock::duration const&) BOOST_NOEXCEPT;
template< typename Rep, typename Period >
@@ -65,9 +65,9 @@ void fm_wait_interval( chrono::duration< Rep, Period > const& wait_interval) BOO
chrono::high_resolution_clock::duration fm_wait_interval() BOOST_NOEXCEPT;
void fm_join( detail::worker_fiber *);
void fm_join( detail::fiber_base *);
detail::worker_fiber * fm_active() BOOST_NOEXCEPT;
detail::fiber_base * fm_active() BOOST_NOEXCEPT;
void fm_run();
@@ -96,7 +96,10 @@ void fm_yield();
chrono::high_resolution_clock::time_point fm_next_wakeup();
void fm_migrate( detail::worker_fiber *);
void fm_migrate( detail::fiber_base *);
bool fm_preserve_fpu_();
void fm_preserve_fpu_( bool);
}}

View File

@@ -13,7 +13,7 @@
#include <boost/utility.hpp>
#include <boost/fiber/detail/config.hpp>
#include <boost/fiber/detail/worker_fiber.hpp>
#include <boost/fiber/detail/fiber_base.hpp>
#include <boost/fiber/detail/fiber_base.hpp>
#include <boost/fiber/detail/spinlock.hpp>
@@ -40,7 +40,7 @@ private:
detail::spinlock splk_;
state_t state_;
detail::worker_fiber::id owner_;
detail::fiber_base::id owner_;
std::deque< detail::fiber_base * > waiting_;
bool lock_if_unlocked_();

View File

@@ -16,7 +16,7 @@
#include <boost/utility.hpp>
#include <boost/fiber/detail/config.hpp>
#include <boost/fiber/detail/worker_fiber.hpp>
#include <boost/fiber/detail/fiber_base.hpp>
#include <boost/fiber/detail/fiber_base.hpp>
#include <boost/fiber/detail/spinlock.hpp>
@@ -43,7 +43,7 @@ private:
detail::spinlock splk_;
state_t state_;
detail::worker_fiber::id owner_;
detail::fiber_base::id owner_;
std::size_t count_;
std::deque< detail::fiber_base * > waiting_;

View File

@@ -18,7 +18,7 @@
#include <boost/fiber/detail/config.hpp>
#include <boost/fiber/detail/convert.hpp>
#include <boost/fiber/detail/worker_fiber.hpp>
#include <boost/fiber/detail/fiber_base.hpp>
#include <boost/fiber/detail/spinlock.hpp>
#include <boost/fiber/detail/fiber_base.hpp>
@@ -45,7 +45,7 @@ private:
detail::spinlock splk_;
state_t state_;
detail::worker_fiber::id owner_;
detail::fiber_base::id owner_;
std::size_t count_;
std::deque< detail::fiber_base * > waiting_;

View File

@@ -11,7 +11,7 @@
#include <boost/fiber/algorithm.hpp>
#include <boost/fiber/detail/config.hpp>
#include <boost/fiber/detail/fifo.hpp>
#include <boost/fiber/detail/worker_fiber.hpp>
#include <boost/fiber/detail/fiber_base.hpp>
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_PREFIX
@@ -33,11 +33,11 @@ private:
rqueue_t rqueue_;
public:
virtual void awakened( detail::worker_fiber *);
virtual void awakened( detail::fiber_base *);
virtual detail::worker_fiber * pick_next();
virtual detail::fiber_base * pick_next();
virtual void priority( detail::worker_fiber *, int) BOOST_NOEXCEPT;
virtual void priority( detail::fiber_base *, int) BOOST_NOEXCEPT;
};
}}

View File

@@ -0,0 +1,32 @@
// Copyright Oliver Kowalke 2009.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_FIBERS_STACK_CONTEXT_H
#define BOOST_FIBERS_STACK_CONTEXT_H
#include <cstddef>
#include <boost/config.hpp>
#include <boost/coroutine/stack_context.hpp>
#include <boost/fiber/detail/config.hpp>
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_PREFIX
#endif
namespace boost {
namespace fibers {
typedef coroutines::stack_context stack_context;
}}
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_SUFFIX
#endif
#endif // BOOST_FIBERS_STACK_CONTEXT_H

View File

@@ -15,7 +15,7 @@
#include <boost/fiber/detail/config.hpp>
#include <boost/fiber/detail/convert.hpp>
#include <boost/fiber/detail/worker_fiber.hpp>
#include <boost/fiber/detail/fiber_base.hpp>
#include <boost/fiber/detail/fiber_base.hpp>
#include <boost/fiber/detail/spinlock.hpp>
@@ -42,7 +42,7 @@ private:
detail::spinlock splk_;
state_t state_;
detail::worker_fiber::id owner_;
detail::fiber_base::id owner_;
std::deque< detail::fiber_base * > waiting_;
bool lock_if_unlocked_();