177 lines
7.6 KiB
Plaintext
177 lines
7.6 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
|
|
]
|
|
|
|
[section:overview Overview]
|
|
|
|
__boost_fiber__ provides a framework for micro-/userland-threads (fibers)
|
|
scheduled cooperatively.
|
|
The API contains classes and functions to manage and synchronize fibers
|
|
similiarly to __std_thread__.
|
|
|
|
Each fiber has its own stack.
|
|
|
|
A fiber can save the current execution state, including all registers
|
|
and CPU flags, the instruction pointer, and the stack pointer and later restore
|
|
this state.
|
|
The idea is to have multiple execution paths running on a single thread using
|
|
cooperative scheduling (versus threads, which are preemptively scheduled). The
|
|
running fiber decides explicitly when it should yield to allow another fiber to
|
|
run (context switching).
|
|
__boost_fiber__ internally uses __cc__ from __boost_context__; the classes
|
|
in this library manage, schedule and, when needed, synchronize those execution
|
|
contexts.
|
|
A context switch between threads usually costs thousands of CPU cycles on x86,
|
|
compared to a fiber switch with less than a hundred cycles.
|
|
A fiber runs on a single thread at any point in time.
|
|
|
|
In order to use the classes and functions described here, you can either include
|
|
the specific headers specified by the descriptions of each class or function, or
|
|
include the master library header:
|
|
|
|
#include <boost/fiber/all.hpp>
|
|
|
|
which includes all the other headers in turn.
|
|
|
|
The namespaces used are:
|
|
|
|
namespace boost::fibers
|
|
namespace boost::this_fiber
|
|
|
|
[heading Fibers and Threads]
|
|
|
|
Control is cooperatively passed between fibers launched on a given thread. At
|
|
a given moment, on a given thread, at most one fiber is running.
|
|
|
|
Spawning additional fibers on a given thread does not distribute your program
|
|
across more hardware cores, though it can make more effective use of the core
|
|
on which it's running.
|
|
|
|
On the other hand, a fiber may safely access any resource exclusively owned by
|
|
its parent thread without explicitly needing to defend that resource against
|
|
concurrent access by other fibers on the same thread. You are already
|
|
guaranteed that no other fiber on that thread is concurrently touching that
|
|
resource. This can be particularly important when introducing concurrency in
|
|
legacy code. You can safely spawn fibers running old code, using asynchronous
|
|
I/O to interleave execution.
|
|
|
|
In effect, fibers provide a natural way to organize concurrent code based on
|
|
asynchronous I/O. Instead of chaining together completion handlers, code
|
|
running on a fiber can make what looks like a normal blocking function call.
|
|
That call can cheaply suspend the calling fiber, allowing other fibers on the
|
|
same thread to run. When the operation has completed, the suspended fiber
|
|
resumes, without having to explicitly save or restore its state. Its local
|
|
stack variables persist across the call.
|
|
|
|
A fiber can be migrated from one thread to another, though the library does
|
|
not do this by default. It is possible for you to supply a custom scheduler
|
|
that migrates fibers between threads. You may specify custom fiber properties
|
|
to help your scheduler decide which fibers are permitted to migrate. Please
|
|
see [link migration Migrating fibers between threads] and [link custom
|
|
Customization] for more details.
|
|
|
|
__boost_fiber__ allows to [*`multiplex fibers across multiple cores`] (see
|
|
__numa_work_stealing__).
|
|
|
|
A fiber launched on a particular thread continues running on that thread
|
|
unless migrated. It might be unblocked (see [link blocking Blocking] below) by
|
|
some other thread, but that only transitions the fiber from ["blocked] to
|
|
["ready] on its current thread [mdash] it does not cause the fiber to
|
|
resume on the thread that unblocked it.
|
|
|
|
[#thread_local_storage]
|
|
[heading thread-local storage]
|
|
Unless migrated, a fiber may access thread-local storage; however that storage
|
|
will be shared among all fibers running on the same thread. For fiber-local
|
|
storage, please see __fsp__.
|
|
|
|
[#cross_thread_sync]
|
|
[heading BOOST_FIBERS_NO_ATOMICS]
|
|
The fiber synchronization objects provided by this library will, by default,
|
|
safely synchronize fibers running on different threads. However, this level of
|
|
synchronization can be removed (for performance) by building the library with
|
|
[*`BOOST_FIBERS_NO_ATOMICS`] defined. When the library is built with that macro,
|
|
you must ensure that all the fibers referencing a particular synchronization
|
|
object are running in the same thread. Please see [link synchronization
|
|
Synchronization].
|
|
|
|
[#blocking]
|
|
[heading Blocking]
|
|
|
|
Normally, when this documentation states that a particular fiber ['blocks] (or
|
|
equivalently, ['suspends),] it means that it yields control, allowing other
|
|
fibers on the same thread to run. The synchronization mechanisms provided by
|
|
__boost_fiber__ have this behavior.
|
|
|
|
A fiber may, of course, use normal thread synchronization mechanisms; however
|
|
a fiber that invokes any of these mechanisms will block its entire thread,
|
|
preventing any other fiber from running on that thread in the meantime. For
|
|
instance, when a fiber wants to wait for a value from another fiber in the
|
|
same thread, using `std::future` would be unfortunate: `std::future::get()` would
|
|
block the whole thread, preventing the other fiber from delivering its value.
|
|
Use __future__ instead.
|
|
|
|
Similarly, a fiber that invokes a normal blocking I/O operation will block its
|
|
entire thread. Fiber authors are encouraged to consistently use asynchronous
|
|
I/O. __boost_asio__ and other asynchronous I/O operations can
|
|
straightforwardly be adapted for __boost_fiber__: see [link callbacks
|
|
Integrating Fibers with Asynchronous Callbacks].
|
|
|
|
__boost_fiber__ depends upon __boost_context__.
|
|
Boost version 1.61.0 or greater is required.
|
|
|
|
[note This library requires C++11!]
|
|
|
|
|
|
[#implementation]
|
|
[section Implementations: fcontext_t, ucontext_t and WinFiber]
|
|
|
|
__boost_fiber__ uses __cc__ from __boost_context__ as building-block.
|
|
|
|
[heading fcontext_t]
|
|
|
|
The implementation uses __fcontext__ per default. fcontext_t is based on
|
|
assembler and not available for all platforms. It provides a much better
|
|
performance than __ucontext__
|
|
(the context switch takes two magnitudes of order less CPU cycles; see section
|
|
[@http://www.boost.org/doc/libs/release/libs/context/doc/html/context/performance.html ['performance]])
|
|
and __winfib__.
|
|
|
|
|
|
[heading ucontext_t]
|
|
|
|
As an alternative, [@https://en.wikipedia.org/wiki/Setcontext __ucontext__]
|
|
can be used by compiling with `BOOST_USE_UCONTEXT` and b2 property `context-impl=ucontext`.
|
|
__ucontext__ might be available on a broader range of POSIX-platforms but has
|
|
some [@http://www.boost.org/doc/libs/release/libs/context/doc/html/context/rational.html#ucontext ['disadvantages]]
|
|
(for instance deprecated since POSIX.1-2003, not C99 conform).
|
|
|
|
[note __cc__ supports [link segmented ['Segmented stacks]] only with
|
|
__ucontext__ as its implementation.]
|
|
|
|
|
|
[heading WinFiber]
|
|
|
|
With `BOOST_USE_WINFIB` and b2 property `context-impl=winfib` Win32-Fibers are used
|
|
as implementation for __cc__.
|
|
|
|
Because the TIB (thread information block) is not fully described in the MSDN,
|
|
it might be possible that not all required TIB-parts are swapped.
|
|
|
|
[note The first call of __cc__ converts the thread into a Windows fiber by
|
|
invoking `ConvertThreadToFiber()`. If desired, `ConvertFiberToThread()` has
|
|
to be called by the user explicitly in order to release resources allocated
|
|
by `ConvertThreadToFiber()` (e.g. after using boost.context). ]
|
|
|
|
[endsect]
|
|
|
|
[important Windows using fcontext_t: turn off global program optimization (/GL) and change /EHsc (compiler
|
|
assumes that functions declared as extern "C" never throw a C++ exception) to /EHs (tells
|
|
compiler assumes that functions declared as extern "C" may throw an exception).]
|
|
|
|
|
|
[endsect]
|