mirror of
https://github.com/boostorg/fiber.git
synced 2026-02-18 01:52:24 +00:00
some fixes
This commit is contained in:
@@ -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;
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
}}}
|
||||
|
||||
@@ -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_;
|
||||
};
|
||||
|
||||
}}}
|
||||
|
||||
@@ -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() {}
|
||||
};
|
||||
|
||||
}}}
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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_;
|
||||
};
|
||||
|
||||
}}}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
}}
|
||||
|
||||
|
||||
@@ -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_();
|
||||
|
||||
@@ -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_;
|
||||
|
||||
|
||||
@@ -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_;
|
||||
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
32
include/boost/fiber/stack_context.hpp
Normal file
32
include/boost/fiber/stack_context.hpp
Normal 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
|
||||
@@ -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_();
|
||||
|
||||
Reference in New Issue
Block a user