2 (C) Copyright 2007-8 Anthony Williams.
3 (C) Copyright 2011-12 Vicente J. Botet Escriba.
4 (C) Copyright 2013 Oliver Kowalke.
5 Distributed under the Boost Software License, Version 1.0.
6 (See accompanying file LICENSE_1_0.txt or copy at
7 http://www.boost.org/LICENSE_1_0.txt).
10 [section:fiber_mgmt Fiber management]
14 #include <boost/fiber/all.hpp>
20 bool operator<( fiber const& l, fiber const& r) noexcept;
21 void swap( fiber & l, fiber & r) noexcept;
23 template< typename SchedAlgo, typename ... Args >
24 void use_scheduling_algorithm( Args && ... args);
25 bool has_ready_fibers();
30 template< typename PROPS >
31 struct algorithm_with_properties;
33 class shared_round_robin;
37 namespace this_fiber {
39 fibers::id get_id() noexcept;
41 template< typename Clock, typename Duration >
42 void sleep_until( std::chrono::time_point< Clock, Duration > const& abs_time)
43 template< typename Rep, typename Period >
44 void sleep_for( std::chrono::duration< Rep, Period > const& rel_time);
45 template< typename PROPS >
53 Each __fiber__ represents a micro-thread which will be launched and managed
54 cooperatively by a scheduler. Objects of type __fiber__ are move-only.
56 boost::fibers::fiber f1; // not-a-fiber
59 boost::fibers::fiber f2( some_fn);
61 f1 = std::move( f2); // f2 moved to f1
67 A new fiber is launched by passing an object of a callable type that can be
68 invoked with no parameters.
69 If the object must not be copied or moved, then ['std::ref] can be used to
70 pass in a reference to the function object. In this case, the user must ensure
71 that the referenced object outlives the newly-created fiber.
77 boost::fibers::fiber copies_are_safe() {
79 return boost::fibers::fiber( x);
80 } // x is destroyed, but the newly-created fiber has a copy, so this is OK
82 boost::fibers::fiber oops() {
84 return boost::fibers::fiber( std::ref( x) );
85 } // x is destroyed, but the newly-created fiber still has a reference
86 // this leads to undefined behaviour
88 The spawned __fiber__ does not immediately start running. It is enqueued in
89 the list of ready-to-run fibers, and will run when the scheduler gets around
96 An exception escaping from the function or callable object passed to the __fiber__
97 constructor calls `std::terminate()`.
98 If you need to know which exception was thrown, use __future__ or
104 A __fiber__ can be detached by explicitly invoking the __detach__ member
105 function. After __detach__ is called on a fiber object, that object represents
106 __not_a_fiber__. The fiber object may then safely be destroyed.
108 boost::fibers::fiber( some_fn).detach();
110 __boost_fiber__ provides a number of ways to wait for a running fiber to
111 complete. You can coordinate even with a detached fiber using a [class_link
112 mutex], or [class_link condition_variable], or any of the other [link
113 synchronization synchronization objects] provided by the library.
115 If a detached fiber is still running when the thread[s] main fiber terminates,
116 the thread will not shut down.
120 In order to wait for a fiber to finish, the __join__ member function of the
121 __fiber__ object can be used. __join__ will block until the __fiber__ object
128 boost::fibers::fiber f( some_fn);
132 If the fiber has already completed, then __join__ returns immediately and
133 the joined __fiber__ object becomes __not_a_fiber__.
136 [heading Destruction]
138 When a __fiber__ object representing a valid execution context (the fiber is
139 __joinable__) is destroyed, the program terminates. If you intend the fiber to
140 outlive the __fiber__ object that launched it, use the __detach__ method.
143 boost::fibers::fiber f( some_fn);
144 } // std::terminate() will be called
147 boost::fibers::fiber f(some_fn);
149 } // okay, program continues
155 Objects of class __fiber_id__ can be used to identify fibers. Each running
156 __fiber__ has a unique __fiber_id__ obtainable from the corresponding __fiber__
157 by calling the __get_id__ member function.
158 Objects of class __fiber_id__ can be copied, and used as keys in associative
159 containers: the full range of comparison operators is provided.
160 They can also be written to an output stream using the stream insertion
161 operator, though the output format is unspecified.
163 Each instance of __fiber_id__ either refers to some fiber, or __not_a_fiber__.
164 Instances that refer to __not_a_fiber__ compare equal to each other, but
165 not equal to any instances that refer to an actual fiber. The comparison
166 operators on __fiber_id__ yield a total order for every non-equal __fiber_id__.
169 [heading Enumeration `launch`]
171 `launch` specifies whether control passes immediately into a
172 newly-launched fiber.
181 [[Effects:] [A fiber launched with `launch == dispatch` is entered
182 immediately. In other words, launching a fiber with `dispatch` suspends the
183 caller (the previously-running fiber) until the fiber scheduler has a chance
184 to resume it later.]]
189 [[Effects:] [A fiber launched with `launch == post` is passed to the
190 fiber scheduler as ready, but it is not yet entered. The caller (the
191 previously-running fiber) continues executing. The newly-launched fiber will
192 be entered when the fiber scheduler has a chance to resume it later.]]
193 [[Note:] [If `launch` is not explicitly specified, `post` is the default.]]
198 [section:fiber Class `fiber`]
200 #include <boost/fiber/fiber.hpp>
209 constexpr fiber() noexcept;
211 template< typename Fn, typename ... Args >
212 fiber( Fn &&, Args && ...);
214 template< typename Fn, typename ... Args >
215 fiber( ``[link class_launch `launch`]``, Fn &&, Args && ...);
217 template< typename __StackAllocator__, typename Fn, typename ... Args >
218 fiber( __allocator_arg_t__, StackAllocator, Fn &&, Args && ...);
220 template< typename __StackAllocator__, typename Fn, typename ... Args >
221 fiber( ``[link class_launch `launch`]``, __allocator_arg_t__, StackAllocator, Fn &&, Args && ...);
225 fiber( fiber const&) = delete;
227 fiber & operator=( fiber const&) = delete;
229 fiber( fiber &&) noexcept;
231 fiber & operator=( fiber &&) noexcept;
233 void swap( fiber &) noexcept;
235 bool joinable() const noexcept;
237 id get_id() const noexcept;
243 template< typename PROPS >
244 PROPS & properties();
247 bool operator<( fiber const&, fiber const&) noexcept;
249 void swap( fiber &, fiber &) noexcept;
251 template< typename SchedAlgo, typename ... Args >
252 void use_scheduling_algorithm( Args && ...) noexcept;
254 bool has_ready_fibers() noexcept;
259 [heading Default constructor]
261 constexpr fiber() noexcept;
264 [[Effects:] [Constructs a __fiber__ instance that refers to __not_a_fiber__.]]
265 [[Postconditions:] [`this->get_id() == fiber::id()`]]
266 [[Throws:] [Nothing]]
270 [heading Constructor]
272 template< typename Fn, typename ... Args >
273 fiber( Fn && fn, Args && ... args);
275 template< typename Fn, typename ... Args >
276 fiber( ``[link class_launch `launch`]`` policy, Fn && fn, Args && ... args);
278 template< typename __StackAllocator__, typename Fn, typename ... Args >
279 fiber( __allocator_arg_t__, StackAllocator salloc, Fn && fn, Args && ... args);
281 template< typename __StackAllocator__, typename Fn, typename ... Args >
282 fiber( ``[link class_launch `launch`]`` policy, __allocator_arg_t__, StackAllocator salloc,
283 Fn && fn, Args && ... args);
286 [[Preconditions:] [`Fn` must be copyable or movable.]]
287 [[Effects:] [`fn` is copied or moved into internal storage for access by the
288 new fiber. If [class_link launch] is specified (or defaulted) to
289 `post`, the new fiber is marked ["ready] and will be entered at the next
290 opportunity. If `launch` is specified as `dispatch`, the calling fiber
291 is suspended and the new fiber is entered immediately.]]
292 [[Postconditions:] [`*this` refers to the newly created fiber of execution.]]
293 [[Throws:] [__fiber_error__ if an error occurs.]]
294 [[Note:] [__StackAllocator__ is required to allocate a stack for the internal
295 __econtext__. If `StackAllocator` is not explicitly passed, the default stack
296 allocator depends on `BOOST_USE_SEGMENTED_STACKS`: if defined, you will get a
297 __segmented_stack__, else a __fixedsize_stack__.]]
298 [[See also:] [__allocator_arg_t__, [link stack Stack allocation]]]
301 [heading Move constructor]
303 fiber( fiber && other) noexcept;
306 [[Effects:] [Transfers ownership of the fiber managed by `other` to the newly
307 constructed __fiber__ instance.]]
308 [[Postconditions:] [`other.get_id() == fiber::id()` and `get_id()` returns the
309 value of `other.get_id()` prior to the construction]]
310 [[Throws:] [Nothing]]
313 [heading Move assignment operator]
315 fiber & operator=( fiber && other) noexcept;
318 [[Effects:] [Transfers ownership of the fiber managed by `other` (if any) to
320 [[Postconditions:] [`other->get_id() == fiber::id()` and `get_id()` returns the
321 value of `other.get_id()` prior to the assignment.]]
322 [[Throws:] [Nothing]]
330 [[Effects:] [If the fiber is __joinable__, calls std::terminate. Destroys
332 [[Note:] [The programmer must ensure that the destructor is never executed while
333 the fiber is still __joinable__. Even if you know that the fiber has completed,
334 you must still call either __join__ or __detach__ before destroying the `fiber`
338 [member_heading fiber..joinable]
340 bool joinable() const noexcept;
343 [[Returns:] [`true` if `*this` refers to a fiber of execution, which may or
344 may not have completed; otherwise `false`.]]
345 [[Throws:] [Nothing]]
348 [member_heading fiber..join]
353 [[Preconditions:] [the fiber is __joinable__.]]
354 [[Effects:] [Waits for the referenced fiber of execution to complete.]]
355 [[Postconditions:] [The fiber of execution referenced on entry has completed.
356 `*this` no longer refers to any fiber of execution.]]
357 [[Throws:] [`fiber_error`]]
358 [[Error Conditions:] [
359 [*resource_deadlock_would_occur]: if `this->get_id() == boost::this_fiber::get_id()`.
360 [*invalid_argument]: if the fiber is not __joinable__.]]
363 [member_heading fiber..detach]
368 [[Preconditions:] [the fiber is __joinable__.]]
369 [[Effects:] [The fiber of execution becomes detached, and no longer has an
370 associated __fiber__ object.]]
371 [[Postconditions:] [`*this` no longer refers to any fiber of execution.]]
372 [[Throws:] [`fiber_error`]]
373 [[Error Conditions:] [
374 [*invalid_argument]: if the fiber is not __joinable__.]]
377 [member_heading fiber..get_id]
379 fiber::id get_id() const noexcept;
382 [[Returns:] [If `*this` refers to a fiber of execution, an instance of
383 __fiber_id__ that represents that fiber. Otherwise returns a
384 default-constructed __fiber_id__.]]
385 [[Throws:] [Nothing]]
386 [[See also:] [[ns_function_link this_fiber..get_id]]]
389 [template_member_heading fiber..properties]
391 template< typename PROPS >
392 PROPS & properties();
395 [[Preconditions:] [`*this` refers to a fiber of execution. [function_link
396 use_scheduling_algorithm] has been called from this thread with a subclass of
397 [template_link algorithm_with_properties] with the same template
399 [[Returns:] [a reference to the scheduler properties instance for `*this`.]]
400 [[Throws:] [`std::bad_cast` if `use_scheduling_algorithm()` was called with a
401 `algorithm_with_properties` subclass with some other template parameter
403 [[Note:] [[template_link algorithm_with_properties] provides a way for a
404 user-coded scheduler to associate extended properties, such as priority, with
405 a fiber instance. This method allows access to those user-provided properties.]]
406 [[See also:] [[link custom Customization]]]
409 [member_heading fiber..swap]
411 void swap( fiber & other) noexcept;
414 [[Effects:] [Exchanges the fiber of execution associated with `*this` and
415 `other`, so `*this` becomes associated with the fiber formerly associated with
416 `other`, and vice-versa.]]
417 [[Postconditions:] [`this->get_id()` returns the same value as `other.get_id()`
418 prior to the call. `other.get_id()` returns the same value as `this->get_id()`
420 [[Throws:] [Nothing]]
423 [function_heading_for swap..fiber]
425 void swap( fiber & l, fiber & r) noexcept;
428 [[Effects:] [Same as `l.swap( r)`.]]
429 [[Throws:] [Nothing]]
432 [function_heading operator<]
434 bool operator<( fiber const& l, fiber const& r) noexcept;
437 [[Returns:] [`true` if `l.get_id() < r.get_id()` is `true`, false otherwise.]]
438 [[Throws:] [Nothing.]]
441 [function_heading use_scheduling_algorithm]
443 template< typename SchedAlgo, typename ... Args >
444 void use_scheduling_algorithm( Args && ... args) noexcept;
447 [[Effects:] [Directs __boost_fiber__ to use `SchedAlgo`, which must be a
448 concrete subclass of __algo__, as the scheduling algorithm for all fibers in
449 the current thread. Pass any required `SchedAlgo` constructor arguments as
451 [[Note:] [If you want a given thread to use a non-default scheduling
452 algorithm, make that thread call `use_scheduling_algorithm()` before any other
453 __boost_fiber__ entry point. If no scheduler has been set for the current
454 thread by the time __boost_fiber__ needs to use it, the library will
455 create a default [class_link round_robin] instance for this thread.]]
456 [[Throws:] [Nothing]]
457 [[See also:] [[link scheduling Scheduling], [link custom Customization]]]
460 [function_heading has_ready_fibers]
462 bool has_ready_fibers() noexcept;
465 [[Returns:] [`true` if scheduler has fibers ready to run.]]
466 [[Throws:] [Nothing]]
467 [[Note:] [Can be used for work-stealing to find an idle scheduler.]]
470 [endsect] [/ section Class fiber]
474 [section:id Class fiber::id]
476 #include <boost/fiber/fiber.hpp>
483 constexpr id() noexcept;
485 bool operator==( id const&) const noexcept;
487 bool operator!=( id const&) const noexcept;
489 bool operator<( id const&) const noexcept;
491 bool operator>( id const&) const noexcept;
493 bool operator<=( id const&) const noexcept;
495 bool operator>=( id const&) const noexcept;
497 template< typename charT, class traitsT >
498 friend std::basic_ostream< charT, traitsT > &
499 operator<<( std::basic_ostream< charT, traitsT > &, id const&);
504 [heading Constructor]
506 constexpr id() noexcept;
509 [[Effects:] [Represents an instance of __not_a_fiber__.]]
510 [[Throws:] [Nothing.]]
513 [operator_heading id..operator_equal..operator==]
515 bool operator==( id const& other) const noexcept;
518 [[Returns:] [`true` if `*this` and `other` represent the same fiber,
519 or both represent __not_a_fiber__, `false` otherwise.]]
520 [[Throws:] [Nothing.]]
523 [operator_heading id..operator_not_equal..operator!=]
525 bool operator!=( id const& other) const noexcept;
528 [[Returns:] [[`! (other == * this)]]]
529 [[Throws:] [Nothing.]]
532 [operator_heading id..operator_less..operator<]
534 bool operator<( id const& other) const noexcept;
537 [[Returns:] [`true` if `*this != other` is true and the
538 implementation-defined total order of `fiber::id` values places `*this` before
539 `other`, false otherwise.]]
540 [[Throws:] [Nothing.]]
543 [operator_heading id..operator_greater..operator>]
545 bool operator>( id const& other) const noexcept;
548 [[Returns:] [`other < * this`]]
549 [[Throws:] [Nothing.]]
552 [operator_heading id..operator_less_equal..operator<=]
554 bool operator<=( id const& other) const noexcept;
557 [[Returns:] [`! (other < * this)`]]
558 [[Throws:] [Nothing.]]
561 [operator_heading id..operator_greater_equal..operator>=]
563 bool operator>=( id const& other) const noexcept;
566 [[Returns:] [`! (* this < other)`]]
567 [[Throws:] [Nothing.]]
572 template< typename charT, class traitsT >
573 std::basic_ostream< charT, traitsT > &
574 operator<<( std::basic_ostream< charT, traitsT > & os, id const& other);
577 [[Efects:] [Writes the representation of `other` to stream `os`. The
578 representation is unspecified.]]
583 [endsect] [/ section Class fiber::id]
586 [section:this_fiber Namespace this_fiber]
588 In general, `this_fiber` operations may be called from the ["main] fiber
589 [mdash] the fiber on which function `main()` is entered [mdash] as well as
590 from an explicitly-launched thread[s] thread-function. That is, in many
591 respects the main fiber on each thread can be treated like an
592 explicitly-launched fiber.
596 namespace this_fiber {
598 fibers::fiber::id get_id() noexcept;
599 void yield() noexcept;
600 template< typename Clock, typename Duration >
601 void sleep_until( std::chrono::time_point< Clock, Duration > const&);
602 template< typename Rep, typename Period >
603 void sleep_for( std::chrono::duration< Rep, Period > const&);
604 template< typename PROPS >
605 PROPS & properties();
609 [ns_function_heading this_fiber..get_id]
611 #include <boost/fiber/operations.hpp>
616 fiber::id get_id() noexcept;
621 [[Returns:] [An instance of __fiber_id__ that represents the currently
623 [[Throws:] [Nothing.]]
626 [ns_function_heading this_fiber..sleep_until]
628 #include <boost/fiber/operations.hpp>
633 template< typename Clock, typename Duration >
634 void sleep_until( std::chrono::time_point< Clock, Duration > const& abs_time);
639 [[Effects:] [Suspends the current fiber until the time point specified by
640 `abs_time` has been reached.]]
641 [[Throws:] [timeout-related exceptions.]]
642 [[Note:] [The current fiber will not resume before `abs_time`, but there are no
643 guarantees about how soon after `abs_time` it might resume.]]
644 [[Note:] [["timeout-related exceptions] are as defined in the C++ Standard,
645 section [*30.2.4 Timing specifications \[thread.req.timing\]]: ["A function
646 that takes an argument which specifies a timeout will throw if, during its
647 execution, a clock, time point, or time duration throws an exception. Such
648 exceptions are referred to as ['timeout-related exceptions.]]]]
651 [ns_function_heading this_fiber..sleep_for]
653 #include <boost/fiber/operations.hpp>
658 template< class Rep, class Period >
659 void sleep_for( std::chrono::duration< Rep, Period > const& rel_time);
664 [[Effects:] [Suspends the current fiber until the time duration specified by
665 `rel_time` has elapsed.]]
666 [[Throws:] [timeout-related exceptions.]]
667 [[Note:][The current fiber will not resume before `rel_time` has elapsed, but
668 there are no guarantees about how soon after that it might resume.]]
671 [ns_function_heading this_fiber..yield]
673 #include <boost/fiber/operations.hpp>
678 void yield() noexcept;
683 [[Effects:] [Reliquishes execution control, allowing other fibers to run.]]
684 [[Throws:] [Nothing.]]
685 [[Note:] [A fiber that calls
686 `yield()` is not suspended: it is immediately passed to the scheduler as ready
690 [ns_function_heading this_fiber..properties]
692 #include <boost/fiber/operations.hpp>
697 template< typename PROPS >
698 PROPS & properties();
703 [[Preconditions:] [[function_link use_scheduling_algorithm] has been called
704 from this thread with a subclass of [template_link
705 algorithm_with_properties] with the same template argument `PROPS`.]]
706 [[Returns:] [a reference to the scheduler properties instance for the
707 currently running fiber.]]
708 [[Throws:] [`std::bad_cast` if `use_scheduling_algorithm()` was called with an
709 `algorithm_with_properties` subclass with some other template parameter
711 [[Note:] [[template_link algorithm_with_properties] provides a way for a
712 user-coded scheduler to associate extended properties, such as priority, with
713 a fiber instance. This function allows access to those user-provided
715 [[Note:] [The first time this function is called from the main fiber of a
716 thread, it may internally yield, permitting other fibers to run.]]
717 [[See also:] [[link custom Customization]]]
721 [endsect] [/ section Namespace this_fiber]
724 [endsect] [/ section Fiber Management]