mirror of
https://github.com/boostorg/fiber.git
synced 2026-02-14 12:42:28 +00:00
339 lines
11 KiB
Plaintext
339 lines
11 KiB
Plaintext
[/
|
|
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
|
|
]
|
|
|
|
[#scheduling]
|
|
[section:scheduling Scheduling]
|
|
|
|
The fibers in a thread are coordinated by a fiber manager. Fibers trade
|
|
control cooperatively, rather than preemptively: the currently-running fiber
|
|
retains control until it invokes some operation that passes control to the
|
|
manager. Each time a fiber suspends (or yields), the fiber manager consults a
|
|
scheduler to determine which fiber will run next.
|
|
|
|
__boost_fiber__ provides the fiber manager, but the scheduler is a
|
|
customization point. (See [link custom Customization].)
|
|
|
|
Each thread has its own scheduler. By default, __boost_fiber__ implicitly
|
|
instantiates [class_link round_robin] as the scheduler for each thread.
|
|
|
|
You are explicitly permitted to code your own __algo__ subclass, and to
|
|
specify it to [function_link use_scheduling_algorithm].
|
|
|
|
|
|
void thread_fn() {
|
|
boost::fibers::use_scheduling_algorithm<my_fiber_scheduler>();
|
|
...
|
|
}
|
|
|
|
A scheduler class must implement interface __algo__. __boost_fiber__ provides
|
|
one scheduler: [class_link round_robin].
|
|
|
|
|
|
[class_heading sched_algorithm]
|
|
|
|
`sched_algorithm` is the abstract base class defining the interface that a
|
|
fiber scheduler must implement.
|
|
|
|
#include <boost/fiber/algorithm.hpp>
|
|
|
|
struct sched_algorithm {
|
|
virtual ~sched_algorithm() {}
|
|
|
|
virtual void awakened( fiber_context *) = 0;
|
|
|
|
virtual fiber_context * pick_next() = 0;
|
|
|
|
virtual std::size_t ready_fibers() const noexcept = 0;
|
|
};
|
|
|
|
[member_heading sched_algorithm..awakened]
|
|
|
|
virtual void awakened( fiber_context * f) = 0;
|
|
|
|
[variablelist
|
|
[[Effects:] [Informs the scheduler that fiber `f` is ready to run. Fiber `f`
|
|
might be newly launched, or it might have been blocked but has just been
|
|
awakened, or it might have called [ns_function_link this_fiber..yield].]]
|
|
[[Note:] [This method advises the scheduler to add fiber `f` to its collection
|
|
of fibers ready to run. A typical scheduler implementation places `f` into a
|
|
queue.]]
|
|
[[See also:] [[class_link round_robin]]]
|
|
]
|
|
|
|
[member_heading sched_algorithm..pick_next]
|
|
|
|
virtual fiber_context * pick_next() = 0;
|
|
|
|
[variablelist
|
|
[[Returns:] [the fiber which is to be resumed next, or `nullptr` if there is no
|
|
ready fiber.]]
|
|
[[Note:] [This is where the scheduler actually specifies the fiber which is to
|
|
run next. A typical scheduler implementation chooses the head of the ready
|
|
queue.]]
|
|
[[See also:] [[class_link round_robin]]]
|
|
]
|
|
|
|
[member_heading sched_algorithm..ready_fibers]
|
|
|
|
virtual std::size_t ready_fibers() const noexcept = 0;
|
|
|
|
[variablelist
|
|
[[Returns:] [the number of fibers ready to run.]]
|
|
]
|
|
|
|
|
|
[class_heading round_robin]
|
|
|
|
This class implements __algo__, scheduling fibers in round-robin fashion.
|
|
|
|
#include <boost/fiber/round_robin.hpp>
|
|
|
|
class round_robin : public sched_algorithm {
|
|
virtual void awakened( fiber_context *);
|
|
|
|
virtual fiber_context * pick_next();
|
|
|
|
virtual std::size_t ready_fibers() const noexcept;
|
|
};
|
|
|
|
[member_heading round_robin..awakened]
|
|
|
|
virtual void awakened( fiber_context * f);
|
|
|
|
[variablelist
|
|
[[Effects:] [Enqueues fiber `f` onto a ready queue.]]
|
|
]
|
|
|
|
[member_heading round_robin..pick_next]
|
|
|
|
virtual fiber_context * pick_next();
|
|
|
|
[variablelist
|
|
[[Returns:] [the fiber at the head of the ready queue, or 0 if the queue is
|
|
empty.]]
|
|
[[Note:] [Placing ready fibers onto a queue, and returning them from the head
|
|
of that queue, shares the thread between ready fibers in round-robin fashion.]]
|
|
]
|
|
|
|
[member_heading round_robin..ready_fibers]
|
|
|
|
virtual std::size_t ready_fibers() const noexcept;
|
|
|
|
[variablelist
|
|
[[Returns:] [the number of fibers ready to run.]]
|
|
]
|
|
|
|
|
|
[heading Custom Scheduler Fiber Properties]
|
|
|
|
A scheduler class directly derived from __algo__ can use any information
|
|
available from [class_link fiber_context] to implement the `sched_algorithm`
|
|
interface. But a custom scheduler might need to track additional properties
|
|
for a fiber. For instance, a priority-based scheduler would need to track a
|
|
fiber's priority.
|
|
|
|
__boost_fiber__ provides a mechanism by which your custom scheduler can
|
|
associate custom properties with each fiber.
|
|
|
|
[class_heading fiber_properties]
|
|
|
|
A custom fiber properties class must be derived from `fiber_properties`.
|
|
|
|
#include <boost/fiber/properties.hpp>
|
|
|
|
class fiber_properties {
|
|
public:
|
|
fiber_properties( fiber_context* f);
|
|
|
|
virtual ~fiber_properties() {}
|
|
|
|
protected:
|
|
void notify();
|
|
};
|
|
|
|
[heading Constructor]
|
|
|
|
fiber_properties( fiber_context* f);
|
|
|
|
[variablelist
|
|
[[Effects:] [Constructs base-class component of custom subclass.]]
|
|
[[Note:] [Your subclass constructor must accept a `fiber_context*` and pass it
|
|
to the base-class `fiber_properties` constructor.]]
|
|
]
|
|
|
|
[member_heading fiber_properties..notify]
|
|
|
|
void notify();
|
|
|
|
[variablelist
|
|
[[Effects:] [Pass control to the custom [template_link
|
|
sched_algorithm_with_properties] subclass's [member_link
|
|
sched_algorithm_with_properties..property_change] method.]]
|
|
[[Note:] [A custom scheduler's [member_link
|
|
sched_algorithm_with_properties..pick_next] method might dynamically select
|
|
from the ready fibers, or [member_link
|
|
sched_algorithm_with_properties..awakened] might instead insert each ready
|
|
fiber into some form of ready queue for `pick_next()`. In the latter case, if
|
|
application code modifies a fiber property (e.g. priority) that should affect
|
|
that fiber's relationship to other ready fibers, the custom scheduler must be
|
|
given the opportunity to reorder its ready queue. The custom property subclass
|
|
should implement an access method to modify such a property; that access
|
|
method should call `notify()` once the new property value has been stored.
|
|
This passes control to the custom scheduler's `property_change()` method,
|
|
allowing the custom scheduler to reorder its ready queue appropriately. Use at
|
|
your discretion. Of course, if you define a property which does not affect the
|
|
behavior of the `pick_next()` method, you need not call `notify()` when that
|
|
property is modified.]]
|
|
]
|
|
|
|
[template_heading sched_algorithm_with_properties]
|
|
|
|
A custom scheduler that depends on a custom properties class `PROPS` should be
|
|
derived from `sched_algorithm_with_properties<PROPS>`. `PROPS` should be
|
|
derived from [class_link fiber_properties].
|
|
|
|
#include <boost/fiber/algorithm.hpp>
|
|
|
|
template< typename PROPS >
|
|
struct sched_algorithm_with_properties {
|
|
// override this method instead of sched_algorithm::awakened()
|
|
virtual void awakened( fiber_context * f, PROPS & properties) = 0;
|
|
|
|
virtual fiber_context * pick_next();
|
|
|
|
virtual std::size_t ready_fibers() const noexcept;
|
|
|
|
// obtain f's associated PROPS instance
|
|
PROPS & properties( fiber_context * f);
|
|
|
|
// override this to be notified by PROPS::notify()
|
|
virtual void property_change( fiber_context * f, PROPS & properties);
|
|
|
|
// Override this to customize instantiation of PROPS, e.g. use a different
|
|
// allocator. Each PROPS instance is associated with a particular
|
|
// fiber_context.
|
|
virtual fiber_properties * new_properties( fiber_context * f);
|
|
};
|
|
|
|
[member_heading sched_algorithm_with_properties..awakened]
|
|
|
|
virtual void awakened( fiber_context * f, PROPS & properties);
|
|
|
|
[variablelist
|
|
[[Effects:] [Informs the scheduler that fiber `f` is ready to run, like
|
|
[member_link sched_algorithm..awakened]. Passes the fiber's associated `PROPS`
|
|
instance.]]
|
|
[[Note:] [A `sched_algorithm_with_properties<>` subclass must override this
|
|
method instead of `sched_algorithm::awakened()`.]]
|
|
]
|
|
|
|
[member_heading sched_algorithm_with_properties..pick_next]
|
|
|
|
virtual fiber_context * pick_next();
|
|
|
|
[variablelist
|
|
[[Returns:] [the fiber which is to be resumed next, or `nullptr` if there is no
|
|
ready fiber.]]
|
|
[[Note:] [same as [member_link sched_algorithm..pick_next]]]
|
|
]
|
|
|
|
[member_heading sched_algorithm_with_properties..ready_fibers]
|
|
|
|
virtual std::size_t ready_fibers() const noexcept;
|
|
|
|
[variablelist
|
|
[[Returns:] [the number of fibers ready to run.]]
|
|
[[Note:] [same as [member_link sched_algorithm..ready_fibers]]]
|
|
]
|
|
|
|
[member_heading sched_algorithm_with_properties..properties]
|
|
|
|
PROPS& properties( fiber_context * f);
|
|
|
|
[variablelist
|
|
[[Returns:] [the `PROPS` instance associated with fiber `f`.]]
|
|
[[Note:] [The fiber's associated `PROPS` instance is already passed to
|
|
[member_link sched_algorithm_with_properties..awakened] and [member_link
|
|
sched_algorithm_with_properties..property_change]. However, every [class_link
|
|
sched_algorithm] subclass is expected to track a collection of ready
|
|
[class_link fiber_context] instances. This method allows your custom scheduler
|
|
to retrieve the [class_link fiber_properties] subclass instance for any
|
|
`fiber_context` in its collection.]]
|
|
]
|
|
|
|
[member_heading sched_algorithm_with_properties..property_change]
|
|
|
|
virtual void property_change( fiber_context * f, PROPS & properties);
|
|
|
|
[variablelist
|
|
[[Effects:] [Notify the custom scheduler of a possibly-relevant change to a
|
|
property belonging to fiber `f`. `properties` contains the new values of
|
|
all relevant properties.]]
|
|
[[Note:] [This method is only called when a custom [class_link
|
|
fiber_properties] subclass explicitly calls [member_link
|
|
fiber_properties..notify].]]
|
|
]
|
|
|
|
[member_heading sched_algorithm_with_properties..new_properties]
|
|
|
|
virtual fiber_properties * new_properties( fiber_context * f);
|
|
|
|
[variablelist
|
|
[[Returns:] [A new instance of [class_link fiber_properties] subclass
|
|
`PROPS`.]]
|
|
[[Note:] [By default, `sched_algorithm_with_properties<>::new_properties()`
|
|
simply returns `new PROPS(f)`, placing the `PROPS` instance on the heap.
|
|
Override this method to allocate `PROPS` some other way. The returned
|
|
`fiber_properties` pointer must point to the `PROPS` instance to be associated
|
|
with fiber `f`.]]
|
|
]
|
|
|
|
[class_heading fiber_context]
|
|
|
|
While you are free to treat `fiber_context*` as an opaque token, certain
|
|
`fiber_context` members may be useful to a custom scheduler implementation.
|
|
|
|
(Most `fiber_context` members are implementation details; most of interest are
|
|
implementations of [class_link fiber] methods.)
|
|
|
|
#include <boost/fiber/fiber_context.hpp>
|
|
|
|
class fiber_context {
|
|
public:
|
|
fiber_context * nxt;
|
|
|
|
static fiber_context * main_fiber();
|
|
|
|
};
|
|
|
|
[data_member_heading fiber_context..nxt]
|
|
|
|
fiber_context * nxt;
|
|
|
|
[variablelist
|
|
[[Note:] [This link pointer may be used to help implement a custom scheduler's
|
|
ready queue. It is overwritten by the fiber manager every time this
|
|
`fiber_context` is returned by [member_link sched_algorithm..pick_next], but
|
|
between the time the fiber manager passes this `fiber_context` to [member_link
|
|
sched_algorithm..awakened] (or [member_link
|
|
sched_algorithm_with_properties..awakened]) and the time your `pick_next()`
|
|
returns it to the fiber manager, it is available for use by your custom
|
|
scheduler.]]
|
|
]
|
|
|
|
[static_member_heading fiber_context..main_fiber]
|
|
|
|
static fiber_context * main_fiber();
|
|
|
|
[variablelist
|
|
[[Returns:] [the `fiber_context` associated with the "main" fiber of the
|
|
thread: the one implicitly created by the thread itself, rather than one
|
|
explicitly created by __boost_fiber__.]]
|
|
]
|
|
|
|
[endsect]
|