120 lines
5.1 KiB
Plaintext
120 lines
5.1 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
|
|
]
|
|
|
|
[/ import path is relative to this .qbk file]
|
|
[import ../examples/priority.cpp]
|
|
|
|
[#custom]
|
|
[section:custom Customization]
|
|
|
|
[heading Overview]
|
|
|
|
As noted in the [link scheduling Scheduling] section, by default
|
|
__boost_fiber__ uses its own [class_link round_robin] scheduler for each
|
|
thread. To control the way __boost_fiber__ schedules ready fibers on a
|
|
particular thread, in general you must follow several steps. This section
|
|
discusses those steps, whereas [link scheduling Scheduling] serves as a
|
|
reference for the classes involved.
|
|
|
|
The library's fiber manager keeps track of suspended (blocked) fibers. Only
|
|
when a fiber becomes ready to run is it passed to the scheduler. Of course, if
|
|
there are fewer than two ready fibers, the scheduler's job is trivial. Only
|
|
when there are two or more ready fibers does the particular scheduler
|
|
implementation start to influence the overall sequence of fiber execution.
|
|
|
|
In this section we illustrate a simple custom scheduler that honors an integer
|
|
fiber priority. We will implement it such that a fiber with higher priority is
|
|
preferred over a fiber with lower priority. Any fibers with equal priority
|
|
values are serviced on a round-robin basis.
|
|
|
|
[/ @path link is relative to (eventual) doc/html/index.html, hence ../..]
|
|
The full source code for the examples below is found in
|
|
[@../../examples/priority.cpp priority.cpp].
|
|
|
|
[heading Custom Property Class]
|
|
|
|
The first essential point is that we must associate an integer priority with
|
|
each fiber.[footnote A previous version of the Fiber library implicitly
|
|
tracked an int priority for each fiber, even though the default scheduler
|
|
ignored it. This has been dropped, since the library now supports arbitrary
|
|
scheduler-specific fiber properties.]
|
|
|
|
One might suggest deriving a custom [class_link fiber] subclass to store such
|
|
properties. There are a couple of reasons for the present mechanism.
|
|
|
|
# __boost_fiber__ provides a number of different ways to launch a fiber.
|
|
(Consider [ns_function_link fibers..async].) Higher-level libraries might
|
|
introduce additional such wrapper functions. A custom scheduler must
|
|
associate its custom properties with ['every] fiber in the thread, not only
|
|
the ones explicitly launched by instantiating a custom `fiber` subclass.
|
|
# Consider a large existing program that launches fibers in many different
|
|
places in the code. We discover a need to introduce a custom scheduler for a
|
|
particular thread. If supporting that scheduler's custom properties required
|
|
a particular `fiber` subclass, we would have to hunt down and modify every
|
|
place that launches a fiber on that thread.
|
|
# The [class_link fiber] class is actually just a handle to internal
|
|
[class_link context] data. A subclass of `fiber` would not add data to
|
|
`context`.
|
|
|
|
The present mechanism allows you to ["drop in] a custom scheduler with its
|
|
attendant custom properties ['without] altering the rest of your application.
|
|
|
|
Instead of deriving a custom scheduler fiber properties subclass from
|
|
[class_link fiber], you must instead derive it from [class_link
|
|
fiber_properties].
|
|
|
|
[priority_props]
|
|
|
|
[heading Custom Scheduler Class]
|
|
|
|
Now we can derive a custom scheduler from [template_link
|
|
algorithm_with_properties], specifying our custom property class
|
|
`priority_props` as the template parameter.
|
|
|
|
[priority_scheduler]
|
|
|
|
Our example `priority_scheduler` doesn't override [member_link
|
|
algorithm_with_properties..new_properties]: we're content with
|
|
allocating `priority_props` instances on the heap.
|
|
|
|
[heading Replace Default Scheduler]
|
|
|
|
You must call [function_link use_scheduling_algorithm] at the start of each
|
|
thread on which you want __boost_fiber__ to use your custom scheduler rather
|
|
than its own default [class_link round_robin]. Specifically, you must call
|
|
`use_scheduling_algorithm()` before performing any other __boost_fiber__
|
|
operations on that thread.
|
|
|
|
[main]
|
|
|
|
[heading Use Properties]
|
|
|
|
The running fiber can access its own [class_link fiber_properties] subclass
|
|
instance by calling [ns_function_link this_fiber..properties]. Although
|
|
`properties<>()` is a nullary function, you must pass, as a template
|
|
parameter, the `fiber_properties` subclass.
|
|
|
|
[main_name]
|
|
|
|
Given a [class_link fiber] instance still connected with a running fiber (that
|
|
is, not [member_link fiber..detach]ed), you may access that fiber's properties
|
|
using [template_member_link fiber..properties]. As with
|
|
`boost::this_fiber::properties<>()`, you must pass your `fiber_properties` subclass
|
|
as the template parameter.
|
|
|
|
[launch]
|
|
|
|
Launching a new fiber schedules that fiber as ready, but does ['not]
|
|
immediately enter its ['fiber-function]. The current fiber retains control
|
|
until it blocks (or yields, or terminates) for some other reason. As shown in
|
|
the `launch()` function above, it is reasonable to launch a fiber and
|
|
immediately set relevant properties -- such as, for instance, its priority.
|
|
Your custom scheduler can then make use of this information next time the
|
|
fiber manager calls [member_link algorithm_with_properties..pick_next].
|
|
|
|
[endsect]
|