mirror of
https://github.com/boostorg/fiber.git
synced 2026-02-22 03:12:28 +00:00
Define sched_algorithm methods on fiber_base*, not worker_fiber*.
Some reviewers disliked that to build a custom sched_algorithm subclass, you must necessarily manipulate pointers to classes in the boost::fibers::detail namespace. Redefine all such methods to use fiber_base* rather than detail::worker_fiber*. Hoist fiber_base* into boost::fibers namespace. We considered an opaque typedef rather than fiber_base*, but in fact a sched_algorithm subclass may need is_ready(). Moreover, a sched_algorithm subclass may well want to use an intrusive linked list to queue fibers. Hoist worker_fiber::nxt_ pointer into fiber_base, and remove worker_fiber::next() and next_reset() methods. This allows recasting detail::fifo in terms of fiber_base*, therefore round_robin can be stated almost entirely in terms of fiber_base* rather than worker_fiber*. Recast fiber constructor taking worker_fiber* to take fiber_base* instead. This constructor is used solely for fiber migration; with relevant functions now returning fiber_base*, we think we no longer need fiber(worker_fiber*).
This commit is contained in:
@@ -13,17 +13,17 @@
|
||||
#endif
|
||||
|
||||
void
|
||||
workstealing_round_robin::awakened( boost::fibers::detail::worker_fiber * f)
|
||||
workstealing_round_robin::awakened( boost::fibers::fiber_base * f)
|
||||
{
|
||||
boost::mutex::scoped_lock lk( mtx_);
|
||||
rqueue_.push_back( f);
|
||||
}
|
||||
|
||||
boost::fibers::detail::worker_fiber *
|
||||
boost::fibers::fiber_base *
|
||||
workstealing_round_robin::pick_next()
|
||||
{
|
||||
boost::mutex::scoped_lock lk( mtx_);
|
||||
boost::fibers::detail::worker_fiber * f = 0;
|
||||
boost::fibers::fiber_base * f = 0;
|
||||
if ( ! rqueue_.empty() )
|
||||
{
|
||||
f = rqueue_.front();
|
||||
@@ -33,20 +33,20 @@ workstealing_round_robin::pick_next()
|
||||
}
|
||||
|
||||
void
|
||||
workstealing_round_robin::priority( boost::fibers::detail::worker_fiber * f, int prio) BOOST_NOEXCEPT
|
||||
workstealing_round_robin::priority( boost::fibers::fiber_base * f, int prio) BOOST_NOEXCEPT
|
||||
{
|
||||
BOOST_ASSERT( f);
|
||||
|
||||
// set only priority to fiber
|
||||
// round-robin does not respect priorities
|
||||
f->priority( prio);
|
||||
static_cast<boost::fibers::detail::worker_fiber*>(f)->priority( prio);
|
||||
}
|
||||
|
||||
boost::fibers::fiber
|
||||
workstealing_round_robin::steal() BOOST_NOEXCEPT
|
||||
{
|
||||
boost::mutex::scoped_lock lk( mtx_);
|
||||
boost::fibers::detail::worker_fiber * f = 0;
|
||||
boost::fibers::fiber_base * f = 0;
|
||||
if ( ! rqueue_.empty() )
|
||||
{
|
||||
f = rqueue_.back();
|
||||
|
||||
@@ -29,17 +29,17 @@
|
||||
class workstealing_round_robin : public boost::fibers::sched_algorithm
|
||||
{
|
||||
private:
|
||||
typedef std::deque< boost::fibers::detail::worker_fiber * > rqueue_t;
|
||||
typedef std::deque< boost::fibers::fiber_base * > rqueue_t;
|
||||
|
||||
boost::mutex mtx_;
|
||||
rqueue_t rqueue_;
|
||||
|
||||
public:
|
||||
virtual void awakened( boost::fibers::detail::worker_fiber *);
|
||||
virtual void awakened( boost::fibers::fiber_base *);
|
||||
|
||||
virtual boost::fibers::detail::worker_fiber * pick_next();
|
||||
virtual boost::fibers::fiber_base * pick_next();
|
||||
|
||||
virtual void priority( boost::fibers::detail::worker_fiber *, int) BOOST_NOEXCEPT;
|
||||
virtual void priority( boost::fibers::fiber_base *, int) BOOST_NOEXCEPT;
|
||||
|
||||
boost::fibers::fiber steal();
|
||||
};
|
||||
|
||||
@@ -25,17 +25,20 @@
|
||||
namespace boost {
|
||||
namespace fibers {
|
||||
|
||||
// hoist fiber_base out of detail namespace into boost::fibers
|
||||
typedef detail::fiber_base fiber_base;
|
||||
|
||||
struct sched_algorithm
|
||||
{
|
||||
virtual ~sched_algorithm() {}
|
||||
|
||||
virtual void awakened( detail::worker_fiber *) = 0;
|
||||
virtual void awakened( fiber_base *) = 0;
|
||||
|
||||
virtual detail::worker_fiber * pick_next() = 0;
|
||||
virtual fiber_base * pick_next() = 0;
|
||||
|
||||
virtual void priority( detail::worker_fiber *, int) BOOST_NOEXCEPT = 0;
|
||||
virtual void priority( fiber_base *, int) BOOST_NOEXCEPT = 0;
|
||||
|
||||
virtual void property_change( detail::worker_fiber *, fiber_properties* ) {}
|
||||
virtual void property_change( fiber_base *, fiber_properties* ) {}
|
||||
};
|
||||
|
||||
namespace detail {
|
||||
@@ -51,9 +54,10 @@ public:
|
||||
typedef sched_algorithm_with_properties<PROPS> super;
|
||||
|
||||
// Start every subclass awakened() override with:
|
||||
// sched_algorithm_with_properties<PROPS>::awakened(f);
|
||||
virtual void awakened( detail::worker_fiber *f)
|
||||
// sched_algorithm_with_properties<PROPS>::awakened(fb);
|
||||
virtual void awakened( fiber_base *fb)
|
||||
{
|
||||
detail::worker_fiber* f = static_cast<detail::worker_fiber*>(fb);
|
||||
if (! f->get_properties())
|
||||
{
|
||||
// TODO: would be great if PROPS could be allocated on the new
|
||||
|
||||
@@ -86,7 +86,8 @@ public:
|
||||
{ return 0 == impl_; }
|
||||
};
|
||||
|
||||
fiber_base()
|
||||
fiber_base():
|
||||
nxt_(0)
|
||||
{}
|
||||
|
||||
virtual ~fiber_base() {};
|
||||
@@ -96,6 +97,9 @@ public:
|
||||
virtual void set_ready() BOOST_NOEXCEPT = 0;
|
||||
|
||||
virtual id get_id() const BOOST_NOEXCEPT = 0;
|
||||
|
||||
// for use by sched_algorithm to queue any subclass instance
|
||||
fiber_base * nxt_;
|
||||
};
|
||||
|
||||
}}}
|
||||
|
||||
@@ -36,28 +36,28 @@ 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() );
|
||||
BOOST_ASSERT( 0 == item->nxt_ );
|
||||
|
||||
if ( empty() )
|
||||
head_ = tail_ = item;
|
||||
else
|
||||
{
|
||||
tail_->next( item);
|
||||
tail_->nxt_ = item;
|
||||
tail_ = item;
|
||||
}
|
||||
}
|
||||
|
||||
worker_fiber * pop() BOOST_NOEXCEPT
|
||||
fiber_base * pop() BOOST_NOEXCEPT
|
||||
{
|
||||
BOOST_ASSERT( ! empty() );
|
||||
|
||||
worker_fiber * item = head_;
|
||||
head_ = head_->next();
|
||||
fiber_base * item = head_;
|
||||
head_ = head_->nxt_;
|
||||
if ( 0 == head_) tail_ = 0;
|
||||
item->next_reset();
|
||||
item->nxt_ = 0;
|
||||
return item;
|
||||
}
|
||||
|
||||
@@ -68,8 +68,8 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
worker_fiber * head_;
|
||||
worker_fiber * tail_;
|
||||
fiber_base * head_;
|
||||
fiber_base * tail_;
|
||||
};
|
||||
|
||||
}}}
|
||||
|
||||
@@ -40,7 +40,7 @@ public:
|
||||
void push( worker_fiber * item) BOOST_NOEXCEPT
|
||||
{
|
||||
BOOST_ASSERT( 0 != item);
|
||||
BOOST_ASSERT( 0 == item->next() );
|
||||
BOOST_ASSERT( 0 == item->nxt_ );
|
||||
|
||||
if ( empty() )
|
||||
head_ = tail_ = item;
|
||||
@@ -49,22 +49,22 @@ public:
|
||||
worker_fiber * f = head_, * prev = 0;
|
||||
do
|
||||
{
|
||||
worker_fiber * nxt = f->next();
|
||||
worker_fiber * nxt = static_cast<worker_fiber*>(f->nxt_);
|
||||
if ( item->time_point() <= f->time_point() )
|
||||
{
|
||||
if ( head_ == f)
|
||||
{
|
||||
BOOST_ASSERT( 0 == prev);
|
||||
|
||||
item->next( f);
|
||||
item->nxt_ = f;
|
||||
head_ = item;
|
||||
}
|
||||
else
|
||||
{
|
||||
BOOST_ASSERT( 0 != prev);
|
||||
|
||||
item->next( f);
|
||||
prev->next( item);
|
||||
item->nxt_ = f;
|
||||
prev->nxt_ = item;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -72,7 +72,7 @@ public:
|
||||
{
|
||||
BOOST_ASSERT( 0 == nxt);
|
||||
|
||||
tail_->next( item);
|
||||
tail_->nxt_ = item;
|
||||
tail_ = item;
|
||||
break;
|
||||
}
|
||||
@@ -100,7 +100,7 @@ public:
|
||||
chrono::high_resolution_clock::time_point now( chrono::high_resolution_clock::now() );
|
||||
while ( 0 != f)
|
||||
{
|
||||
worker_fiber * nxt = f->next();
|
||||
worker_fiber * nxt = static_cast<worker_fiber*>(f->nxt_);
|
||||
if ( fn( f, now) )
|
||||
{
|
||||
if ( f == head_)
|
||||
@@ -118,9 +118,9 @@ public:
|
||||
if ( 0 == nxt)
|
||||
tail_ = prev;
|
||||
|
||||
prev->next( nxt);
|
||||
prev->nxt_ = nxt;
|
||||
}
|
||||
f->next_reset();
|
||||
f->nxt_ = 0;
|
||||
f->time_point_reset();
|
||||
sched_algo->awakened( f);
|
||||
}
|
||||
|
||||
@@ -92,7 +92,6 @@ private:
|
||||
|
||||
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_;
|
||||
@@ -218,15 +217,6 @@ public:
|
||||
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_; }
|
||||
|
||||
|
||||
@@ -108,8 +108,10 @@ public:
|
||||
impl_()
|
||||
{}
|
||||
|
||||
explicit fiber( detail::worker_fiber * impl) BOOST_NOEXCEPT :
|
||||
impl_( impl)
|
||||
// This fiber_base* is allowed to be 0 -- call joinable() before performing
|
||||
// operations on such a fiber object!
|
||||
explicit fiber( fiber_base * impl) BOOST_NOEXCEPT :
|
||||
impl_( dynamic_cast<detail::worker_fiber*>(impl))
|
||||
{}
|
||||
|
||||
#ifdef BOOST_MSVC
|
||||
|
||||
@@ -33,11 +33,11 @@ private:
|
||||
rqueue_t rqueue_;
|
||||
|
||||
public:
|
||||
virtual void awakened( detail::worker_fiber *);
|
||||
virtual void awakened( fiber_base *);
|
||||
|
||||
virtual detail::worker_fiber * pick_next();
|
||||
virtual fiber_base * pick_next();
|
||||
|
||||
virtual void priority( detail::worker_fiber *, int) BOOST_NOEXCEPT;
|
||||
virtual void priority( fiber_base *, int) BOOST_NOEXCEPT;
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
@@ -30,7 +30,6 @@ worker_fiber::worker_fiber( coro_t::yield_type * callee) :
|
||||
fiber_base(),
|
||||
use_count_( 1), // allocated on stack
|
||||
fss_data_(),
|
||||
nxt_( 0),
|
||||
tp_( (chrono::high_resolution_clock::time_point::max)() ),
|
||||
callee_( callee),
|
||||
caller_(),
|
||||
|
||||
@@ -172,17 +172,17 @@ void fm_run()
|
||||
|
||||
BOOST_ASSERT( 0 != fm);
|
||||
|
||||
// move all fibers witch are ready (state_ready)
|
||||
// move all fibers which are ready (state_ready)
|
||||
// from waiting-queue to the runnable-queue
|
||||
fm->wqueue_.move_to( fm->sched_algo_, fetch_ready);
|
||||
|
||||
// pop new fiber from ready-queue which is not complete
|
||||
// (example: fiber in ready-queue could be canceled by active-fiber)
|
||||
detail::worker_fiber * f( fm->sched_algo_->pick_next() );
|
||||
fiber_base * f( fm->sched_algo_->pick_next());
|
||||
if ( f)
|
||||
{
|
||||
BOOST_ASSERT_MSG( f->is_ready(), "fiber with invalid state in ready-queue");
|
||||
fm_resume_( f);
|
||||
fm_resume_( static_cast<detail::worker_fiber*>(f));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -16,30 +16,30 @@ namespace boost {
|
||||
namespace fibers {
|
||||
|
||||
void
|
||||
round_robin::awakened( detail::worker_fiber * f)
|
||||
round_robin::awakened( fiber_base * f)
|
||||
{
|
||||
BOOST_ASSERT( 0 != f);
|
||||
|
||||
rqueue_.push( f);
|
||||
}
|
||||
|
||||
detail::worker_fiber *
|
||||
fiber_base *
|
||||
round_robin::pick_next()
|
||||
{
|
||||
detail::worker_fiber * victim = 0;
|
||||
fiber_base * victim = 0;
|
||||
if ( ! rqueue_.empty() )
|
||||
victim = rqueue_.pop();
|
||||
return victim;
|
||||
}
|
||||
|
||||
void
|
||||
round_robin::priority( detail::worker_fiber * f, int prio) BOOST_NOEXCEPT
|
||||
round_robin::priority( fiber_base * f, int prio) BOOST_NOEXCEPT
|
||||
{
|
||||
BOOST_ASSERT( f);
|
||||
|
||||
// set only priority to fiber
|
||||
// round-robin does not respect priorities
|
||||
f->priority( prio);
|
||||
static_cast<detail::worker_fiber*>(f)->priority( prio);
|
||||
}
|
||||
|
||||
}}
|
||||
|
||||
Reference in New Issue
Block a user