123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176 |
- [/
- 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]
|