124 lines
4.3 KiB
Plaintext
124 lines
4.3 KiB
Plaintext
[/
|
|
Copyright Oliver Kowalke 2014.
|
|
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:coroutine Coroutine]
|
|
|
|
__boost_coroutine__ provides asymmetric coroutines.
|
|
|
|
Implementations that produce sequences of values typically use asymmetric
|
|
coroutines.
|
|
[footnote Moura, Ana Lucia De and Ierusalimschy, Roberto.
|
|
"Revisiting coroutines". ACM Trans. Program. Lang. Syst., Volume 31 Issue 2,
|
|
February 2009, Article No. 6]
|
|
|
|
|
|
[heading stackful]
|
|
Each instance of a coroutine has its own stack.
|
|
|
|
In contrast to stackless coroutines, stackful coroutines allow invoking the
|
|
suspend operation out of arbitrary sub-stackframes, enabling escape-and-reenter
|
|
recursive operations.
|
|
|
|
|
|
[heading move-only]
|
|
A coroutine is moveable-only.
|
|
|
|
If it were copyable, then its stack with all the objects allocated on it
|
|
would be copied too. That would force undefined behaviour if some of these
|
|
objects were RAII-classes (manage a resource via RAII pattern). When the first
|
|
of the coroutine copies terminates (unwinds its stack), the RAII class
|
|
destructors will release their managed resources. When the second copy
|
|
terminates, the same destructors will try to doubly-release the same resources,
|
|
leading to undefined behaviour.
|
|
|
|
|
|
[heading clean-up]
|
|
On coroutine destruction the associated stack will be unwound.
|
|
|
|
The constructor of coroutine allows you to pass a customized ['stack-allocator].
|
|
['stack-allocator] is free to deallocate the stack or cache it for future usage
|
|
(for coroutines created later).
|
|
|
|
|
|
[heading segmented stack]
|
|
__push_coro__ and __pull_coro__ support segmented stacks (growing on demand).
|
|
|
|
It is not always possible to accurately estimate the required stack size - in
|
|
most cases too much memory is allocated (waste of virtual address-space).
|
|
|
|
At construction a coroutine starts with a default (minimal) stack size. This
|
|
minimal stack size is the maximum of page size and the canonical size for signal
|
|
stack (macro SIGSTKSZ on POSIX).
|
|
|
|
At this time of writing only GCC (4.7)
|
|
[footnote [@http://gcc.gnu.org/wiki/SplitStacks Ian Lance Taylor, Split Stacks in GCC]]
|
|
is known to support segmented stacks. With version 1.54 __boost_coroutine__
|
|
provides support for [link segmented ['segmented stacks]].
|
|
|
|
The destructor releases the associated stack. The implementer is free to
|
|
deallocate the stack or to cache it for later usage.
|
|
|
|
|
|
[heading context switch]
|
|
A coroutine saves and restores registers according to the underlying ABI on
|
|
each context switch (using __boost_context__).
|
|
|
|
A context switch is done via __push_coro_op__ and __pull_coro_op__.
|
|
|
|
[warning Calling __push_coro_op__ and __pull_coro_op__ from inside the [_same]
|
|
coroutine results in undefined behaviour.]
|
|
|
|
As an example, the code below will result in undefined behaviour:
|
|
|
|
boost::coroutines2::coroutine<void>::push_type coro(
|
|
[&](boost::coroutines2::coroutine<void>::pull_type& yield){
|
|
coro();
|
|
});
|
|
coro();
|
|
|
|
|
|
[include asymmetric.qbk]
|
|
|
|
|
|
[section Implementations: fcontext_t, ucontext_t and WinFiber]
|
|
|
|
[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) 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 (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]
|
|
|
|
[endsect]
|