mirror of
https://github.com/boostorg/fiber.git
synced 2026-02-12 12:02:54 +00:00
Nat Goodspeed:
- Change some doc references from 'algorithm' to 'sched_algorithm'. - Initial cut at supporting arbitrary user-coded scheduler properties. - Set fiber_properties::sched_algo_ every time through awakened(). - Define sched_algorithm methods on fiber_base*, not worker_fiber*. - Simplify detail::fifo by making tail_ point to last link pointer. - Reimplement waiting_queue::push() using pointer-to-pointer trick. - Reimplement waiting_queue::move_to() using fiber_base** scan. - Make bounded_queue::tail_ a ptr* to simplify appending new nodes. - Make unbounded_queue::tail_ a ptr* to simplify linking new nodes. - Remove thread_affinity flag and access methods. - Re-add thread_affinity specific to workstealing_round_robin. - Remove 'priority' for every fiber, and its support methods.
This commit is contained in:
@@ -12,47 +12,71 @@
|
||||
# include BOOST_ABI_PREFIX
|
||||
#endif
|
||||
|
||||
workstealing_round_robin::workstealing_round_robin():
|
||||
rhead_(0),
|
||||
rtail_(&rhead_)
|
||||
{}
|
||||
|
||||
void
|
||||
workstealing_round_robin::awakened( boost::fibers::detail::worker_fiber * f)
|
||||
workstealing_round_robin::awakened( boost::fibers::fiber_base * f)
|
||||
{
|
||||
// forward this call to base-class method
|
||||
boost::fibers::sched_algorithm_with_properties<affinity>::awakened(f);
|
||||
|
||||
boost::mutex::scoped_lock lk( mtx_);
|
||||
rqueue_.push_back( f);
|
||||
// append this fiber_base* to ready queue
|
||||
BOOST_ASSERT(! f->nxt_);
|
||||
*rtail_ = f;
|
||||
rtail_ = &f->nxt_;
|
||||
}
|
||||
|
||||
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;
|
||||
if ( ! rqueue_.empty() )
|
||||
boost::fibers::fiber_base * f = 0;
|
||||
if ( rhead_ )
|
||||
{
|
||||
f = rqueue_.front();
|
||||
rqueue_.pop_front();
|
||||
f = rhead_;
|
||||
// pop head item from ready queue
|
||||
rhead_ = rhead_->nxt_;
|
||||
f->nxt_ = 0;
|
||||
// if that was the last item, reset tail_
|
||||
if (! rhead_)
|
||||
rtail_ = &rhead_;
|
||||
}
|
||||
return f;
|
||||
}
|
||||
|
||||
void
|
||||
workstealing_round_robin::priority( boost::fibers::detail::worker_fiber * f, int prio) BOOST_NOEXCEPT
|
||||
{
|
||||
BOOST_ASSERT( f);
|
||||
|
||||
// set only priority to fiber
|
||||
// round-robin does not respect priorities
|
||||
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;
|
||||
if ( ! rqueue_.empty() )
|
||||
|
||||
// Search the queue for the LAST fiber_base that's willing to migrate,
|
||||
// in other words (! thread_affinity).
|
||||
boost::fibers::fiber_base ** fp = &rhead_, ** found = 0;
|
||||
for ( ; *fp; fp = &(*fp)->nxt_)
|
||||
{
|
||||
f = rqueue_.back();
|
||||
rqueue_.pop_back();
|
||||
// do not consider any fiber whose thread_affinity is set
|
||||
if (! properties(*fp).thread_affinity)
|
||||
found = fp;
|
||||
}
|
||||
return boost::fibers::fiber( f);
|
||||
if (! found)
|
||||
{
|
||||
// either the queue is completely empty or all current entries have
|
||||
// thread_affinity set
|
||||
return boost::fibers::fiber(static_cast<boost::fibers::fiber_base*>(0));
|
||||
}
|
||||
// We found at least one fiber_base whose thread_affinity is NOT set;
|
||||
// *found points to the last of these. Unlink and return it.
|
||||
boost::fibers::fiber_base* ret = *found;
|
||||
*found = ret->nxt_;
|
||||
ret->nxt_ = 0;
|
||||
// if that was the last item, reset tail_
|
||||
if (! *found)
|
||||
rtail_ = &rhead_;
|
||||
return boost::fibers::fiber(ret);
|
||||
}
|
||||
|
||||
#ifdef BOOST_HAS_ABI_HEADERS
|
||||
|
||||
@@ -11,10 +11,8 @@
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/thread/mutex.hpp>
|
||||
|
||||
#include <boost/fiber/detail/config.hpp>
|
||||
#include <boost/fiber/detail/fifo.hpp>
|
||||
#include <boost/fiber/detail/worker_fiber.hpp>
|
||||
#include <boost/fiber/fiber_manager.hpp>
|
||||
#include <boost/fiber/fiber.hpp>
|
||||
#include <boost/fiber/properties.hpp>
|
||||
|
||||
#ifdef BOOST_HAS_ABI_HEADERS
|
||||
# include BOOST_ABI_PREFIX
|
||||
@@ -25,20 +23,34 @@
|
||||
# pragma warning(disable:4251 4275)
|
||||
# endif
|
||||
|
||||
class workstealing_round_robin : public boost::fibers::sched_algorithm
|
||||
struct affinity: public boost::fibers::fiber_properties
|
||||
{
|
||||
affinity(boost::fibers::fiber_properties::back_ptr p):
|
||||
fiber_properties(p),
|
||||
// By default, assume a given fiber CAN migrate to another thread.
|
||||
thread_affinity(false)
|
||||
{}
|
||||
|
||||
bool thread_affinity;
|
||||
};
|
||||
|
||||
class workstealing_round_robin :
|
||||
public boost::fibers::sched_algorithm_with_properties<affinity>
|
||||
{
|
||||
private:
|
||||
typedef std::deque< boost::fibers::detail::worker_fiber * > rqueue_t;
|
||||
|
||||
boost::mutex mtx_;
|
||||
rqueue_t rqueue_;
|
||||
|
||||
// We should package these as a queue class. Better yet, we should
|
||||
// refactor one of our existing (intrusive) queue classes to support the
|
||||
// required operations generically. But for now...
|
||||
boost::fibers::fiber_base *rhead_, **rtail_;
|
||||
|
||||
public:
|
||||
virtual void awakened( boost::fibers::detail::worker_fiber *);
|
||||
workstealing_round_robin();
|
||||
|
||||
virtual boost::fibers::detail::worker_fiber * pick_next();
|
||||
virtual void awakened( boost::fibers::fiber_base *);
|
||||
|
||||
virtual void priority( boost::fibers::detail::worker_fiber *, int) BOOST_NOEXCEPT;
|
||||
virtual boost::fibers::fiber_base * pick_next();
|
||||
|
||||
boost::fibers::fiber steal();
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user