mirror of
https://github.com/boostorg/fiber.git
synced 2026-02-02 20:52:21 +00:00
Merge branch 'feature/pointer' into develop
This commit is contained in:
@@ -31,8 +31,7 @@ project boost/fiber
|
||||
;
|
||||
|
||||
lib boost_fiber
|
||||
: asio/round_robin.cpp
|
||||
barrier.cpp
|
||||
: barrier.cpp
|
||||
condition.cpp
|
||||
detail/worker_fiber.cpp
|
||||
detail/scheduler.cpp
|
||||
|
||||
@@ -31,13 +31,13 @@ namespace fibers {
|
||||
|
||||
struct algorithm : private noncopyable
|
||||
{
|
||||
virtual void spawn( detail::worker_fiber::ptr_t const&) = 0;
|
||||
virtual void spawn( detail::worker_fiber *) = 0;
|
||||
|
||||
virtual void priority( detail::worker_fiber::ptr_t const&, int) BOOST_NOEXCEPT = 0;
|
||||
virtual void priority( detail::worker_fiber *, int) BOOST_NOEXCEPT = 0;
|
||||
|
||||
virtual void join( detail::worker_fiber::ptr_t const&) = 0;
|
||||
virtual void join( detail::worker_fiber *) = 0;
|
||||
|
||||
virtual detail::worker_fiber::ptr_t active() BOOST_NOEXCEPT = 0;
|
||||
virtual detail::worker_fiber * active() BOOST_NOEXCEPT = 0;
|
||||
|
||||
virtual void run() = 0;
|
||||
|
||||
@@ -51,7 +51,7 @@ struct algorithm : private noncopyable
|
||||
|
||||
virtual void yield() = 0;
|
||||
|
||||
virtual detail::fiber_base::ptr_t get_main_fiber() = 0;
|
||||
virtual detail::fiber_base * get_main_fiber() = 0;
|
||||
|
||||
virtual ~algorithm() {}
|
||||
};
|
||||
|
||||
@@ -8,10 +8,10 @@
|
||||
#define BOOST_FIBERS_H
|
||||
|
||||
#include <boost/fiber/algorithm.hpp>
|
||||
#include <boost/fiber/asio/round_robin.hpp>
|
||||
#include <boost/fiber/asio/spawn.hpp>
|
||||
#include <boost/fiber/asio/use_future.hpp>
|
||||
#include <boost/fiber/asio/yield.hpp>
|
||||
//#include <boost/fiber/asio/round_robin.hpp>
|
||||
//#include <boost/fiber/asio/spawn.hpp>
|
||||
//#include <boost/fiber/asio/use_future.hpp>
|
||||
//#include <boost/fiber/asio/yield.hpp>
|
||||
#include <boost/fiber/attributes.hpp>
|
||||
#include <boost/fiber/barrier.hpp>
|
||||
#include <boost/fiber/bounded_queue.hpp>
|
||||
|
||||
@@ -51,7 +51,7 @@ class BOOST_FIBERS_DECL condition : private noncopyable
|
||||
{
|
||||
private:
|
||||
detail::spinlock splk_;
|
||||
std::deque< detail::fiber_base::ptr_t > waiting_;
|
||||
std::deque< detail::fiber_base * > waiting_;
|
||||
|
||||
public:
|
||||
condition();
|
||||
@@ -72,7 +72,7 @@ public:
|
||||
template< typename LockType >
|
||||
void wait( LockType & lt)
|
||||
{
|
||||
detail::fiber_base::ptr_t n( detail::scheduler::instance()->active() );
|
||||
detail::fiber_base * n( detail::scheduler::instance()->active() );
|
||||
try
|
||||
{
|
||||
if ( n)
|
||||
@@ -143,7 +143,7 @@ public:
|
||||
{
|
||||
cv_status status = cv_status::no_timeout;
|
||||
|
||||
detail::fiber_base::ptr_t n( detail::scheduler::instance()->active() );
|
||||
detail::fiber_base * n( detail::scheduler::instance()->active() );
|
||||
try
|
||||
{
|
||||
if ( n)
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/atomic.hpp>
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/intrusive_ptr.hpp>
|
||||
#include <boost/utility.hpp>
|
||||
|
||||
#include <boost/fiber/detail/config.hpp>
|
||||
@@ -34,28 +33,18 @@ namespace detail {
|
||||
|
||||
class BOOST_FIBERS_DECL fiber_base : private noncopyable
|
||||
{
|
||||
private:
|
||||
atomic< std::size_t > use_count_;
|
||||
// std::atomic< std::size_t > use_count_;
|
||||
// std::size_t use_count_;
|
||||
|
||||
protected:
|
||||
virtual void deallocate_object() = 0;
|
||||
|
||||
public:
|
||||
typedef intrusive_ptr< fiber_base > ptr_t;
|
||||
|
||||
class id
|
||||
{
|
||||
private:
|
||||
fiber_base::ptr_t impl_;
|
||||
fiber_base * impl_;
|
||||
|
||||
public:
|
||||
id() BOOST_NOEXCEPT :
|
||||
impl_()
|
||||
impl_( 0)
|
||||
{}
|
||||
|
||||
explicit id( fiber_base::ptr_t impl) BOOST_NOEXCEPT :
|
||||
explicit id( fiber_base * impl) BOOST_NOEXCEPT :
|
||||
impl_( impl)
|
||||
{}
|
||||
|
||||
@@ -94,8 +83,7 @@ public:
|
||||
{ return 0 == impl_; }
|
||||
};
|
||||
|
||||
fiber_base() :
|
||||
use_count_( 0)
|
||||
fiber_base()
|
||||
{}
|
||||
|
||||
virtual ~fiber_base() {};
|
||||
@@ -105,12 +93,6 @@ public:
|
||||
virtual void set_ready() BOOST_NOEXCEPT = 0;
|
||||
|
||||
virtual id get_id() const BOOST_NOEXCEPT = 0;
|
||||
|
||||
friend inline void intrusive_ptr_add_ref( fiber_base * p) BOOST_NOEXCEPT
|
||||
{ ++p->use_count_; }
|
||||
|
||||
friend inline void intrusive_ptr_release( fiber_base * p)
|
||||
{ if ( --p->use_count_ == 0) p->deallocate_object(); }
|
||||
};
|
||||
|
||||
}}}
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#ifndef BOOST_FIBERS_DETAIL_FIFO_H
|
||||
#define BOOST_FIBERS_DETAIL_FIFO_H
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstddef>
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
@@ -28,27 +29,25 @@ namespace detail {
|
||||
class fifo : private noncopyable
|
||||
{
|
||||
public:
|
||||
typedef worker_fiber::ptr_t ptr_t;
|
||||
|
||||
fifo() BOOST_NOEXCEPT :
|
||||
head_(),
|
||||
tail_()
|
||||
head_( 0),
|
||||
tail_( 0)
|
||||
{}
|
||||
|
||||
bool empty() const BOOST_NOEXCEPT
|
||||
{ return 0 == head_.get(); }
|
||||
{ return 0 == head_; }
|
||||
|
||||
std::size_t size() const BOOST_NOEXCEPT
|
||||
{
|
||||
std::size_t counter = 0;
|
||||
for ( ptr_t x = head_; x; x = x->next() )
|
||||
for ( worker_fiber * x = head_; x; x = x->next() )
|
||||
++counter;
|
||||
return counter;
|
||||
}
|
||||
|
||||
void push( ptr_t const& item) BOOST_NOEXCEPT
|
||||
void push( worker_fiber * item) BOOST_NOEXCEPT
|
||||
{
|
||||
BOOST_ASSERT( item);
|
||||
BOOST_ASSERT( 0 != item);
|
||||
|
||||
if ( empty() )
|
||||
{
|
||||
@@ -59,23 +58,23 @@ public:
|
||||
tail_ = tail_->next();
|
||||
}
|
||||
|
||||
ptr_t head() const BOOST_NOEXCEPT
|
||||
worker_fiber * head() const BOOST_NOEXCEPT
|
||||
{ return head_; }
|
||||
|
||||
void top( ptr_t const& item) BOOST_NOEXCEPT
|
||||
void top( worker_fiber * item) BOOST_NOEXCEPT
|
||||
{ head_ = item; }
|
||||
|
||||
ptr_t tail() const BOOST_NOEXCEPT
|
||||
worker_fiber * tail() const BOOST_NOEXCEPT
|
||||
{ return tail_; }
|
||||
|
||||
void tail( ptr_t const& item) BOOST_NOEXCEPT
|
||||
void tail( worker_fiber * item) BOOST_NOEXCEPT
|
||||
{ tail_ = item; }
|
||||
|
||||
ptr_t pop() BOOST_NOEXCEPT
|
||||
worker_fiber * pop() BOOST_NOEXCEPT
|
||||
{
|
||||
BOOST_ASSERT( ! empty() );
|
||||
|
||||
ptr_t item = head_;
|
||||
worker_fiber * item = head_;
|
||||
head_ = head_->next();
|
||||
if ( ! head_)
|
||||
tail_ = head_;
|
||||
@@ -84,16 +83,16 @@ public:
|
||||
return item;
|
||||
}
|
||||
|
||||
ptr_t find( ptr_t const& item) BOOST_NOEXCEPT
|
||||
worker_fiber * find( worker_fiber * item) BOOST_NOEXCEPT
|
||||
{
|
||||
BOOST_ASSERT( item);
|
||||
BOOST_ASSERT( 0 != item);
|
||||
|
||||
for ( ptr_t x = head_; x; x = x->next() )
|
||||
for ( worker_fiber * x = head_; x; x = x->next() )
|
||||
if ( item == x) return x;
|
||||
return ptr_t();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void erase( ptr_t const& item) BOOST_NOEXCEPT
|
||||
void erase( worker_fiber * item) BOOST_NOEXCEPT
|
||||
{
|
||||
BOOST_ASSERT( item);
|
||||
BOOST_ASSERT( ! empty() );
|
||||
@@ -103,9 +102,9 @@ public:
|
||||
pop();
|
||||
return;
|
||||
}
|
||||
for ( ptr_t x = head_; x; x = x->next() )
|
||||
for ( worker_fiber * x = head_; x; x = x->next() )
|
||||
{
|
||||
ptr_t nxt = x->next();
|
||||
worker_fiber * nxt = x->next();
|
||||
if ( ! nxt) return;
|
||||
if ( item == nxt)
|
||||
{
|
||||
@@ -120,9 +119,9 @@ public:
|
||||
template< typename Queue, typename Fn >
|
||||
void move_to( Queue & queue, Fn fn)
|
||||
{
|
||||
for ( ptr_t f = head_, prev = head_; f; )
|
||||
for ( worker_fiber * f = head_, * prev = head_; f; )
|
||||
{
|
||||
ptr_t nxt = f->next();
|
||||
worker_fiber * nxt = f->next();
|
||||
if ( fn( f) )
|
||||
{
|
||||
if ( f == head_)
|
||||
@@ -154,13 +153,13 @@ public:
|
||||
|
||||
void swap( fifo & other)
|
||||
{
|
||||
head_.swap( other.head_);
|
||||
tail_.swap( other.tail_);
|
||||
std::swap( head_, other.head_);
|
||||
std::swap( tail_, other.tail_);
|
||||
}
|
||||
|
||||
private:
|
||||
ptr_t head_;
|
||||
ptr_t tail_;
|
||||
worker_fiber * head_;
|
||||
worker_fiber * tail_;
|
||||
};
|
||||
|
||||
}}}
|
||||
|
||||
@@ -23,7 +23,8 @@ enum flag_t
|
||||
{
|
||||
flag_interruption_blocked = 1 << 0,
|
||||
flag_interruption_requested = 1 << 1,
|
||||
flag_thread_affinity = 1 << 2
|
||||
flag_thread_affinity = 1 << 2,
|
||||
flag_detached = 1 << 3
|
||||
};
|
||||
|
||||
}}}
|
||||
|
||||
@@ -23,10 +23,8 @@ namespace detail {
|
||||
class main_fiber : public fiber_base
|
||||
{
|
||||
public:
|
||||
static ptr_t make_pointer( main_fiber & n) {
|
||||
ptr_t p( & n);
|
||||
intrusive_ptr_add_ref( p.get() );
|
||||
return p;
|
||||
static main_fiber * make_pointer( main_fiber & n) {
|
||||
return & n;
|
||||
}
|
||||
|
||||
main_fiber() :
|
||||
@@ -40,9 +38,6 @@ public:
|
||||
void set_ready() BOOST_NOEXCEPT
|
||||
{ ready_ = true; }
|
||||
|
||||
void deallocate_object()
|
||||
{}
|
||||
|
||||
id get_id() const BOOST_NOEXCEPT
|
||||
{ return id( const_cast< main_fiber * >( this) ); }
|
||||
|
||||
|
||||
@@ -79,7 +79,7 @@ private:
|
||||
|
||||
public:
|
||||
template< typename F >
|
||||
static fiber_base::ptr_t extract( F const& f) BOOST_NOEXCEPT
|
||||
static fiber_base * extract( F const& f) BOOST_NOEXCEPT
|
||||
{ return f.impl_; }
|
||||
|
||||
static algorithm * instance()
|
||||
|
||||
@@ -46,9 +46,6 @@ namespace coro = boost::coroutines;
|
||||
|
||||
class BOOST_FIBERS_DECL worker_fiber : public fiber_base
|
||||
{
|
||||
public:
|
||||
typedef intrusive_ptr< worker_fiber > ptr_t;
|
||||
|
||||
private:
|
||||
enum state_t
|
||||
{
|
||||
@@ -83,20 +80,20 @@ private:
|
||||
> coro_t;
|
||||
|
||||
fss_data_t fss_data_;
|
||||
ptr_t nxt_;
|
||||
worker_fiber * nxt_;
|
||||
clock_type::time_point tp_;
|
||||
|
||||
void trampoline_( coro_t::yield_type &);
|
||||
|
||||
protected:
|
||||
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< ptr_t > waiting_;
|
||||
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_;
|
||||
|
||||
void release();
|
||||
|
||||
@@ -116,7 +113,13 @@ public:
|
||||
void priority( int prio) BOOST_NOEXCEPT
|
||||
{ priority_ = prio; }
|
||||
|
||||
bool join( ptr_t const&);
|
||||
bool join( worker_fiber *);
|
||||
|
||||
bool detached() const BOOST_NOEXCEPT
|
||||
{ return 0 != ( flags_.load() & flag_detached); }
|
||||
|
||||
void detach() BOOST_NOEXCEPT
|
||||
{ flags_ |= flag_detached; }
|
||||
|
||||
bool interruption_blocked() const BOOST_NOEXCEPT
|
||||
{ return 0 != ( flags_.load() & flag_interruption_blocked); }
|
||||
@@ -177,11 +180,9 @@ public:
|
||||
void * data,
|
||||
bool cleanup_existing);
|
||||
|
||||
bool has_exception() const BOOST_NOEXCEPT
|
||||
exception_ptr exception() const BOOST_NOEXCEPT
|
||||
{ return except_; }
|
||||
|
||||
void rethrow() const;
|
||||
|
||||
void resume( worker_fiber * f)
|
||||
{
|
||||
if ( 0 == f)
|
||||
@@ -213,14 +214,14 @@ public:
|
||||
BOOST_ASSERT( is_running() ); // set by the scheduler-algorithm
|
||||
}
|
||||
|
||||
ptr_t const& next() const
|
||||
worker_fiber * next() const
|
||||
{ return nxt_; }
|
||||
|
||||
void next( ptr_t const& nxt)
|
||||
void next( worker_fiber * nxt)
|
||||
{ nxt_ = nxt; }
|
||||
|
||||
void next_reset()
|
||||
{ nxt_.reset(); }
|
||||
{ nxt_ = 0; }
|
||||
|
||||
clock_type::time_point const& time_point() const
|
||||
{ return tp_; }
|
||||
@@ -230,6 +231,8 @@ public:
|
||||
|
||||
void time_point_reset()
|
||||
{ tp_ = (clock_type::time_point::max)(); }
|
||||
|
||||
virtual void deallocate() = 0;
|
||||
};
|
||||
|
||||
}}}
|
||||
|
||||
@@ -1,189 +0,0 @@
|
||||
|
||||
// Copyright Oliver Kowalke 2013.
|
||||
// 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_WORKER_FIBER_H
|
||||
#define BOOST_FIBERS_DETAIL_WORKER_FIBER_H
|
||||
|
||||
#include <cstddef>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/atomic.hpp>
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/cstdint.hpp>
|
||||
#include <boost/exception_ptr.hpp>
|
||||
#include <boost/intrusive_ptr.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>
|
||||
|
||||
#ifdef BOOST_HAS_ABI_HEADERS
|
||||
# include BOOST_ABI_PREFIX
|
||||
#endif
|
||||
|
||||
# if defined(BOOST_MSVC)
|
||||
# pragma warning(push)
|
||||
# pragma warning(disable:4251)
|
||||
# endif
|
||||
|
||||
namespace boost {
|
||||
namespace fibers {
|
||||
namespace detail {
|
||||
|
||||
class BOOST_FIBERS_DECL worker_fiber : public fiber_base
|
||||
{
|
||||
public:
|
||||
typedef intrusive_ptr< worker_fiber > ptr_t;
|
||||
|
||||
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;
|
||||
|
||||
fss_data_t fss_data_;
|
||||
ptr_t nxt_;
|
||||
clock_type::time_point tp_;
|
||||
|
||||
protected:
|
||||
atomic< state_t > state_;
|
||||
atomic< int > flags_;
|
||||
atomic< int > priority_;
|
||||
exception_ptr except_;
|
||||
spinlock splk_;
|
||||
std::vector< ptr_t > waiting_;
|
||||
|
||||
void release();
|
||||
|
||||
public:
|
||||
worker_fiber();
|
||||
|
||||
virtual ~worker_fiber();
|
||||
|
||||
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( ptr_t const&);
|
||||
|
||||
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;
|
||||
|
||||
void set_ready() BOOST_NOEXCEPT;
|
||||
|
||||
void set_running() BOOST_NOEXCEPT;
|
||||
|
||||
void set_waiting() BOOST_NOEXCEPT;
|
||||
|
||||
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);
|
||||
|
||||
bool has_exception() const BOOST_NOEXCEPT
|
||||
{ return except_; }
|
||||
|
||||
void rethrow() const;
|
||||
|
||||
virtual void resume() = 0;
|
||||
|
||||
virtual void suspend() = 0;
|
||||
|
||||
ptr_t const& next() const
|
||||
{ return nxt_; }
|
||||
|
||||
void next( ptr_t const& nxt)
|
||||
{ nxt_ = nxt; }
|
||||
|
||||
void next_reset()
|
||||
{ nxt_.reset(); }
|
||||
|
||||
clock_type::time_point const& time_point() const
|
||||
{ return tp_; }
|
||||
|
||||
void time_point( clock_type::time_point const& tp)
|
||||
{ tp_ = tp; }
|
||||
|
||||
void time_point_reset()
|
||||
{ tp_ = (clock_type::time_point::max)(); }
|
||||
};
|
||||
|
||||
}}}
|
||||
|
||||
# if defined(BOOST_MSVC)
|
||||
# pragma warning(pop)
|
||||
# endif
|
||||
|
||||
#ifdef BOOST_HAS_ABI_HEADERS
|
||||
# include BOOST_ABI_SUFFIX
|
||||
#endif
|
||||
|
||||
#endif // BOOST_FIBERS_DETAIL_WORKER_FIBER_H
|
||||
@@ -1,245 +0,0 @@
|
||||
|
||||
// Copyright Oliver Kowalke 2013.
|
||||
// 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_WORKER_FIBER_H
|
||||
#define BOOST_FIBERS_DETAIL_WORKER_FIBER_H
|
||||
|
||||
#include <cstddef>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/atomic.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/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>
|
||||
|
||||
#ifdef BOOST_HAS_ABI_HEADERS
|
||||
# include BOOST_ABI_PREFIX
|
||||
#endif
|
||||
|
||||
# if defined(BOOST_MSVC)
|
||||
# pragma warning(push)
|
||||
# pragma warning(disable:4251)
|
||||
# endif
|
||||
|
||||
namespace boost {
|
||||
namespace fibers {
|
||||
namespace detail {
|
||||
|
||||
namespace coro = boost::coroutines;
|
||||
|
||||
class BOOST_FIBERS_DECL worker_fiber : public fiber_base
|
||||
{
|
||||
public:
|
||||
typedef intrusive_ptr< worker_fiber > ptr_t;
|
||||
|
||||
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;
|
||||
typedef coro::symmetric_coroutine<
|
||||
void
|
||||
> coro_t;
|
||||
|
||||
fss_data_t fss_data_;
|
||||
ptr_t nxt_;
|
||||
clock_type::time_point tp_;
|
||||
|
||||
void trampoline_( coro_t::yield_type &);
|
||||
|
||||
protected:
|
||||
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< ptr_t > waiting_;
|
||||
|
||||
void release();
|
||||
|
||||
virtual void run() = 0;
|
||||
|
||||
public:
|
||||
worker_fiber( attributes const&);
|
||||
|
||||
virtual ~worker_fiber();
|
||||
|
||||
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( ptr_t const&);
|
||||
|
||||
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 set_ready() BOOST_NOEXCEPT
|
||||
{
|
||||
state_t previous = state_.exchange( READY);
|
||||
BOOST_ASSERT( WAITING == previous || RUNNING == previous || READY == previous);
|
||||
}
|
||||
|
||||
void set_running() BOOST_NOEXCEPT
|
||||
{
|
||||
state_t previous = state_.exchange( RUNNING);
|
||||
BOOST_ASSERT( READY == previous);
|
||||
}
|
||||
|
||||
void set_waiting() BOOST_NOEXCEPT
|
||||
{
|
||||
state_t previous = state_.exchange( WAITING);
|
||||
BOOST_ASSERT( RUNNING == 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);
|
||||
|
||||
bool has_exception() const BOOST_NOEXCEPT
|
||||
{ return except_; }
|
||||
|
||||
void rethrow() const;
|
||||
|
||||
void resume( worker_fiber * f)
|
||||
{
|
||||
if ( 0 == f)
|
||||
{
|
||||
BOOST_ASSERT( caller_);
|
||||
BOOST_ASSERT( is_running() ); // set by the scheduler-algorithm
|
||||
|
||||
// called from main-fiber
|
||||
caller_();
|
||||
}
|
||||
else
|
||||
{
|
||||
// caller from worker-fiber f
|
||||
BOOST_ASSERT( caller_);
|
||||
BOOST_ASSERT( is_running() ); // set by the scheduler-algorithm
|
||||
BOOST_ASSERT( f->callee_);
|
||||
|
||||
( * f->callee_)( caller_);
|
||||
}
|
||||
}
|
||||
|
||||
void suspend()
|
||||
{
|
||||
BOOST_ASSERT( callee_);
|
||||
BOOST_ASSERT( * callee_);
|
||||
|
||||
( * callee_)();
|
||||
|
||||
BOOST_ASSERT( is_running() ); // set by the scheduler-algorithm
|
||||
}
|
||||
|
||||
ptr_t const& next() const
|
||||
{ return nxt_; }
|
||||
|
||||
void next( ptr_t const& nxt)
|
||||
{ nxt_ = nxt; }
|
||||
|
||||
void next_reset()
|
||||
{ nxt_.reset(); }
|
||||
|
||||
clock_type::time_point const& time_point() const
|
||||
{ return tp_; }
|
||||
|
||||
void time_point( clock_type::time_point const& tp)
|
||||
{ tp_ = tp; }
|
||||
|
||||
void time_point_reset()
|
||||
{ tp_ = (clock_type::time_point::max)(); }
|
||||
};
|
||||
|
||||
}}}
|
||||
|
||||
# if defined(BOOST_MSVC)
|
||||
# pragma warning(pop)
|
||||
# endif
|
||||
|
||||
#ifdef BOOST_HAS_ABI_HEADERS
|
||||
# include BOOST_ABI_SUFFIX
|
||||
#endif
|
||||
|
||||
#endif // BOOST_FIBERS_DETAIL_WORKER_FIBER_H
|
||||
@@ -95,7 +95,7 @@ public:
|
||||
}
|
||||
#endif
|
||||
|
||||
void deallocate_object()
|
||||
void deallocate()
|
||||
{ destroy_( alloc_, this); }
|
||||
|
||||
private:
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#ifndef BOOST_FIBERS_FIBER_H
|
||||
#define BOOST_FIBERS_FIBER_H
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstddef>
|
||||
#include <exception>
|
||||
#include <memory>
|
||||
@@ -49,9 +50,8 @@ private:
|
||||
friend class detail::scheduler;
|
||||
|
||||
typedef detail::worker_fiber base_t;
|
||||
typedef base_t::ptr_t ptr_t;
|
||||
|
||||
ptr_t impl_;
|
||||
detail::worker_fiber * impl_;
|
||||
|
||||
BOOST_MOVABLE_BUT_NOT_COPYABLE( fiber);
|
||||
|
||||
@@ -61,10 +61,10 @@ public:
|
||||
typedef detail::worker_fiber::id id;
|
||||
|
||||
fiber() BOOST_NOEXCEPT :
|
||||
impl_()
|
||||
impl_( 0)
|
||||
{}
|
||||
|
||||
explicit fiber( ptr_t imp) BOOST_NOEXCEPT :
|
||||
explicit fiber( detail::worker_fiber * imp) BOOST_NOEXCEPT :
|
||||
impl_( imp)
|
||||
{}
|
||||
|
||||
@@ -75,15 +75,13 @@ public:
|
||||
explicit fiber( fiber_fn fn, attributes const& attr = attributes(),
|
||||
stack_allocator const& stack_alloc = stack_allocator(),
|
||||
std::allocator< fiber > const& alloc = std::allocator< fiber >() ) :
|
||||
impl_()
|
||||
impl_( 0)
|
||||
{
|
||||
typedef detail::worker_object<
|
||||
fiber_fn, std::allocator< fiber >
|
||||
> object_t;
|
||||
object_t::allocator_t a( alloc);
|
||||
impl_ = ptr_t(
|
||||
// placement new
|
||||
::new( a.allocate( 1) ) object_t( forward< fiber_fn >( fn), attr, a) );
|
||||
impl_ = ::new( a.allocate( 1) ) object_t( forward< fiber_fn >( fn), attr, a);
|
||||
start_fiber_();
|
||||
}
|
||||
|
||||
@@ -91,15 +89,13 @@ public:
|
||||
explicit fiber( fiber_fn fn, attributes const& attr,
|
||||
StackAllocator const& stack_alloc,
|
||||
std::allocator< fiber > const& alloc = std::allocator< fiber >() ) :
|
||||
impl_()
|
||||
impl_( 0)
|
||||
{
|
||||
typedef detail::worker_object<
|
||||
fiber_fn, std::allocator< fiber >
|
||||
> object_t;
|
||||
typename object_t::allocator_t a( alloc);
|
||||
impl_ = ptr_t(
|
||||
// placement new
|
||||
::new( a.allocate( 1) ) object_t( forward< fiber_fn >( fn), attr, a) );
|
||||
impl_ = ::new( a.allocate( 1) ) object_t( forward< fiber_fn >( fn), attr, a);
|
||||
start_fiber_();
|
||||
}
|
||||
|
||||
@@ -107,15 +103,13 @@ public:
|
||||
explicit fiber( fiber_fn fn, attributes const& attr,
|
||||
StackAllocator const& stack_alloc,
|
||||
Allocator const& alloc) :
|
||||
impl_()
|
||||
impl_( 0)
|
||||
{
|
||||
typedef detail::worker_object<
|
||||
fiber_fn, Allocator
|
||||
> object_t;
|
||||
typename object_t::allocator_t a( alloc);
|
||||
impl_ = ptr_t(
|
||||
// placement new
|
||||
::new( a.allocate( 1) ) object_t( forward< fiber_fn >( fn), attr, a) );
|
||||
impl_ = ::new( a.allocate( 1) ) object_t( forward< fiber_fn >( fn), attr, a);
|
||||
start_fiber_();
|
||||
}
|
||||
#endif
|
||||
@@ -123,15 +117,13 @@ public:
|
||||
explicit fiber( BOOST_RV_REF( Fn) fn, attributes const& attr = attributes(),
|
||||
stack_allocator const& stack_alloc = stack_allocator(),
|
||||
std::allocator< fiber > const& alloc = std::allocator< fiber >() ) :
|
||||
impl_()
|
||||
impl_( 0)
|
||||
{
|
||||
typedef detail::worker_object<
|
||||
Fn, std::allocator< fiber >
|
||||
> object_t;
|
||||
typename object_t::allocator_t a( alloc);
|
||||
impl_ = ptr_t(
|
||||
// placement new
|
||||
::new( a.allocate( 1) ) object_t( forward< Fn >( fn), attr, a) );
|
||||
impl_ = ::new( a.allocate( 1) ) object_t( forward< Fn >( fn), attr, a);
|
||||
start_fiber_();
|
||||
}
|
||||
|
||||
@@ -139,15 +131,13 @@ public:
|
||||
explicit fiber( BOOST_RV_REF( Fn) fn, attributes const& attr,
|
||||
StackAllocator const& stack_alloc,
|
||||
std::allocator< fiber > const& alloc = std::allocator< fiber >() ) :
|
||||
impl_()
|
||||
impl_( 0)
|
||||
{
|
||||
typedef detail::worker_object<
|
||||
Fn, std::allocator< fiber >
|
||||
> object_t;
|
||||
typename object_t::allocator_t a( alloc);
|
||||
impl_ = ptr_t(
|
||||
// placement new
|
||||
::new( a.allocate( 1) ) object_t( forward< Fn >( fn), attr, a) );
|
||||
impl_ = ::new( a.allocate( 1) ) object_t( forward< Fn >( fn), attr, a);
|
||||
start_fiber_();
|
||||
}
|
||||
|
||||
@@ -155,15 +145,13 @@ public:
|
||||
explicit fiber( BOOST_RV_REF( Fn) fn, attributes const& attr,
|
||||
StackAllocator const& stack_alloc,
|
||||
Allocator const& alloc) :
|
||||
impl_()
|
||||
impl_( 0)
|
||||
{
|
||||
typedef detail::worker_object<
|
||||
Fn, Allocator
|
||||
> object_t;
|
||||
typename object_t::allocator_t a( alloc);
|
||||
impl_ = ptr_t(
|
||||
// placement new
|
||||
::new( a.allocate( 1) ) object_t( forward< Fn >( fn), attr, a) );
|
||||
impl_ = ::new( a.allocate( 1) ) object_t( forward< Fn >( fn), attr, a);
|
||||
start_fiber_();
|
||||
}
|
||||
#else
|
||||
@@ -171,15 +159,13 @@ public:
|
||||
explicit fiber( Fn fn, attributes const& attr = attributes(),
|
||||
stack_allocator const& stack_alloc = stack_allocator(),
|
||||
std::allocator< fiber > const& alloc = std::allocator< fiber >() ) :
|
||||
impl_()
|
||||
impl_( 0)
|
||||
{
|
||||
typedef detail::worker_object<
|
||||
Fn, std::allocator< fiber >
|
||||
> object_t;
|
||||
typename object_t::allocator_t a( alloc);
|
||||
impl_ = ptr_t(
|
||||
// placement new
|
||||
::new( a.allocate( 1) ) object_t( fn, attr, a) );
|
||||
impl_ = ::new( a.allocate( 1) ) object_t( fn, attr, a);
|
||||
start_fiber_();
|
||||
}
|
||||
|
||||
@@ -187,15 +173,13 @@ public:
|
||||
explicit fiber( Fn fn, attributes const& attr,
|
||||
StackAllocator const& stack_alloc,
|
||||
std::allocator< fiber > const& alloc = std::allocator< fiber >() ) :
|
||||
impl_()
|
||||
impl_( 0)
|
||||
{
|
||||
typedef detail::worker_object<
|
||||
Fn, std::allocator< fiber >
|
||||
> object_t;
|
||||
typename object_t::allocator_t a( alloc);
|
||||
impl_ = ptr_t(
|
||||
// placement new
|
||||
::new( a.allocate( 1) ) object_t( fn, attr, a) );
|
||||
impl_ = ::new( a.allocate( 1) ) object_t( fn, attr, a);
|
||||
start_fiber_();
|
||||
}
|
||||
|
||||
@@ -203,15 +187,13 @@ public:
|
||||
explicit fiber( Fn fn, attributes const& attr,
|
||||
StackAllocator const& stack_alloc,
|
||||
Allocator const& alloc) :
|
||||
impl_()
|
||||
impl_( 0)
|
||||
{
|
||||
typedef detail::worker_object<
|
||||
Fn, Allocator
|
||||
> object_t;
|
||||
typename object_t::allocator_t a( alloc);
|
||||
impl_ = ptr_t(
|
||||
// placement new
|
||||
::new( a.allocate( 1) ) object_t( fn, attr, a) );
|
||||
impl_ = ::new( a.allocate( 1) ) object_t( fn, attr, a);
|
||||
start_fiber_();
|
||||
}
|
||||
|
||||
@@ -219,15 +201,13 @@ public:
|
||||
explicit fiber( BOOST_RV_REF( Fn) fn, attributes const& attr = attributes(),
|
||||
stack_allocator const& stack_alloc = stack_allocator(),
|
||||
std::allocator< fiber > const& alloc = std::allocator< fiber >() ) :
|
||||
impl_()
|
||||
impl_( 0)
|
||||
{
|
||||
typedef detail::worker_object<
|
||||
Fn, std::allocator< fiber >
|
||||
> object_t;
|
||||
typename object_t::allocator_t a( alloc);
|
||||
impl_ = ptr_t(
|
||||
// placement new
|
||||
::new( a.allocate( 1) ) object_t( fn, attr, a) );
|
||||
impl_ = ::new( a.allocate( 1) ) object_t( fn, attr, a);
|
||||
start_fiber_();
|
||||
}
|
||||
|
||||
@@ -235,15 +215,13 @@ public:
|
||||
explicit fiber( BOOST_RV_REF( Fn) fn, attributes const& attr,
|
||||
StackAllocator const& stack_alloc,
|
||||
std::allocator< fiber > const& alloc = std::allocator< fiber >() ) :
|
||||
impl_()
|
||||
impl_( 0)
|
||||
{
|
||||
typedef detail::worker_object<
|
||||
Fn, std::allocator< fiber >
|
||||
> object_t;
|
||||
typename object_t::allocator_t a( alloc);
|
||||
impl_ = ptr_t(
|
||||
// placement new
|
||||
::new( a.allocate( 1) ) object_t( fn, attr, a) );
|
||||
impl_ = ::new( a.allocate( 1) ) object_t( fn, attr, a);
|
||||
start_fiber_();
|
||||
}
|
||||
|
||||
@@ -251,24 +229,29 @@ public:
|
||||
explicit fiber( BOOST_RV_REF( Fn) fn, attributes const& attr,
|
||||
StackAllocator const& stack_alloc,
|
||||
Allocator const& alloc) :
|
||||
impl_()
|
||||
impl_( 0)
|
||||
{
|
||||
typedef detail::worker_object<
|
||||
Fn, Allocator
|
||||
> object_t;
|
||||
typename object_t::allocator_t a( alloc);
|
||||
impl_ = ptr_t(
|
||||
// placement new
|
||||
::new( a.allocate( 1) ) object_t( fn, attr, a) );
|
||||
impl_ = ::new( a.allocate( 1) ) object_t( fn, attr, a);
|
||||
start_fiber_();
|
||||
}
|
||||
#endif
|
||||
|
||||
~fiber()
|
||||
{ if ( joinable() ) std::terminate(); }
|
||||
{
|
||||
if ( joinable() ) std::terminate();
|
||||
if ( 0 != impl_)
|
||||
{
|
||||
impl_->deallocate();
|
||||
impl_ = 0;
|
||||
}
|
||||
}
|
||||
|
||||
fiber( BOOST_RV_REF( fiber) other) BOOST_NOEXCEPT :
|
||||
impl_()
|
||||
impl_( 0)
|
||||
{ swap( other); }
|
||||
|
||||
fiber & operator=( BOOST_RV_REF( fiber) other) BOOST_NOEXCEPT
|
||||
@@ -285,10 +268,10 @@ public:
|
||||
{ return ! impl_ || impl_->is_terminated(); }
|
||||
|
||||
void swap( fiber & other) BOOST_NOEXCEPT
|
||||
{ impl_.swap( other.impl_); }
|
||||
{ std::swap( impl_, other.impl_); }
|
||||
|
||||
bool joinable() const BOOST_NOEXCEPT
|
||||
{ return 0 != impl_.get() /* && ! impl_->is_terminated() */; }
|
||||
{ return 0 != impl_ /* && ! impl_->is_terminated() */; }
|
||||
|
||||
id get_id() const BOOST_NOEXCEPT
|
||||
{ return impl_ ? impl_->get_id() : id(); }
|
||||
|
||||
@@ -39,12 +39,10 @@ private:
|
||||
UNLOCKED
|
||||
};
|
||||
|
||||
detail::spinlock splk_;
|
||||
state_t state_;
|
||||
detail::worker_fiber::id owner_;
|
||||
std::deque<
|
||||
detail::fiber_base::ptr_t
|
||||
> waiting_;
|
||||
detail::spinlock splk_;
|
||||
state_t state_;
|
||||
detail::worker_fiber::id owner_;
|
||||
std::deque< detail::fiber_base * > waiting_;
|
||||
|
||||
public:
|
||||
typedef unique_lock< mutex > scoped_lock;
|
||||
|
||||
@@ -25,7 +25,7 @@ namespace this_fiber {
|
||||
inline
|
||||
fibers::fiber::id get_id() BOOST_NOEXCEPT
|
||||
{
|
||||
return fibers::detail::scheduler::instance()->active()
|
||||
return 0 != fibers::detail::scheduler::instance()->active()
|
||||
? fibers::detail::scheduler::instance()->active()->get_id()
|
||||
: fibers::fiber::id();
|
||||
}
|
||||
@@ -33,7 +33,7 @@ fibers::fiber::id get_id() BOOST_NOEXCEPT
|
||||
inline
|
||||
void yield()
|
||||
{
|
||||
if ( fibers::detail::scheduler::instance()->active() )
|
||||
if ( 0 != fibers::detail::scheduler::instance()->active() )
|
||||
fibers::detail::scheduler::instance()->yield();
|
||||
else
|
||||
fibers::detail::scheduler::instance()->run();
|
||||
@@ -42,7 +42,7 @@ void yield()
|
||||
inline
|
||||
void sleep_until( fibers::clock_type::time_point const& sleep_time)
|
||||
{
|
||||
if ( fibers::detail::scheduler::instance()->active() )
|
||||
if ( 0 != fibers::detail::scheduler::instance()->active() )
|
||||
{
|
||||
fibers::detail::spinlock splk;
|
||||
unique_lock< fibers::detail::spinlock > lk( splk);
|
||||
@@ -65,7 +65,7 @@ void sleep_for( chrono::duration< Rep, Period > const& timeout_duration)
|
||||
inline
|
||||
bool thread_affinity() BOOST_NOEXCEPT
|
||||
{
|
||||
return fibers::detail::scheduler::instance()->active()
|
||||
return 0 != fibers::detail::scheduler::instance()->active()
|
||||
? fibers::detail::scheduler::instance()->active()->thread_affinity()
|
||||
: true;
|
||||
}
|
||||
@@ -73,7 +73,7 @@ bool thread_affinity() BOOST_NOEXCEPT
|
||||
inline
|
||||
void thread_affinity( bool req) BOOST_NOEXCEPT
|
||||
{
|
||||
if ( fibers::detail::scheduler::instance()->active() )
|
||||
if ( 0 != fibers::detail::scheduler::instance()->active() )
|
||||
fibers::detail::scheduler::instance()->active()->thread_affinity( req);
|
||||
}
|
||||
|
||||
|
||||
@@ -42,13 +42,11 @@ private:
|
||||
UNLOCKED
|
||||
};
|
||||
|
||||
detail::spinlock splk_;
|
||||
state_t state_;
|
||||
detail::worker_fiber::id owner_;
|
||||
std::size_t count_;
|
||||
std::deque<
|
||||
detail::fiber_base::ptr_t
|
||||
> waiting_;
|
||||
detail::spinlock splk_;
|
||||
state_t state_;
|
||||
detail::worker_fiber::id owner_;
|
||||
std::size_t count_;
|
||||
std::deque< detail::fiber_base * > waiting_;
|
||||
|
||||
public:
|
||||
typedef unique_lock< recursive_mutex > scoped_lock;
|
||||
|
||||
@@ -42,13 +42,11 @@ private:
|
||||
UNLOCKED
|
||||
};
|
||||
|
||||
detail::spinlock splk_;
|
||||
state_t state_;
|
||||
detail::worker_fiber::id owner_;
|
||||
std::size_t count_;
|
||||
std::deque<
|
||||
detail::fiber_base::ptr_t
|
||||
> waiting_;
|
||||
detail::spinlock splk_;
|
||||
state_t state_;
|
||||
detail::worker_fiber::id owner_;
|
||||
std::size_t count_;
|
||||
std::deque< detail::fiber_base * > waiting_;
|
||||
|
||||
public:
|
||||
typedef unique_lock< recursive_timed_mutex > scoped_lock;
|
||||
|
||||
@@ -46,27 +46,27 @@ private:
|
||||
typedef detail::fifo wqueue_t;
|
||||
typedef detail::fifo rqueue_t;
|
||||
|
||||
detail::worker_fiber::ptr_t active_fiber_;
|
||||
detail::worker_fiber * active_fiber_;
|
||||
wqueue_t wqueue_;
|
||||
rqueue_t rqueue_;
|
||||
detail::main_fiber mn_;
|
||||
|
||||
detail::worker_fiber::ptr_t pick_next_();
|
||||
detail::worker_fiber * pick_next_();
|
||||
|
||||
void resume_( detail::worker_fiber::ptr_t const&);
|
||||
void resume_( detail::worker_fiber *);
|
||||
|
||||
public:
|
||||
round_robin() BOOST_NOEXCEPT;
|
||||
|
||||
~round_robin() BOOST_NOEXCEPT;
|
||||
|
||||
void spawn( detail::worker_fiber::ptr_t const&);
|
||||
void spawn( detail::worker_fiber *);
|
||||
|
||||
void priority( detail::worker_fiber::ptr_t const&, int) BOOST_NOEXCEPT;
|
||||
void priority( detail::worker_fiber *, int) BOOST_NOEXCEPT;
|
||||
|
||||
void join( detail::worker_fiber::ptr_t const&);
|
||||
void join( detail::worker_fiber *);
|
||||
|
||||
detail::worker_fiber::ptr_t active() BOOST_NOEXCEPT
|
||||
detail::worker_fiber * active() BOOST_NOEXCEPT
|
||||
{ return active_fiber_; }
|
||||
|
||||
void run();
|
||||
@@ -77,8 +77,11 @@ public:
|
||||
|
||||
void yield();
|
||||
|
||||
detail::fiber_base::ptr_t get_main_fiber()
|
||||
{ return detail::fiber_base::ptr_t( new detail::main_fiber() ); }
|
||||
// FIXME: must be removed
|
||||
// allocate main_fiber on stack of mutext, condition, etc.
|
||||
// and pass address of main_fiber to wait-container
|
||||
detail::fiber_base * get_main_fiber()
|
||||
{ return new detail::main_fiber(); }
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
@@ -39,12 +39,10 @@ private:
|
||||
UNLOCKED
|
||||
};
|
||||
|
||||
detail::spinlock splk_;
|
||||
state_t state_;
|
||||
detail::worker_fiber::id owner_;
|
||||
std::deque<
|
||||
detail::fiber_base::ptr_t
|
||||
> waiting_;
|
||||
detail::spinlock splk_;
|
||||
state_t state_;
|
||||
detail::worker_fiber::id owner_;
|
||||
std::deque< detail::fiber_base * > waiting_;
|
||||
|
||||
public:
|
||||
typedef unique_lock< timed_mutex > scoped_lock;
|
||||
|
||||
@@ -28,12 +28,12 @@ condition::~condition()
|
||||
void
|
||||
condition::notify_one()
|
||||
{
|
||||
detail::fiber_base::ptr_t n;
|
||||
detail::fiber_base * n = 0;
|
||||
|
||||
unique_lock< detail::spinlock > lk( splk_);
|
||||
// get one waiting fiber
|
||||
if ( ! waiting_.empty() ) {
|
||||
n.swap( waiting_.front() );
|
||||
n = waiting_.front();
|
||||
waiting_.pop_front();
|
||||
}
|
||||
lk.unlock();
|
||||
@@ -45,7 +45,7 @@ condition::notify_one()
|
||||
void
|
||||
condition::notify_all()
|
||||
{
|
||||
std::deque< detail::fiber_base::ptr_t > waiting;
|
||||
std::deque< detail::fiber_base * > waiting;
|
||||
|
||||
unique_lock< detail::spinlock > lk( splk_);
|
||||
// get all waiting fibers
|
||||
@@ -55,7 +55,7 @@ condition::notify_all()
|
||||
// notify all waiting fibers
|
||||
while ( ! waiting.empty() )
|
||||
{
|
||||
detail::fiber_base::ptr_t n( waiting.front() );
|
||||
detail::fiber_base * n( waiting.front() );
|
||||
waiting.pop_front();
|
||||
BOOST_ASSERT( n);
|
||||
n->set_ready();
|
||||
|
||||
@@ -22,7 +22,7 @@ spinlock::spinlock() :
|
||||
void
|
||||
spinlock::lock()
|
||||
{
|
||||
bool is_fiber = 0 != scheduler::instance()->active().get();
|
||||
bool is_fiber = 0 != scheduler::instance()->active();
|
||||
for (;;)
|
||||
{
|
||||
// access to CPU's cache
|
||||
|
||||
@@ -60,7 +60,7 @@ worker_fiber::trampoline_( coro_t::yield_type & yield)
|
||||
worker_fiber::worker_fiber( attributes const& attrs) :
|
||||
fiber_base(),
|
||||
fss_data_(),
|
||||
nxt_(),
|
||||
nxt_( 0),
|
||||
tp_( (clock_type::time_point::max)() ),
|
||||
callee_( 0),
|
||||
caller_(
|
||||
@@ -84,7 +84,7 @@ worker_fiber::release()
|
||||
{
|
||||
BOOST_ASSERT( is_terminated() );
|
||||
|
||||
std::vector< ptr_t > waiting;
|
||||
std::vector< worker_fiber * > waiting;
|
||||
|
||||
// get all waiting fibers
|
||||
splk_.lock();
|
||||
@@ -92,7 +92,7 @@ worker_fiber::release()
|
||||
splk_.unlock();
|
||||
|
||||
// notify all waiting fibers
|
||||
BOOST_FOREACH( worker_fiber::ptr_t p, waiting)
|
||||
BOOST_FOREACH( worker_fiber * p, waiting)
|
||||
{ p->set_ready(); }
|
||||
|
||||
// release all fiber-specific-pointers
|
||||
@@ -101,7 +101,7 @@ worker_fiber::release()
|
||||
}
|
||||
|
||||
bool
|
||||
worker_fiber::join( ptr_t const& p)
|
||||
worker_fiber::join( worker_fiber * p)
|
||||
{
|
||||
unique_lock< spinlock > lk( splk_);
|
||||
if ( is_terminated() ) return false;
|
||||
@@ -174,14 +174,6 @@ worker_fiber::set_fss_data(
|
||||
fss_data( data, cleanup_fn) ) );
|
||||
}
|
||||
|
||||
void
|
||||
worker_fiber::rethrow() const
|
||||
{
|
||||
BOOST_ASSERT( has_exception() );
|
||||
|
||||
rethrow_exception( except_);
|
||||
}
|
||||
|
||||
}}}
|
||||
|
||||
#ifdef BOOST_HAS_ABI_HEADERS
|
||||
|
||||
@@ -77,11 +77,13 @@ fiber::join()
|
||||
|
||||
detail::scheduler::instance()->join( impl_);
|
||||
|
||||
ptr_t tmp;
|
||||
tmp.swap( impl_);
|
||||
detail::worker_fiber * tmp = 0;
|
||||
std::swap( tmp, impl_);
|
||||
// check if joined fiber was interrupted
|
||||
if ( tmp->has_exception() )
|
||||
tmp->rethrow();
|
||||
exception_ptr except( tmp->exception() );
|
||||
tmp->deallocate();
|
||||
if ( except)
|
||||
rethrow_exception( except);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -96,7 +98,8 @@ fiber::detach() BOOST_NOEXCEPT
|
||||
system::errc::invalid_argument, "boost fiber: fiber not joinable") );
|
||||
}
|
||||
|
||||
impl_.reset();
|
||||
impl_->detach();
|
||||
impl_ = 0;
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -50,14 +50,14 @@ restore_interruption::~restore_interruption() BOOST_NOEXCEPT
|
||||
|
||||
bool interruption_enabled() BOOST_NOEXCEPT
|
||||
{
|
||||
fibers::detail::worker_fiber::ptr_t f( fibers::detail::scheduler::instance()->active() );
|
||||
return f && ! f->interruption_blocked();
|
||||
fibers::detail::worker_fiber * f = fibers::detail::scheduler::instance()->active();
|
||||
return 0 != f && ! f->interruption_blocked();
|
||||
}
|
||||
|
||||
bool interruption_requested() BOOST_NOEXCEPT
|
||||
{
|
||||
fibers::detail::worker_fiber::ptr_t f( fibers::detail::scheduler::instance()->active() );
|
||||
if ( ! f) return false;
|
||||
fibers::detail::worker_fiber * f = fibers::detail::scheduler::instance()->active();
|
||||
if ( 0 == f) return false;
|
||||
return f->interruption_requested();
|
||||
}
|
||||
|
||||
|
||||
@@ -37,8 +37,8 @@ mutex::~mutex()
|
||||
void
|
||||
mutex::lock()
|
||||
{
|
||||
detail::fiber_base::ptr_t n( detail::scheduler::instance()->active() );
|
||||
if ( n)
|
||||
detail::fiber_base * n( detail::scheduler::instance()->active() );
|
||||
if ( 0 != n)
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
@@ -118,10 +118,10 @@ mutex::unlock()
|
||||
BOOST_ASSERT( this_fiber::get_id() == owner_);
|
||||
|
||||
unique_lock< detail::spinlock > lk( splk_);
|
||||
detail::fiber_base::ptr_t n;
|
||||
detail::fiber_base * n = 0;
|
||||
if ( ! waiting_.empty() )
|
||||
{
|
||||
n.swap( waiting_.front() );
|
||||
n = waiting_.front();
|
||||
waiting_.pop_front();
|
||||
}
|
||||
owner_ = detail::worker_fiber::id();
|
||||
|
||||
@@ -39,8 +39,8 @@ recursive_mutex::~recursive_mutex()
|
||||
void
|
||||
recursive_mutex::lock()
|
||||
{
|
||||
detail::fiber_base::ptr_t n( detail::scheduler::instance()->active() );
|
||||
if ( n)
|
||||
detail::fiber_base * n( detail::scheduler::instance()->active() );
|
||||
if ( 0 != n)
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
@@ -138,13 +138,13 @@ recursive_mutex::unlock()
|
||||
BOOST_ASSERT( this_fiber::get_id() == owner_);
|
||||
|
||||
unique_lock< detail::spinlock > lk( splk_);
|
||||
detail::fiber_base::ptr_t n;
|
||||
detail::fiber_base * n = 0;
|
||||
|
||||
if ( 0 == --count_)
|
||||
{
|
||||
if ( ! waiting_.empty() )
|
||||
{
|
||||
n.swap( waiting_.front() );
|
||||
n = waiting_.front();
|
||||
waiting_.pop_front();
|
||||
}
|
||||
owner_ = detail::worker_fiber::id();
|
||||
|
||||
@@ -39,8 +39,8 @@ recursive_timed_mutex::~recursive_timed_mutex()
|
||||
void
|
||||
recursive_timed_mutex::lock()
|
||||
{
|
||||
detail::fiber_base::ptr_t n( detail::scheduler::instance()->active() );
|
||||
if ( n)
|
||||
detail::fiber_base * n( detail::scheduler::instance()->active() );
|
||||
if ( 0 != n)
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
@@ -134,7 +134,7 @@ recursive_timed_mutex::try_lock()
|
||||
bool
|
||||
recursive_timed_mutex::try_lock_until( clock_type::time_point const& timeout_time)
|
||||
{
|
||||
detail::fiber_base::ptr_t n( detail::scheduler::instance()->active() );
|
||||
detail::fiber_base * n( detail::scheduler::instance()->active() );
|
||||
if ( n)
|
||||
{
|
||||
for (;;)
|
||||
@@ -231,13 +231,13 @@ recursive_timed_mutex::unlock()
|
||||
BOOST_ASSERT( this_fiber::get_id() == owner_);
|
||||
|
||||
unique_lock< detail::spinlock > lk( splk_);
|
||||
detail::fiber_base::ptr_t n;
|
||||
detail::fiber_base * n = 0;
|
||||
|
||||
if ( 0 == --count_)
|
||||
{
|
||||
if ( ! waiting_.empty() )
|
||||
{
|
||||
n.swap( waiting_.front() );
|
||||
n = waiting_.front();
|
||||
waiting_.pop_front();
|
||||
}
|
||||
owner_ = detail::worker_fiber::id();
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
namespace boost {
|
||||
namespace fibers {
|
||||
|
||||
bool fetch_ready( detail::worker_fiber::ptr_t & f)
|
||||
bool fetch_ready( detail::worker_fiber * f)
|
||||
{
|
||||
BOOST_ASSERT( ! f->is_running() );
|
||||
BOOST_ASSERT( ! f->is_terminated() );
|
||||
@@ -40,23 +40,23 @@ bool fetch_ready( detail::worker_fiber::ptr_t & f)
|
||||
return f->is_ready();
|
||||
}
|
||||
|
||||
detail::worker_fiber::ptr_t
|
||||
detail::worker_fiber *
|
||||
round_robin::pick_next_()
|
||||
{
|
||||
detail::worker_fiber::ptr_t victim;
|
||||
detail::worker_fiber * victim = 0;
|
||||
if ( ! rqueue_.empty() )
|
||||
victim = rqueue_.pop();
|
||||
return victim;
|
||||
}
|
||||
|
||||
void
|
||||
round_robin::resume_( detail::worker_fiber::ptr_t const& f)
|
||||
round_robin::resume_( detail::worker_fiber * f)
|
||||
{
|
||||
BOOST_ASSERT( f);
|
||||
BOOST_ASSERT( f->is_ready() );
|
||||
|
||||
// store active fiber in local var
|
||||
detail::worker_fiber::ptr_t tmp = active_fiber_;
|
||||
detail::worker_fiber * tmp( active_fiber_);
|
||||
// assign new fiber to active fiber
|
||||
active_fiber_ = f;
|
||||
// set active fiber to state_running
|
||||
@@ -65,16 +65,19 @@ round_robin::resume_( detail::worker_fiber::ptr_t const& f)
|
||||
// this might happend if fiber calls yield() and no
|
||||
// other fiber is in the ready-queue
|
||||
if ( tmp != active_fiber_)
|
||||
{
|
||||
// resume active-fiber == start or yield to
|
||||
active_fiber_->resume( tmp.get() );
|
||||
active_fiber_->resume( tmp);
|
||||
if ( active_fiber_->detached() && active_fiber_->is_terminated() )
|
||||
active_fiber_->deallocate();
|
||||
}
|
||||
|
||||
//BOOST_ASSERT( f == active_fiber_);
|
||||
// reset active fiber to previous
|
||||
active_fiber_ = tmp;
|
||||
}
|
||||
|
||||
round_robin::round_robin() BOOST_NOEXCEPT :
|
||||
active_fiber_(),
|
||||
active_fiber_( 0),
|
||||
wqueue_(),
|
||||
rqueue_(),
|
||||
mn_()
|
||||
@@ -92,7 +95,7 @@ round_robin::~round_robin() BOOST_NOEXCEPT
|
||||
}
|
||||
|
||||
void
|
||||
round_robin::spawn( detail::worker_fiber::ptr_t const& f)
|
||||
round_robin::spawn( detail::worker_fiber * f)
|
||||
{ rqueue_.push( f); }
|
||||
|
||||
void
|
||||
@@ -106,7 +109,7 @@ round_robin::run()
|
||||
|
||||
// pop new fiber from ready-queue which is not complete
|
||||
// (example: fiber in ready-queue could be canceled by active-fiber)
|
||||
detail::worker_fiber::ptr_t f = pick_next_();
|
||||
detail::worker_fiber * f( pick_next_() );
|
||||
if ( f)
|
||||
{
|
||||
BOOST_ASSERT_MSG( f->is_ready(), "fiber with invalid state in ready-queue");
|
||||
@@ -163,7 +166,7 @@ round_robin::yield()
|
||||
}
|
||||
|
||||
void
|
||||
round_robin::join( detail::worker_fiber::ptr_t const& f)
|
||||
round_robin::join( detail::worker_fiber * f)
|
||||
{
|
||||
BOOST_ASSERT( f);
|
||||
BOOST_ASSERT( f != active_fiber_);
|
||||
@@ -195,7 +198,7 @@ round_robin::join( detail::worker_fiber::ptr_t const& f)
|
||||
}
|
||||
|
||||
void
|
||||
round_robin::priority( detail::worker_fiber::ptr_t const& f, int prio) BOOST_NOEXCEPT
|
||||
round_robin::priority( detail::worker_fiber * f, int prio) BOOST_NOEXCEPT
|
||||
{
|
||||
BOOST_ASSERT( f);
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@ timed_mutex::~timed_mutex()
|
||||
void
|
||||
timed_mutex::lock()
|
||||
{
|
||||
detail::fiber_base::ptr_t n( detail::scheduler::instance()->active() );
|
||||
detail::fiber_base * n( detail::scheduler::instance()->active() );
|
||||
if ( n)
|
||||
{
|
||||
for (;;)
|
||||
@@ -114,7 +114,7 @@ timed_mutex::try_lock()
|
||||
bool
|
||||
timed_mutex::try_lock_until( clock_type::time_point const& timeout_time)
|
||||
{
|
||||
detail::fiber_base::ptr_t n( detail::scheduler::instance()->active() );
|
||||
detail::fiber_base * n( detail::scheduler::instance()->active() );
|
||||
if ( n)
|
||||
{
|
||||
for (;;)
|
||||
@@ -199,11 +199,11 @@ timed_mutex::unlock()
|
||||
BOOST_ASSERT( this_fiber::get_id() == owner_);
|
||||
|
||||
unique_lock< detail::spinlock > lk( splk_);
|
||||
detail::fiber_base::ptr_t n;
|
||||
detail::fiber_base * n = 0;
|
||||
|
||||
if ( ! waiting_.empty() )
|
||||
{
|
||||
n.swap( waiting_.front() );
|
||||
n = waiting_.front();
|
||||
waiting_.pop_front();
|
||||
}
|
||||
owner_ = detail::worker_fiber::id();
|
||||
|
||||
Reference in New Issue
Block a user