]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/fiber/doc/scheduling.qbk
add subtree-ish sources for 12.0.3
[ceph.git] / ceph / src / boost / libs / fiber / doc / scheduling.qbk
1 [/
2 Copyright Oliver Kowalke 2013.
3 Distributed under the Boost Software License, Version 1.0.
4 (See accompanying file LICENSE_1_0.txt or copy at
5 http://www.boost.org/LICENSE_1_0.txt
6 ]
7
8 [#scheduling]
9 [section:scheduling Scheduling]
10
11 The fibers in a thread are coordinated by a fiber manager. Fibers trade
12 control cooperatively, rather than preemptively: the currently-running fiber
13 retains control until it invokes some operation that passes control to the
14 manager. Each time a fiber suspends (or yields), the fiber manager consults a
15 scheduler to determine which fiber will run next.
16
17 __boost_fiber__ provides the fiber manager, but the scheduler is a
18 customization point. (See [link custom Customization].)
19
20 Each thread has its own scheduler. Different threads in a process may use
21 different schedulers. By default, __boost_fiber__ implicitly instantiates
22 [class_link round_robin] as the scheduler for each thread.
23
24 You are explicitly permitted to code your own __algo__ subclass. For the most
25 part, your `algorithm` subclass need not defend against cross-thread
26 calls: the fiber manager intercepts and defers such calls. Most
27 `algorithm` methods are only ever directly called from the thread whose
28 fibers it is managing [mdash] with exceptions as documented below.
29
30 Your `algorithm` subclass is engaged on a particular thread by calling
31 [function_link use_scheduling_algorithm]:
32
33 void thread_fn() {
34 boost::fibers::use_scheduling_algorithm< my_fiber_scheduler >();
35 ...
36 }
37
38 A scheduler class must implement interface __algo__. __boost_fiber__ provides
39 one scheduler: [class_link round_robin].
40
41
42 [class_heading algorithm]
43
44 `algorithm` is the abstract base class defining the interface that a
45 fiber scheduler must implement.
46
47 #include <boost/fiber/algo/algorithm.hpp>
48
49 namespace boost {
50 namespace fibers {
51 namespace algo {
52
53 struct algorithm {
54 virtual ~algorithm();
55
56 virtual void awakened( context *) noexcept = 0;
57
58 virtual context * pick_next() noexcept = 0;
59
60 virtual bool has_ready_fibers() const noexcept = 0;
61
62 virtual void suspend_until( std::chrono::steady_clock::time_point const&) noexcept = 0;
63
64 virtual void notify() noexcept = 0;
65 };
66
67 }}}
68
69 [member_heading algorithm..awakened]
70
71 virtual void awakened( context * f) noexcept = 0;
72
73 [variablelist
74 [[Effects:] [Informs the scheduler that fiber `f` is ready to run. Fiber `f`
75 might be newly launched, or it might have been blocked but has just been
76 awakened, or it might have called [ns_function_link this_fiber..yield].]]
77 [[Note:] [This method advises the scheduler to add fiber `f` to its collection
78 of fibers ready to run. A typical scheduler implementation places `f` into a
79 queue.]]
80 [[See also:] [[class_link round_robin]]]
81 ]
82
83 [member_heading algorithm..pick_next]
84
85 virtual context * pick_next() noexcept = 0;
86
87 [variablelist
88 [[Returns:] [the fiber which is to be resumed next, or `nullptr` if there is no
89 ready fiber.]]
90 [[Note:] [This is where the scheduler actually specifies the fiber which is to
91 run next. A typical scheduler implementation chooses the head of the ready
92 queue.]]
93 [[See also:] [[class_link round_robin]]]
94 ]
95
96 [member_heading algorithm..has_ready_fibers]
97
98 virtual bool has_ready_fibers() const noexcept = 0;
99
100 [variablelist
101 [[Returns:] [`true` if scheduler has fibers ready to run.]]
102 ]
103
104 [member_heading algorithm..suspend_until]
105
106 virtual void suspend_until( std::chrono::steady_clock::time_point const& abs_time) noexcept = 0;
107
108 [variablelist
109 [[Effects:] [Informs the scheduler that no fiber will be ready until
110 time-point `abs_time`.]]
111 [[Note:] [This method allows a custom scheduler to yield control to the
112 containing environment in whatever way makes sense. The fiber manager is
113 stating that `suspend_until()` need not return until `abs_time` [mdash] or
114 [member_link algorithm..notify] is called [mdash] whichever comes first.
115 The interaction with `notify()` means that, for instance, calling
116 [@http://en.cppreference.com/w/cpp/thread/sleep_until
117 `std::this_thread::sleep_until(abs_time)`] would be too simplistic.
118 [member_link round_robin..suspend_until] uses a
119 [@http://en.cppreference.com/w/cpp/thread/condition_variable
120 `std::condition_variable`] to coordinate with [member_link
121 round_robin..notify].]]
122 [[Note:] [Given that `notify()` might be called from another thread, your
123 `suspend_until()` implementation [mdash] like the rest of your
124 `algorithm` implementation [mdash] must guard any data it shares with
125 your `notify()` implementation.]]
126 ]
127
128 [member_heading algorithm..notify]
129
130 virtual void notify() noexcept = 0;
131
132 [variablelist
133 [[Effects:] [Requests the scheduler to return from a pending call to
134 [member_link algorithm..suspend_until].]]
135 [[Note:] [Alone among the `algorithm` methods, `notify()` may be called
136 from another thread. Your `notify()` implementation must guard any data it
137 shares with the rest of your `algorithm` implementation.]]
138 ]
139
140 [class_heading round_robin]
141
142 This class implements __algo__, scheduling fibers in round-robin fashion.
143
144 #include <boost/fiber/algo/round_robin.hpp>
145
146 namespace boost {
147 namespace fibers {
148 namespace algo {
149
150 class round_robin : public algorithm {
151 virtual void awakened( context *) noexcept;
152
153 virtual context * pick_next() noexcept;
154
155 virtual bool has_ready_fibers() const noexcept;
156
157 virtual void suspend_until( std::chrono::steady_clock::time_point const&) noexcept;
158
159 virtual void notify() noexcept;
160 };
161
162 }}}
163
164 [member_heading round_robin..awakened]
165
166 virtual void awakened( context * f) noexcept;
167
168 [variablelist
169 [[Effects:] [Enqueues fiber `f` onto a ready queue.]]
170 [[Throws:] [Nothing.]]
171 ]
172
173 [member_heading round_robin..pick_next]
174
175 virtual context * pick_next() noexcept;
176
177 [variablelist
178 [[Returns:] [the fiber at the head of the ready queue, or `nullptr` if the
179 queue is empty.]]
180 [[Throws:] [Nothing.]]
181 [[Note:] [Placing ready fibers onto the tail of a queue, and returning them
182 from the head of that queue, shares the thread between ready fibers in
183 round-robin fashion.]]
184 ]
185
186 [member_heading round_robin..has_ready_fibers]
187
188 virtual bool has_ready_fibers() const noexcept;
189
190 [variablelist
191 [[Returns:] [`true` if scheduler has fibers ready to run.]]
192 [[Throws:] [Nothing.]]
193 ]
194
195 [member_heading round_robin..suspend_until]
196
197 virtual void suspend_until( std::chrono::steady_clock::time_point const& abs_time) noexcept;
198
199 [variablelist
200 [[Effects:] [Informs `round_robin` that no ready fiber will be available until
201 time-point `abs_time`. This implementation blocks in
202 [@http://en.cppreference.com/w/cpp/thread/condition_variable/wait_until
203 `std::condition_variable::wait_until()`].]]
204 [[Throws:] [Nothing.]]
205 ]
206
207 [member_heading round_robin..notify]
208
209 virtual void notify() noexcept = 0;
210
211 [variablelist
212 [[Effects:] [Wake up a pending call to [member_link
213 round_robin..suspend_until], some fibers might be ready. This implementation
214 wakes `suspend_until()` via
215 [@http://en.cppreference.com/w/cpp/thread/condition_variable/notify_all
216 `std::condition_variable::notify_all()`].]]
217 [[Throws:] [Nothing.]]
218 ]
219
220
221 [class_heading shared_work]
222
223 This class implements __algo__; ready fibers are shared between all instances (running on different threads)
224 of shared_work.
225
226 #include <boost/fiber/algo/shared_work.hpp>
227
228 namespace boost {
229 namespace fibers {
230 namespace algo {
231
232 class shared_work : public algorithm {
233 virtual void awakened( context *) noexcept;
234
235 virtual context * pick_next() noexcept;
236
237 virtual bool has_ready_fibers() const noexcept;
238
239 virtual void suspend_until( std::chrono::steady_clock::time_point const&) noexcept;
240
241 virtual void notify() noexcept;
242 };
243
244 }}}
245
246 [member_heading shared_work..awakened]
247
248 virtual void awakened( context * f) noexcept;
249
250 [variablelist
251 [[Effects:] [Enqueues fiber `f` onto the shared ready queue.]]
252 [[Throws:] [Nothing.]]
253 ]
254
255 [member_heading shared_work..pick_next]
256
257 virtual context * pick_next() noexcept;
258
259 [variablelist
260 [[Returns:] [the fiber at the head of the ready queue, or `nullptr` if the
261 queue is empty.]]
262 [[Throws:] [Nothing.]]
263 [[Note:] [Placing ready fibers onto the tail of the shared queue, and returning them
264 from the head of that queue, shares the thread between ready fibers in
265 round-robin fashion.]]
266 ]
267
268 [member_heading shared_work..has_ready_fibers]
269
270 virtual bool has_ready_fibers() const noexcept;
271
272 [variablelist
273 [[Returns:] [`true` if scheduler has fibers ready to run.]]
274 [[Throws:] [Nothing.]]
275 ]
276
277 [member_heading shared_work..suspend_until]
278
279 virtual void suspend_until( std::chrono::steady_clock::time_point const& abs_time) noexcept;
280
281 [variablelist
282 [[Effects:] [Informs `shared_work` that no ready fiber will be available until
283 time-point `abs_time`. This implementation blocks in
284 [@http://en.cppreference.com/w/cpp/thread/condition_variable/wait_until
285 `std::condition_variable::wait_until()`].]]
286 [[Throws:] [Nothing.]]
287 ]
288
289 [member_heading shared_work..notify]
290
291 virtual void notify() noexcept = 0;
292
293 [variablelist
294 [[Effects:] [Wake up a pending call to [member_link
295 shared_work..suspend_until], some fibers might be ready. This implementation
296 wakes `suspend_until()` via
297 [@http://en.cppreference.com/w/cpp/thread/condition_variable/notify_all
298 `std::condition_variable::notify_all()`].]]
299 [[Throws:] [Nothing.]]
300 ]
301
302
303 [heading Custom Scheduler Fiber Properties]
304
305 A scheduler class directly derived from __algo__ can use any information
306 available from [class_link context] to implement the `algorithm`
307 interface. But a custom scheduler might need to track additional properties
308 for a fiber. For instance, a priority-based scheduler would need to track a
309 fiber[s] priority.
310
311 __boost_fiber__ provides a mechanism by which your custom scheduler can
312 associate custom properties with each fiber.
313
314 [class_heading fiber_properties]
315
316 A custom fiber properties class must be derived from `fiber_properties`.
317
318 #include <boost/fiber/properties.hpp>
319
320 namespace boost {
321 namespace fibers {
322
323 class fiber_properties {
324 public:
325 fiber_properties( context *) noexcept;
326
327 virtual ~fiber_properties();
328
329 protected:
330 void notify() noexcept;
331 };
332
333 }}
334
335 [heading Constructor]
336
337 fiber_properties( context * f) noexcept;
338
339 [variablelist
340 [[Effects:] [Constructs base-class component of custom subclass.]]
341 [[Throws:] [Nothing.]]
342 [[Note:] [Your subclass constructor must accept a `context*` and pass it
343 to the base-class `fiber_properties` constructor.]]
344 ]
345
346 [member_heading fiber_properties..notify]
347
348 void notify() noexcept;
349
350 [variablelist
351 [[Effects:] [Pass control to the custom [template_link
352 algorithm_with_properties] subclass[s] [member_link
353 algorithm_with_properties..property_change] method.]]
354 [[Throws:] [Nothing.]]
355 [[Note:] [A custom scheduler[s] [member_link
356 algorithm_with_properties..pick_next] method might dynamically select
357 from the ready fibers, or [member_link
358 algorithm_with_properties..awakened] might instead insert each ready
359 fiber into some form of ready queue for `pick_next()`. In the latter case, if
360 application code modifies a fiber property (e.g. priority) that should affect
361 that fiber[s] relationship to other ready fibers, the custom scheduler must be
362 given the opportunity to reorder its ready queue. The custom property subclass
363 should implement an access method to modify such a property; that access
364 method should call `notify()` once the new property value has been stored.
365 This passes control to the custom scheduler[s] `property_change()` method,
366 allowing the custom scheduler to reorder its ready queue appropriately. Use at
367 your discretion. Of course, if you define a property which does not affect the
368 behavior of the `pick_next()` method, you need not call `notify()` when that
369 property is modified.]]
370 ]
371
372 [template_heading algorithm_with_properties]
373
374 A custom scheduler that depends on a custom properties class `PROPS` should be
375 derived from `algorithm_with_properties<PROPS>`. `PROPS` should be
376 derived from [class_link fiber_properties].
377
378 #include <boost/fiber/algorithm.hpp>
379
380 namespace boost {
381 namespace fibers {
382 namespace algo {
383
384 template< typename PROPS >
385 struct algorithm_with_properties {
386 virtual void awakened( context *, PROPS &) noexcept = 0;
387
388 virtual context * pick_next() noexcept;
389
390 virtual bool has_ready_fibers() const noexcept;
391
392 virtual void suspend_until( std::chrono::steady_clock::time_point const&) noexcept = 0;
393
394 virtual void notify() noexcept = 0;
395
396 PROPS & properties( context *) noexcept;
397
398 virtual void property_change( context *, PROPS &) noexcept;
399
400 virtual fiber_properties * new_properties( context *);
401 };
402
403 }}}
404
405 [member_heading algorithm_with_properties..awakened]
406
407 virtual void awakened( context * f, PROPS & properties) noexcept;
408
409 [variablelist
410 [[Effects:] [Informs the scheduler that fiber `f` is ready to run, like
411 [member_link algorithm..awakened]. Passes the fiber[s] associated `PROPS`
412 instance.]]
413 [[Throws:] [Nothing.]]
414 [[Note:] [An `algorithm_with_properties<>` subclass must override this
415 method instead of `algorithm::awakened()`.]]
416 ]
417
418 [member_heading algorithm_with_properties..pick_next]
419
420 virtual context * pick_next() noexcept;
421
422 [variablelist
423 [[Returns:] [the fiber which is to be resumed next, or `nullptr` if there is no
424 ready fiber.]]
425 [[Throws:] [Nothing.]]
426 [[Note:] [same as [member_link algorithm..pick_next]]]
427 ]
428
429 [member_heading algorithm_with_properties..has_ready_fibers]
430
431 virtual bool has_ready_fibers() const noexcept;
432
433 [variablelist
434 [[Returns:] [`true` if scheduler has fibers ready to run.]]
435 [[Throws:] [Nothing.]]
436 [[Note:] [same as [member_link algorithm..has_ready_fibers]]]
437 ]
438
439 [member_heading algorithm_with_properties..suspend_until]
440
441 virtual void suspend_until( std::chrono::steady_clock::time_point const& abs_time) noexcept = 0;
442
443 [variablelist
444 [[Effects:] [Informs the scheduler that no fiber will be ready until
445 time-point `abs_time`.]]
446 [[Note:] [same as [member_link algorithm..suspend_until]]]
447 ]
448
449 [member_heading algorithm_with_properties..notify]
450
451 virtual void notify() noexcept = 0;
452
453 [variablelist
454 [[Effects:] [Requests the scheduler to return from a pending call to
455 [member_link algorithm_with_properties..suspend_until].]]
456 [[Note:] [same as [member_link algorithm..notify]]]
457 ]
458
459 [member_heading algorithm_with_properties..properties]
460
461 PROPS& properties( context * f) noexcept;
462
463 [variablelist
464 [[Returns:] [the `PROPS` instance associated with fiber `f`.]]
465 [[Throws:] [Nothing.]]
466 [[Note:] [The fiber[s] associated `PROPS` instance is already passed to
467 [member_link algorithm_with_properties..awakened] and [member_link
468 algorithm_with_properties..property_change]. However, every [class_link
469 algorithm] subclass is expected to track a collection of ready
470 [class_link context] instances. This method allows your custom scheduler
471 to retrieve the [class_link fiber_properties] subclass instance for any
472 `context` in its collection.]]
473 ]
474
475 [member_heading algorithm_with_properties..property_change]
476
477 virtual void property_change( context * f, PROPS & properties) noexcept;
478
479 [variablelist
480 [[Effects:] [Notify the custom scheduler of a possibly-relevant change to a
481 property belonging to fiber `f`. `properties` contains the new values of
482 all relevant properties.]]
483 [[Throws:] [Nothing.]]
484 [[Note:] [This method is only called when a custom [class_link
485 fiber_properties] subclass explicitly calls [member_link
486 fiber_properties..notify].]]
487 ]
488
489 [member_heading algorithm_with_properties..new_properties]
490
491 virtual fiber_properties * new_properties( context * f);
492
493 [variablelist
494 [[Returns:] [A new instance of [class_link fiber_properties] subclass
495 `PROPS`.]]
496 [[Note:] [By default, `algorithm_with_properties<>::new_properties()`
497 simply returns `new PROPS(f)`, placing the `PROPS` instance on the heap.
498 Override this method to allocate `PROPS` some other way. The returned
499 `fiber_properties` pointer must point to the `PROPS` instance to be associated
500 with fiber `f`.]]
501 ]
502
503 [#context]
504 [class_heading context]
505
506 While you are free to treat `context*` as an opaque token, certain
507 `context` members may be useful to a custom scheduler implementation.
508
509 [#ready_queue_t]
510 Of particular note is the fact that `context` contains a hook to participate
511 in a [@http://www.boost.org/doc/libs/release/doc/html/intrusive/list.html
512 `boost::intrusive::list`] [^typedef][,]ed as
513 `boost::fibers::scheduler::ready_queue_t`. This hook is reserved for use by
514 [class_link algorithm] implementations. (For instance, [class_link
515 round_robin] contains a `ready_queue_t` instance to manage its ready fibers.)
516 See [member_link context..ready_is_linked], [member_link context..ready_link],
517 [member_link context..ready_unlink].
518
519 Your `algorithm` implementation may use any container you desire to
520 manage passed `context` instances. `ready_queue_t` avoids some of the overhead
521 of typical STL containers.
522
523 #include <boost/fiber/context.hpp>
524
525 namespace boost {
526 namespace fibers {
527
528 enum class type {
529 none = ``['unspecified]``,
530 main_context = ``['unspecified]``, // fiber associated with thread's stack
531 dispatcher_context = ``['unspecified]``, // special fiber for maintenance operations
532 worker_context = ``['unspecified]``, // fiber not special to the library
533 pinned_context = ``['unspecified]`` // fiber must not be migrated to another thread
534 };
535
536 class context {
537 public:
538 class id;
539
540 static context * active() noexcept;
541
542 context( context const&) = delete;
543 context & operator=( context const&) = delete;
544
545 id get_id() const noexcept;
546
547 void detach() noexcept;
548 void attach( context *) noexcept;
549
550 bool is_context( type) const noexcept;
551
552 bool is_terminated() const noexcept;
553
554 bool ready_is_linked() const noexcept;
555 bool remote_ready_is_linked() const noexcept;
556 bool wait_is_linked() const noexcept;
557
558 template< typename List >
559 void ready_link( List &) noexcept;
560 template< typename List >
561 void remote_ready_link( List &) noexcept;
562 template< typename List >
563 void wait_link( List &) noexcept;
564
565 void ready_unlink() noexcept;
566 void remote_ready_unlink() noexcept;
567 void wait_unlink() noexcept;
568
569 void suspend() noexcept;
570 void set_ready( context *) noexcept;
571 };
572
573 bool operator<( context const& l, context const& r) noexcept;
574
575 }}
576
577 [static_member_heading context..active]
578
579 static context * active() noexcept;
580
581 [variablelist
582 [[Returns:] [Pointer to instance of current fiber.]]
583 [[Throws:] [Nothing]]
584 ]
585
586 [member_heading context..get_id]
587
588 context::id get_id() const noexcept;
589
590 [variablelist
591 [[Returns:] [If `*this` refers to a fiber of execution, an instance of
592 __fiber_id__ that represents that fiber. Otherwise returns a
593 default-constructed __fiber_id__.]]
594 [[Throws:] [Nothing]]
595 [[See also:] [[member_link fiber..get_id]]]
596 ]
597
598 [member_heading context..attach]
599
600 void attach( context * f) noexcept;
601
602 [variablelist
603 [[Precondition:] [`this->get_scheduler() == nullptr`]]
604 [[Effects:] [Attach fiber `f` to scheduler running `*this`.]]
605 [[Postcondition:] [`this->get_scheduler() != nullptr`]]
606 [[Throws:] [Nothing]]
607 [[Note:] [A typical call: `boost::fibers::context::active()->attach(f);`]]
608 [[Note:] [`f` must not be the running fiber[s] context. It must not be
609 __blocked__ or terminated. It must not be a `pinned_context`. It must be
610 currently detached. It must not currently be linked into an [class_link
611 algorithm] implementation[s] ready queue. Most of these conditions are
612 implied by `f` being owned by an `algorithm` implementation: that is, it
613 has been passed to [member_link algorithm..awakened] but has not yet
614 been returned by [member_link algorithm..pick_next]. Typically a
615 `pick_next()` implementation would call `attach()` with the `context*` it is
616 about to return. It must first remove `f` from its ready queue. You should
617 never pass a `pinned_context` to `attach()` because you should never have
618 called its `detach()` method in the first place.]]
619 ]
620
621 [member_heading context..detach]
622
623 void detach() noexcept;
624
625 [variablelist
626 [[Precondition:] [`(this->get_scheduler() != nullptr) && ! this->is_context(pinned_context)`]]
627 [[Effects:] [Detach fiber `*this` from its scheduler running `*this`.]]
628 [[Throws:] [Nothing]]
629 [[Postcondition:] [`this->get_scheduler() == nullptr`]]
630 [[Note:] [This method must be called on the thread with which the fiber is
631 currently associated. `*this` must not be the running fiber[s] context. It
632 must not be __blocked__ or terminated. It must not be a `pinned_context`. It
633 must not be detached already. It must not already be linked into an [class_link
634 algorithm] implementation[s] ready queue. Most of these conditions are
635 implied by `*this` being passed to [member_link algorithm..awakened]; an
636 `awakened()` implementation must, however, test for `pinned_context`. It must
637 call `detach()` ['before] linking `*this` into its ready queue.]]
638 [[Note:] [In particular, it is erroneous to attempt to migrate a fiber from
639 one thread to another by calling both `detach()` and `attach()` in the
640 [member_link algorithm..pick_next] method. `pick_next()` is called on
641 the intended destination thread. `detach()` must be called on the fiber[s]
642 original thread. You must call `detach()` in the corresponding `awakened()`
643 method.]]
644 [[Note:] [Unless you intend make a fiber available for potential migration to
645 a different thread, you should call neither `detach()` nor `attach()` with its
646 `context`.]]
647 ]
648
649 [member_heading context..is_context]
650
651 bool is_context( type t) const noexcept;
652
653 [variablelist
654 [[Returns:] [`true` if `*this` is of the specified type.]]
655 [[Throws:] [Nothing]]
656 [[Note:] [`type::worker_context` here means any fiber not special to the
657 library. For `type::main_context` the `context` is associated with the ["main]
658 fiber of the thread: the one implicitly created by the thread itself, rather
659 than one explicitly created by __boost_fiber__. For `type::dispatcher_context`
660 the `context` is associated with a ["dispatching] fiber, responsible for
661 dispatching awakened fibers to a scheduler[s] ready-queue. The ["dispatching]
662 fiber is an implementation detail of the fiber manager. The context of the
663 ["main] or ["dispatching] fiber [mdash] any fiber for which
664 `is_context(pinned_context)` is `true` [mdash] must never be passed to
665 [member_link context..detach].]]
666 ]
667
668 [member_heading context..is_terminated]
669
670 bool is_terminated() const noexcept;
671
672 [variablelist
673 [[Returns:] [`true` if `*this` is no longer a valid context.]]
674 [[Throws:] [Nothing]]
675 [[Note:] [The `context` has returned from its fiber-function and is
676 no longer considered a valid context.]]
677 ]
678
679 [member_heading context..ready_is_linked]
680
681 bool ready_is_linked() const noexcept;
682
683 [variablelist
684 [[Returns:] [`true` if `*this` is stored in an [class_link algorithm]
685 implementation[s] ready-queue.]]
686 [[Throws:] [Nothing]]
687 [[Note:] [Specifically, this method indicates whether [member_link
688 context..ready_link] has been called on `*this`. `ready_is_linked()` has
689 no information about participation in any other containers.]]
690 ]
691
692 [member_heading context..remote_ready_is_linked]
693
694 bool remote_ready_is_linked() const noexcept;
695
696 [variablelist
697 [[Returns:] [`true` if `*this` is stored in the fiber manager[s]
698 remote-ready-queue.]]
699 [[Throws:] [Nothing]]
700 [[Note:] [A `context` signaled as ready by another thread is first stored in
701 the fiber manager[s] remote-ready-queue. This is the mechanism by which the
702 fiber manager protects an [class_link algorithm] implementation from
703 cross-thread [member_link algorithm..awakened] calls.]]
704 ]
705
706 [member_heading context..wait_is_linked]
707
708 bool wait_is_linked() const noexcept;
709
710 [variablelist
711 [[Returns:] [`true` if `*this` is stored in the wait-queue of some
712 synchronization object.]]
713 [[Throws:] [Nothing]]
714 [[Note:] [The `context` of a fiber waiting on a synchronization object (e.g.
715 `mutex`, `condition_variable` etc.) is stored in the wait-queue of that
716 synchronization object.]]
717 ]
718
719 [member_heading context..ready_link]
720
721 template< typename List >
722 void ready_link( List & lst) noexcept;
723
724 [variablelist
725 [[Effects:] [Stores `*this` in ready-queue `lst`.]]
726 [[Throws:] [Nothing]]
727 [[Note:] [Argument `lst` must be a doubly-linked list from
728 __boost_intrusive__, e.g. an instance of
729 `boost::fibers::scheduler::ready_queue_t`. Specifically, it must be a
730 [@http://www.boost.org/doc/libs/release/doc/html/intrusive/list.html
731 `boost::intrusive::list`] compatible with the `list_member_hook` stored in the
732 `context` object.]]
733 ]
734
735 [member_heading context..remote_ready_link]
736
737 template< typename List >
738 void remote_ready_link( List & lst) noexcept;
739
740 [variablelist
741 [[Effects:] [Stores `*this` in remote-ready-queue `lst`.]]
742 [[Throws:] [Nothing]]
743 [[Note:] [Argument `lst` must be a doubly-linked list from
744 __boost_intrusive__.]]
745 ]
746
747 [member_heading context..wait_link]
748
749 template< typename List >
750 void wait_link( List & lst) noexcept;
751
752 [variablelist
753 [[Effects:] [Stores `*this` in wait-queue `lst`.]]
754 [[Throws:] [Nothing]]
755 [[Note:] [Argument `lst` must be a doubly-linked list from
756 __boost_intrusive__.]]
757 ]
758
759 [member_heading context..ready_unlink]
760
761 void ready_unlink() noexcept;
762
763 [variablelist
764 [[Effects:] [Removes `*this` from ready-queue: undoes the effect of
765 [member_link context..ready_link].]]
766 [[Throws:] [Nothing]]
767 ]
768
769 [member_heading context..remote_ready_unlink]
770
771 void remote_ready_unlink() noexcept;
772
773 [variablelist
774 [[Effects:] [Removes `*this` from remote-ready-queue.]]
775 [[Throws:] [Nothing]]
776 ]
777
778 [member_heading context..wait_unlink]
779
780 void wait_unlink() noexcept;
781
782 [variablelist
783 [[Effects:] [Removes `*this` from wait-queue.]]
784 [[Throws:] [Nothing]]
785 ]
786
787 [member_heading context..suspend]
788
789 void suspend() noexcept;
790
791 [variablelist
792 [[Effects:] [Suspends the running fiber (the fiber associated with `*this`)
793 until some other fiber passes `this` to [member_link context..set_ready].
794 `*this` is marked as not-ready, and control passes to the scheduler to select
795 another fiber to run.]]
796 [[Throws:] [Nothing]]
797 [[Note:] [This is a low-level API potentially useful for integration with
798 other frameworks. It is not intended to be directly invoked by a typical
799 application program.]]
800 [[Note:] [The burden is on the caller to arrange for a call to `set_ready()`
801 with a pointer to `this` at some future time.]]
802 ]
803
804 [member_heading context..set_ready]
805
806 void set_ready( context * ctx ) noexcept;
807
808 [variablelist
809 [[Effects:] [Mark the fiber associated with context `*ctx` as being ready to
810 run. This does not immediately resume that fiber; rather it passes the fiber
811 to the scheduler for subsequent resumption. If the scheduler is idle (has not
812 returned from a call to [member_link algorithm..suspend_until]),
813 [member_link algorithm..notify] is called to wake it up.]]
814 [[Throws:] [Nothing]]
815 [[Note:] [This is a low-level API potentially useful for integration with
816 other frameworks. It is not intended to be directly invoked by a typical
817 application program.]]
818 [[Note:] [It is explicitly supported to call `set_ready(ctx)` from a thread
819 other than the one on which `*ctx` is currently suspended. The corresponding
820 fiber will be resumed on its original thread in due course.]]
821 [/[[Note:] [See [member_link context..migrate] for a way to migrate the
822 suspended thread to the thread calling `set_ready()`.]]]
823 ]
824
825 [hding context_less..Non-member function [`operator<()]]
826
827 bool operator<( context const& l, context const& r) noexcept;
828
829 [variablelist
830 [[Returns:] [`true` if `l.get_id() < r.get_id()` is `true`, `false`
831 otherwise.]]
832 [[Throws:] [Nothing.]]
833 ]
834
835
836 [endsect]