...one of the most highly
regarded and expertly designed C++ library projects in the
world.
— Herb Sutter and Andrei
Alexandrescu, C++
Coding Standards
#include <boost/fiber/all.hpp> namespace boost { namespace fibers { class fiber; bool operator<( fiber const& l, fiber const& r) noexcept; void swap( fiber & l, fiber & r) noexcept; template< typename SchedAlgo, typename ... Args > void use_scheduling_algorithm( Args && ... args); bool has_ready_fibers(); namespace algo { struct algorithm; template< typename PROPS > struct algorithm_with_properties; class round_robin; class shared_round_robin; }} namespace this_fiber { fibers::id get_id() noexcept; void yield(); template< typename Clock, typename Duration > void sleep_until( std::chrono::time_point< Clock, Duration > const& abs_time) template< typename Rep, typename Period > void sleep_for( std::chrono::duration< Rep, Period > const& rel_time); template< typename PROPS > PROPS & properties(); }
Each fiber
represents a micro-thread which will be launched and managed
cooperatively by a scheduler. Objects of type fiber
are move-only.
boost::fibers::fiber f1; // not-a-fiber void f() { boost::fibers::fiber f2( some_fn); f1 = std::move( f2); // f2 moved to f1 }
A new fiber is launched by passing an object of a callable type that can be invoked with no parameters. If the object must not be copied or moved, then std::ref can be used to pass in a reference to the function object. In this case, the user must ensure that the referenced object outlives the newly-created fiber.
struct callable { void operator()(); }; boost::fibers::fiber copies_are_safe() { callable x; return boost::fibers::fiber( x); } // x is destroyed, but the newly-created fiber has a copy, so this is OK boost::fibers::fiber oops() { callable x; return boost::fibers::fiber( std::ref( x) ); } // x is destroyed, but the newly-created fiber still has a reference // this leads to undefined behaviour
The spawned fiber
does not immediately start running. It is enqueued
in the list of ready-to-run fibers, and will run when the scheduler gets around
to it.
An exception escaping from the function or callable object passed to the fiber
constructor
calls std::terminate()
.
If you need to know which exception was thrown, use future<>
or
packaged_task<>
.
A fiber
can be detached by explicitly invoking the fiber::detach()
member
function. After fiber::detach()
is called on a fiber object, that
object represents not-a-fiber. The fiber object may then
safely be destroyed.
boost::fibers::fiber( some_fn).detach();
Boost.Fiber provides a number of ways to wait
for a running fiber to complete. You can coordinate even with a detached fiber
using a mutex
, or condition_variable
, or
any of the other synchronization objects
provided by the library.
If a detached fiber is still running when the thread’s main fiber terminates, the thread will not shut down.
In order to wait for a fiber to finish, the fiber::join()
member function
of the fiber
object can be used. fiber::join()
will block
until the fiber
object has completed.
void some_fn() { ... } boost::fibers::fiber f( some_fn); ... f.join();
If the fiber has already completed, then fiber::join()
returns immediately
and the joined fiber
object becomes not-a-fiber.
When a fiber
object representing a valid execution context (the fiber
is fiber::joinable()
) is destroyed, the program terminates. If
you intend the fiber to outlive the fiber
object that launched it,
use the fiber::detach()
method.
{ boost::fibers::fiber f( some_fn); } // std::terminate() will be called { boost::fibers::fiber f(some_fn); f.detach(); } // okay, program continues
Objects of class fiber::id
can be
used to identify fibers. Each running fiber
has a unique fiber::id
obtainable
from the corresponding fiber
by calling the fiber::get_id()
member
function. Objects of class fiber::id
can be
copied, and used as keys in associative containers: the full range of comparison
operators is provided. They can also be written to an output stream using the
stream insertion operator, though the output format is unspecified.
Each instance of fiber::id
either
refers to some fiber, or not-a-fiber. Instances that refer
to not-a-fiber compare equal to each other, but not equal
to any instances that refer to an actual fiber. The comparison operators on
fiber::id
yield a total order for every non-equal
fiber::id
.
launch
launch
specifies whether control
passes immediately into a newly-launched fiber.
enum class launch { dispatch, post };
dispatch
A fiber launched with launch
== dispatch
is entered immediately. In other words, launching a fiber with dispatch
suspends the caller (the previously-running
fiber) until the fiber scheduler has a chance to resume it later.
post
A fiber launched with launch
== post
is passed to the fiber scheduler as ready, but it is not yet entered.
The caller (the previously-running fiber) continues executing. The newly-launched
fiber will be entered when the fiber scheduler has a chance to resume
it later.
If launch
is not explicitly
specified, post
is the
default.