123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993 |
- [/
- 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. Different threads in a process may use
- different schedulers. 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. For the most
- part, your `algorithm` subclass need not defend against cross-thread
- calls: the fiber manager intercepts and defers such calls. Most
- `algorithm` methods are only ever directly called from the thread whose
- fibers it is managing [mdash] with exceptions as documented below.
- Your `algorithm` subclass is engaged on a particular thread by calling
- [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
- schedulers: __round_robin__, __work_stealing__, __numa_work_stealing__ and
- __shared_work__.
- void thread( std::uint32_t thread_count) {
- // thread registers itself at work-stealing scheduler
- boost::fibers::use_scheduling_algorithm< boost::fibers::algo::work_stealing >( thread_count);
- ...
- }
- // count of logical cpus
- std::uint32_t thread_count = std::thread::hardware_concurrency();
- // start worker-threads first
- std::vector< std::thread > threads;
- for ( std::uint32_t i = 1 /* count start-thread */; i < thread_count; ++i) {
- // spawn thread
- threads.emplace_back( thread, thread_count);
- }
- // start-thread registers itself at work-stealing scheduler
- boost::fibers::use_scheduling_algorithm< boost::fibers::algo::work_stealing >( thread_count);
- ...
- The example spawns as many threads as `std::thread::hardware_concurrency()`
- returns.
- Each thread runs a __work_stealing__ scheduler. Each instance of this
- scheduler needs to know how many threads run the work-stealing scheduler in the
- program.
- If the local queue of one thread runs out of ready fibers, the thread tries to
- steal a ready fiber from another thread running this scheduler.
- [class_heading algorithm]
- `algorithm` is the abstract base class defining the interface that a
- fiber scheduler must implement.
- #include <boost/fiber/algo/algorithm.hpp>
- namespace boost {
- namespace fibers {
- namespace algo {
- struct algorithm {
- virtual ~algorithm();
- virtual void awakened( context *) noexcept = 0;
- virtual context * pick_next() noexcept = 0;
- virtual bool has_ready_fibers() const noexcept = 0;
- virtual void suspend_until( std::chrono::steady_clock::time_point const&) noexcept = 0;
- virtual void notify() noexcept = 0;
- };
- }}}
- [member_heading algorithm..awakened]
- virtual void awakened( context * f) noexcept = 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 algorithm..pick_next]
- virtual context * pick_next() noexcept = 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 algorithm..has_ready_fibers]
- virtual bool has_ready_fibers() const noexcept = 0;
- [variablelist
- [[Returns:] [`true` if scheduler has fibers ready to run.]]
- ]
- [member_heading algorithm..suspend_until]
- virtual void suspend_until( std::chrono::steady_clock::time_point const& abs_time) noexcept = 0;
- [variablelist
- [[Effects:] [Informs the scheduler that no fiber will be ready until
- time-point `abs_time`.]]
- [[Note:] [This method allows a custom scheduler to yield control to the
- containing environment in whatever way makes sense. The fiber manager is
- stating that `suspend_until()` need not return until `abs_time` [mdash] or
- [member_link algorithm..notify] is called [mdash] whichever comes first.
- The interaction with `notify()` means that, for instance, calling
- [@http://en.cppreference.com/w/cpp/thread/sleep_until
- `std::this_thread::sleep_until(abs_time)`] would be too simplistic.
- [member_link round_robin..suspend_until] uses a
- [@http://en.cppreference.com/w/cpp/thread/condition_variable
- `std::condition_variable`] to coordinate with [member_link
- round_robin..notify].]]
- [[Note:] [Given that `notify()` might be called from another thread, your
- `suspend_until()` implementation [mdash] like the rest of your
- `algorithm` implementation [mdash] must guard any data it shares with
- your `notify()` implementation.]]
- ]
- [member_heading algorithm..notify]
- virtual void notify() noexcept = 0;
- [variablelist
- [[Effects:] [Requests the scheduler to return from a pending call to
- [member_link algorithm..suspend_until].]]
- [[Note:] [Alone among the `algorithm` methods, `notify()` may be called
- from another thread. Your `notify()` implementation must guard any data it
- shares with the rest of your `algorithm` implementation.]]
- ]
- [class_heading round_robin]
- This class implements __algo__, scheduling fibers in round-robin fashion.
- #include <boost/fiber/algo/round_robin.hpp>
- namespace boost {
- namespace fibers {
- namespace algo {
- class round_robin : public algorithm {
- virtual void awakened( context *) noexcept;
- virtual context * pick_next() noexcept;
- virtual bool has_ready_fibers() const noexcept;
- virtual void suspend_until( std::chrono::steady_clock::time_point const&) noexcept;
- virtual void notify() noexcept;
- };
- }}}
- [member_heading round_robin..awakened]
- virtual void awakened( context * f) noexcept;
- [variablelist
- [[Effects:] [Enqueues fiber `f` onto a ready queue.]]
- [[Throws:] [Nothing.]]
- ]
- [member_heading round_robin..pick_next]
- virtual context * pick_next() noexcept;
- [variablelist
- [[Returns:] [the fiber at the head of the ready queue, or `nullptr` if the
- queue is empty.]]
- [[Throws:] [Nothing.]]
- [[Note:] [Placing ready fibers onto the tail of 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..has_ready_fibers]
- virtual bool has_ready_fibers() const noexcept;
- [variablelist
- [[Returns:] [`true` if scheduler has fibers ready to run.]]
- [[Throws:] [Nothing.]]
- ]
- [member_heading round_robin..suspend_until]
- virtual void suspend_until( std::chrono::steady_clock::time_point const& abs_time) noexcept;
- [variablelist
- [[Effects:] [Informs `round_robin` that no ready fiber will be available until
- time-point `abs_time`. This implementation blocks in
- [@http://en.cppreference.com/w/cpp/thread/condition_variable/wait_until
- `std::condition_variable::wait_until()`].]]
- [[Throws:] [Nothing.]]
- ]
- [member_heading round_robin..notify]
- virtual void notify() noexcept = 0;
- [variablelist
- [[Effects:] [Wake up a pending call to [member_link
- round_robin..suspend_until], some fibers might be ready. This implementation
- wakes `suspend_until()` via
- [@http://en.cppreference.com/w/cpp/thread/condition_variable/notify_all
- `std::condition_variable::notify_all()`].]]
- [[Throws:] [Nothing.]]
- ]
- [class_heading work_stealing]
- This class implements __algo__; if the local ready-queue runs out of ready fibers, ready fibers are stolen
- from other schedulers.[br]
- The victim scheduler (from which a ready fiber is stolen) is selected at random.
- [note Worker-threads are stored in a static variable, dynamically adding/removing worker threads is not supported.]
- #include <boost/fiber/algo/work_stealing.hpp>
- namespace boost {
- namespace fibers {
- namespace algo {
- class work_stealing : public algorithm {
- public:
- work_stealing( std::uint32_t thread_count, bool suspend = false);
- work_stealing( work_stealing const&) = delete;
- work_stealing( work_stealing &&) = delete;
- work_stealing & operator=( work_stealing const&) = delete;
- work_stealing & operator=( work_stealing &&) = delete;
- virtual void awakened( context *) noexcept;
- virtual context * pick_next() noexcept;
- virtual bool has_ready_fibers() const noexcept;
- virtual void suspend_until( std::chrono::steady_clock::time_point const&) noexcept;
- virtual void notify() noexcept;
- };
- }}}
- [heading Constructor]
- work_stealing( std::uint32_t thread_count, bool suspend = false);
- [variablelist
- [[Effects:] [Constructs work-stealing scheduling algorithm. `thread_count` represents the number of threads
- running this algorithm.]]
- [[Throws:] [`system_error`]]
- [[Note:][If `suspend` is set to `true`, then the scheduler suspends if no ready fiber could be stolen.
- The scheduler will by woken up if a sleeping fiber times out or it was notified from remote (other thread or
- fiber scheduler).]]
- ]
- [member_heading work_stealing..awakened]
- virtual void awakened( context * f) noexcept;
- [variablelist
- [[Effects:] [Enqueues fiber `f` onto the shared ready queue.]]
- [[Throws:] [Nothing.]]
- ]
- [member_heading work_stealing..pick_next]
- virtual context * pick_next() noexcept;
- [variablelist
- [[Returns:] [the fiber at the head of the ready queue, or `nullptr` if the
- queue is empty.]]
- [[Throws:] [Nothing.]]
- [[Note:] [Placing ready fibers onto the tail of the sahred queue, and returning them
- from the head of that queue, shares the thread between ready fibers in
- round-robin fashion.]]
- ]
- [member_heading work_stealing..has_ready_fibers]
- virtual bool has_ready_fibers() const noexcept;
- [variablelist
- [[Returns:] [`true` if scheduler has fibers ready to run.]]
- [[Throws:] [Nothing.]]
- ]
- [member_heading work_stealing..suspend_until]
- virtual void suspend_until( std::chrono::steady_clock::time_point const& abs_time) noexcept;
- [variablelist
- [[Effects:] [Informs `work_stealing` that no ready fiber will be available until
- time-point `abs_time`. This implementation blocks in
- [@http://en.cppreference.com/w/cpp/thread/condition_variable/wait_until
- `std::condition_variable::wait_until()`].]]
- [[Throws:] [Nothing.]]
- ]
- [member_heading work_stealing..notify]
- virtual void notify() noexcept = 0;
- [variablelist
- [[Effects:] [Wake up a pending call to [member_link
- work_stealing..suspend_until], some fibers might be ready. This implementation
- wakes `suspend_until()` via
- [@http://en.cppreference.com/w/cpp/thread/condition_variable/notify_all
- `std::condition_variable::notify_all()`].]]
- [[Throws:] [Nothing.]]
- ]
- [class_heading shared_work]
- [note Because of the non-locality of data, ['shared_work] is less performant
- than __work_stealing__.]
- This class implements __algo__, scheduling fibers in round-robin fashion.
- Ready fibers are shared between all instances (running on different threads)
- of shared_work, thus the work is distributed equally over all threads.
- [note Worker-threads are stored in a static variable, dynamically adding/removing worker threads is not supported.]
- #include <boost/fiber/algo/shared_work.hpp>
- namespace boost {
- namespace fibers {
- namespace algo {
- class shared_work : public algorithm {
- shared_work();
- shared_work( bool suspend);
- virtual void awakened( context *) noexcept;
- virtual context * pick_next() noexcept;
- virtual bool has_ready_fibers() const noexcept;
- virtual void suspend_until( std::chrono::steady_clock::time_point const&) noexcept;
- virtual void notify() noexcept;
- };
- }}}
- [heading Constructor]
- shared_work();
- shared_work( bool suspend);
- [variablelist
- [[Effects:] [Constructs work-sharing scheduling algorithm.]]
- [[Throws:] [`system_error`]]
- [[Note:][If `suspend` is set to `true` (default is `false`), then the scheduler suspends if no ready fiber
- could be stolen. The scheduler will by woken up if a sleeping fiber times out or it was notified from remote
- (other thread or fiber scheduler).]]
- ]
- [member_heading shared_work..awakened]
- virtual void awakened( context * f) noexcept;
- [variablelist
- [[Effects:] [Enqueues fiber `f` onto the shared ready queue.]]
- [[Throws:] [Nothing.]]
- ]
- [member_heading shared_work..pick_next]
- virtual context * pick_next() noexcept;
- [variablelist
- [[Returns:] [the fiber at the head of the ready queue, or `nullptr` if the
- queue is empty.]]
- [[Throws:] [Nothing.]]
- [[Note:] [Placing ready fibers onto the tail of the shared queue, and returning them
- from the head of that queue, shares the thread between ready fibers in
- round-robin fashion.]]
- ]
- [member_heading shared_work..has_ready_fibers]
- virtual bool has_ready_fibers() const noexcept;
- [variablelist
- [[Returns:] [`true` if scheduler has fibers ready to run.]]
- [[Throws:] [Nothing.]]
- ]
- [member_heading shared_work..suspend_until]
- virtual void suspend_until( std::chrono::steady_clock::time_point const& abs_time) noexcept;
- [variablelist
- [[Effects:] [Informs `shared_work` that no ready fiber will be available until
- time-point `abs_time`. This implementation blocks in
- [@http://en.cppreference.com/w/cpp/thread/condition_variable/wait_until
- `std::condition_variable::wait_until()`].]]
- [[Throws:] [Nothing.]]
- ]
- [member_heading shared_work..notify]
- virtual void notify() noexcept = 0;
- [variablelist
- [[Effects:] [Wake up a pending call to [member_link
- shared_work..suspend_until], some fibers might be ready. This implementation
- wakes `suspend_until()` via
- [@http://en.cppreference.com/w/cpp/thread/condition_variable/notify_all
- `std::condition_variable::notify_all()`].]]
- [[Throws:] [Nothing.]]
- ]
- [heading Custom Scheduler Fiber Properties]
- A scheduler class directly derived from __algo__ can use any information
- available from [class_link context] to implement the `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>
- namespace boost {
- namespace fibers {
- class fiber_properties {
- public:
- fiber_properties( context *) noexcept;
- virtual ~fiber_properties();
- protected:
- void notify() noexcept;
- };
- }}
- [heading Constructor]
- fiber_properties( context * f) noexcept;
- [variablelist
- [[Effects:] [Constructs base-class component of custom subclass.]]
- [[Throws:] [Nothing.]]
- [[Note:] [Your subclass constructor must accept a `context*` and pass it
- to the base-class `fiber_properties` constructor.]]
- ]
- [member_heading fiber_properties..notify]
- void notify() noexcept;
- [variablelist
- [[Effects:] [Pass control to the custom [template_link
- algorithm_with_properties] subclass[s] [member_link
- algorithm_with_properties..property_change] method.]]
- [[Throws:] [Nothing.]]
- [[Note:] [A custom scheduler[s] [member_link
- algorithm_with_properties..pick_next] method might dynamically select
- from the ready fibers, or [member_link
- 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 algorithm_with_properties]
- A custom scheduler that depends on a custom properties class `PROPS` should be
- derived from `algorithm_with_properties<PROPS>`. `PROPS` should be
- derived from [class_link fiber_properties].
- #include <boost/fiber/algorithm.hpp>
- namespace boost {
- namespace fibers {
- namespace algo {
- template< typename PROPS >
- struct algorithm_with_properties {
- virtual void awakened( context *, PROPS &) noexcept = 0;
- virtual context * pick_next() noexcept;
- virtual bool has_ready_fibers() const noexcept;
- virtual void suspend_until( std::chrono::steady_clock::time_point const&) noexcept = 0;
- virtual void notify() noexcept = 0;
- PROPS & properties( context *) noexcept;
- virtual void property_change( context *, PROPS &) noexcept;
- virtual fiber_properties * new_properties( context *);
- };
- }}}
- [member_heading algorithm_with_properties..awakened]
- virtual void awakened( context * f, PROPS & properties) noexcept;
- [variablelist
- [[Effects:] [Informs the scheduler that fiber `f` is ready to run, like
- [member_link algorithm..awakened]. Passes the fiber[s] associated `PROPS`
- instance.]]
- [[Throws:] [Nothing.]]
- [[Note:] [An `algorithm_with_properties<>` subclass must override this
- method instead of `algorithm::awakened()`.]]
- ]
- [member_heading algorithm_with_properties..pick_next]
- virtual context * pick_next() noexcept;
- [variablelist
- [[Returns:] [the fiber which is to be resumed next, or `nullptr` if there is no
- ready fiber.]]
- [[Throws:] [Nothing.]]
- [[Note:] [same as [member_link algorithm..pick_next]]]
- ]
- [member_heading algorithm_with_properties..has_ready_fibers]
- virtual bool has_ready_fibers() const noexcept;
- [variablelist
- [[Returns:] [`true` if scheduler has fibers ready to run.]]
- [[Throws:] [Nothing.]]
- [[Note:] [same as [member_link algorithm..has_ready_fibers]]]
- ]
- [member_heading algorithm_with_properties..suspend_until]
- virtual void suspend_until( std::chrono::steady_clock::time_point const& abs_time) noexcept = 0;
- [variablelist
- [[Effects:] [Informs the scheduler that no fiber will be ready until
- time-point `abs_time`.]]
- [[Note:] [same as [member_link algorithm..suspend_until]]]
- ]
- [member_heading algorithm_with_properties..notify]
- virtual void notify() noexcept = 0;
- [variablelist
- [[Effects:] [Requests the scheduler to return from a pending call to
- [member_link algorithm_with_properties..suspend_until].]]
- [[Note:] [same as [member_link algorithm..notify]]]
- ]
- [member_heading algorithm_with_properties..properties]
- PROPS& properties( context * f) noexcept;
- [variablelist
- [[Returns:] [the `PROPS` instance associated with fiber `f`.]]
- [[Throws:] [Nothing.]]
- [[Note:] [The fiber[s] associated `PROPS` instance is already passed to
- [member_link algorithm_with_properties..awakened] and [member_link
- algorithm_with_properties..property_change]. However, every [class_link
- algorithm] subclass is expected to track a collection of ready
- [class_link context] instances. This method allows your custom scheduler
- to retrieve the [class_link fiber_properties] subclass instance for any
- `context` in its collection.]]
- ]
- [member_heading algorithm_with_properties..property_change]
- virtual void property_change( context * f, PROPS & properties) noexcept;
- [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.]]
- [[Throws:] [Nothing.]]
- [[Note:] [This method is only called when a custom [class_link
- fiber_properties] subclass explicitly calls [member_link
- fiber_properties..notify].]]
- ]
- [member_heading algorithm_with_properties..new_properties]
- virtual fiber_properties * new_properties( context * f);
- [variablelist
- [[Returns:] [A new instance of [class_link fiber_properties] subclass
- `PROPS`.]]
- [[Note:] [By default, `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`.]]
- ]
- [#context]
- [class_heading context]
- While you are free to treat `context*` as an opaque token, certain
- `context` members may be useful to a custom scheduler implementation.
- [#ready_queue_t]
- Of particular note is the fact that `context` contains a hook to participate
- in a [@http://www.boost.org/doc/libs/release/doc/html/intrusive/list.html
- `boost::intrusive::list`] [^typedef][,]ed as
- `boost::fibers::scheduler::ready_queue_t`. This hook is reserved for use by
- [class_link algorithm] implementations. (For instance, [class_link
- round_robin] contains a `ready_queue_t` instance to manage its ready fibers.)
- See [member_link context..ready_is_linked], [member_link context..ready_link],
- [member_link context..ready_unlink].
- Your `algorithm` implementation may use any container you desire to
- manage passed `context` instances. `ready_queue_t` avoids some of the overhead
- of typical STL containers.
- #include <boost/fiber/context.hpp>
- namespace boost {
- namespace fibers {
-
- enum class type {
- none = ``['unspecified]``,
- main_context = ``['unspecified]``, // fiber associated with thread's stack
- dispatcher_context = ``['unspecified]``, // special fiber for maintenance operations
- worker_context = ``['unspecified]``, // fiber not special to the library
- pinned_context = ``['unspecified]`` // fiber must not be migrated to another thread
- };
- class context {
- public:
- class id;
- static context * active() noexcept;
- context( context const&) = delete;
- context & operator=( context const&) = delete;
- id get_id() const noexcept;
- void detach() noexcept;
- void attach( context *) noexcept;
- bool is_context( type) const noexcept;
- bool is_terminated() const noexcept;
- bool ready_is_linked() const noexcept;
- bool remote_ready_is_linked() const noexcept;
- bool wait_is_linked() const noexcept;
- template< typename List >
- void ready_link( List &) noexcept;
- template< typename List >
- void remote_ready_link( List &) noexcept;
- template< typename List >
- void wait_link( List &) noexcept;
- void ready_unlink() noexcept;
- void remote_ready_unlink() noexcept;
- void wait_unlink() noexcept;
- void suspend() noexcept;
- void schedule( context *) noexcept;
- };
- bool operator<( context const& l, context const& r) noexcept;
- }}
- [static_member_heading context..active]
- static context * active() noexcept;
- [variablelist
- [[Returns:] [Pointer to instance of current fiber.]]
- [[Throws:] [Nothing]]
- ]
- [member_heading context..get_id]
- context::id get_id() const noexcept;
- [variablelist
- [[Returns:] [If `*this` refers to a fiber of execution, an instance of
- __fiber_id__ that represents that fiber. Otherwise returns a
- default-constructed __fiber_id__.]]
- [[Throws:] [Nothing]]
- [[See also:] [[member_link fiber..get_id]]]
- ]
- [member_heading context..attach]
- void attach( context * f) noexcept;
- [variablelist
- [[Precondition:] [`this->get_scheduler() == nullptr`]]
- [[Effects:] [Attach fiber `f` to scheduler running `*this`.]]
- [[Postcondition:] [`this->get_scheduler() != nullptr`]]
- [[Throws:] [Nothing]]
- [[Note:] [A typical call: `boost::fibers::context::active()->attach(f);`]]
- [[Note:] [`f` must not be the running fiber[s] context. It must not be
- __blocked__ or terminated. It must not be a `pinned_context`. It must be
- currently detached. It must not currently be linked into an [class_link
- algorithm] implementation[s] ready queue. Most of these conditions are
- implied by `f` being owned by an `algorithm` implementation: that is, it
- has been passed to [member_link algorithm..awakened] but has not yet
- been returned by [member_link algorithm..pick_next]. Typically a
- `pick_next()` implementation would call `attach()` with the `context*` it is
- about to return. It must first remove `f` from its ready queue. You should
- never pass a `pinned_context` to `attach()` because you should never have
- called its `detach()` method in the first place.]]
- ]
- [member_heading context..detach]
- void detach() noexcept;
- [variablelist
- [[Precondition:] [`(this->get_scheduler() != nullptr) && ! this->is_context(pinned_context)`]]
- [[Effects:] [Detach fiber `*this` from its scheduler running `*this`.]]
- [[Throws:] [Nothing]]
- [[Postcondition:] [`this->get_scheduler() == nullptr`]]
- [[Note:] [This method must be called on the thread with which the fiber is
- currently associated. `*this` must not be the running fiber[s] context. It
- must not be __blocked__ or terminated. It must not be a `pinned_context`. It
- must not be detached already. It must not already be linked into an [class_link
- algorithm] implementation[s] ready queue. Most of these conditions are
- implied by `*this` being passed to [member_link algorithm..awakened]; an
- `awakened()` implementation must, however, test for `pinned_context`. It must
- call `detach()` ['before] linking `*this` into its ready queue.]]
- [[Note:] [In particular, it is erroneous to attempt to migrate a fiber from
- one thread to another by calling both `detach()` and `attach()` in the
- [member_link algorithm..pick_next] method. `pick_next()` is called on
- the intended destination thread. `detach()` must be called on the fiber[s]
- original thread. You must call `detach()` in the corresponding `awakened()`
- method.]]
- [[Note:] [Unless you intend make a fiber available for potential migration to
- a different thread, you should call neither `detach()` nor `attach()` with its
- `context`.]]
- ]
- [member_heading context..is_context]
- bool is_context( type t) const noexcept;
- [variablelist
- [[Returns:] [`true` if `*this` is of the specified type.]]
- [[Throws:] [Nothing]]
- [[Note:] [`type::worker_context` here means any fiber not special to the
- library. For `type::main_context` the `context` is associated with the ["main]
- fiber of the thread: the one implicitly created by the thread itself, rather
- than one explicitly created by __boost_fiber__. For `type::dispatcher_context`
- the `context` is associated with a ["dispatching] fiber, responsible for
- dispatching awakened fibers to a scheduler[s] ready-queue. The ["dispatching]
- fiber is an implementation detail of the fiber manager. The context of the
- ["main] or ["dispatching] fiber [mdash] any fiber for which
- `is_context(pinned_context)` is `true` [mdash] must never be passed to
- [member_link context..detach].]]
- ]
- [member_heading context..is_terminated]
- bool is_terminated() const noexcept;
- [variablelist
- [[Returns:] [`true` if `*this` is no longer a valid context.]]
- [[Throws:] [Nothing]]
- [[Note:] [The `context` has returned from its fiber-function and is
- no longer considered a valid context.]]
- ]
- [member_heading context..ready_is_linked]
- bool ready_is_linked() const noexcept;
- [variablelist
- [[Returns:] [`true` if `*this` is stored in an [class_link algorithm]
- implementation[s] ready-queue.]]
- [[Throws:] [Nothing]]
- [[Note:] [Specifically, this method indicates whether [member_link
- context..ready_link] has been called on `*this`. `ready_is_linked()` has
- no information about participation in any other containers.]]
- ]
- [member_heading context..remote_ready_is_linked]
- bool remote_ready_is_linked() const noexcept;
- [variablelist
- [[Returns:] [`true` if `*this` is stored in the fiber manager[s]
- remote-ready-queue.]]
- [[Throws:] [Nothing]]
- [[Note:] [A `context` signaled as ready by another thread is first stored in
- the fiber manager[s] remote-ready-queue. This is the mechanism by which the
- fiber manager protects an [class_link algorithm] implementation from
- cross-thread [member_link algorithm..awakened] calls.]]
- ]
- [member_heading context..wait_is_linked]
- bool wait_is_linked() const noexcept;
- [variablelist
- [[Returns:] [`true` if `*this` is stored in the wait-queue of some
- synchronization object.]]
- [[Throws:] [Nothing]]
- [[Note:] [The `context` of a fiber waiting on a synchronization object (e.g.
- `mutex`, `condition_variable` etc.) is stored in the wait-queue of that
- synchronization object.]]
- ]
- [member_heading context..ready_link]
- template< typename List >
- void ready_link( List & lst) noexcept;
- [variablelist
- [[Effects:] [Stores `*this` in ready-queue `lst`.]]
- [[Throws:] [Nothing]]
- [[Note:] [Argument `lst` must be a doubly-linked list from
- __boost_intrusive__, e.g. an instance of
- `boost::fibers::scheduler::ready_queue_t`. Specifically, it must be a
- [@http://www.boost.org/doc/libs/release/doc/html/intrusive/list.html
- `boost::intrusive::list`] compatible with the `list_member_hook` stored in the
- `context` object.]]
- ]
- [member_heading context..remote_ready_link]
- template< typename List >
- void remote_ready_link( List & lst) noexcept;
- [variablelist
- [[Effects:] [Stores `*this` in remote-ready-queue `lst`.]]
- [[Throws:] [Nothing]]
- [[Note:] [Argument `lst` must be a doubly-linked list from
- __boost_intrusive__.]]
- ]
- [member_heading context..wait_link]
- template< typename List >
- void wait_link( List & lst) noexcept;
- [variablelist
- [[Effects:] [Stores `*this` in wait-queue `lst`.]]
- [[Throws:] [Nothing]]
- [[Note:] [Argument `lst` must be a doubly-linked list from
- __boost_intrusive__.]]
- ]
- [member_heading context..ready_unlink]
- void ready_unlink() noexcept;
- [variablelist
- [[Effects:] [Removes `*this` from ready-queue: undoes the effect of
- [member_link context..ready_link].]]
- [[Throws:] [Nothing]]
- ]
- [member_heading context..remote_ready_unlink]
- void remote_ready_unlink() noexcept;
- [variablelist
- [[Effects:] [Removes `*this` from remote-ready-queue.]]
- [[Throws:] [Nothing]]
- ]
- [member_heading context..wait_unlink]
- void wait_unlink() noexcept;
- [variablelist
- [[Effects:] [Removes `*this` from wait-queue.]]
- [[Throws:] [Nothing]]
- ]
- [member_heading context..suspend]
- void suspend() noexcept;
- [variablelist
- [[Effects:] [Suspends the running fiber (the fiber associated with `*this`)
- until some other fiber passes `this` to [member_link context..schedule].
- `*this` is marked as not-ready, and control passes to the scheduler to select
- another fiber to run.]]
- [[Throws:] [Nothing]]
- [[Note:] [This is a low-level API potentially useful for integration with
- other frameworks. It is not intended to be directly invoked by a typical
- application program.]]
- [[Note:] [The burden is on the caller to arrange for a call to `schedule()`
- with a pointer to `this` at some future time.]]
- ]
- [member_heading context..schedule]
- void schedule( context * ctx ) noexcept;
- [variablelist
- [[Effects:] [Mark the fiber associated with context `*ctx` as being ready to
- run. This does not immediately resume that fiber; rather it passes the fiber
- to the scheduler for subsequent resumption. If the scheduler is idle (has not
- returned from a call to [member_link algorithm..suspend_until]),
- [member_link algorithm..notify] is called to wake it up.]]
- [[Throws:] [Nothing]]
- [[Note:] [This is a low-level API potentially useful for integration with
- other frameworks. It is not intended to be directly invoked by a typical
- application program.]]
- [[Note:] [It is explicitly supported to call `schedule(ctx)` from a thread
- other than the one on which `*ctx` is currently suspended. The corresponding
- fiber will be resumed on its original thread in due course.]]
- [/[[Note:] [See [member_link context..migrate] for a way to migrate the
- suspended thread to the thread calling `schedule()`.]]]
- ]
- [hding context_less..Non-member function [`operator<()]]
- bool operator<( context const& l, context const& r) noexcept;
- [variablelist
- [[Returns:] [`true` if `l.get_id() < r.get_id()` is `true`, `false`
- otherwise.]]
- [[Throws:] [Nothing.]]
- ]
- [endsect]
|