102 lines
3.6 KiB
Plaintext
102 lines
3.6 KiB
Plaintext
[/
|
|
Copyright Oliver Kowalke 2009.
|
|
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 two implementations - asymmetric and symmetric
|
|
coroutines.
|
|
|
|
Symmetric coroutines occur usually in the context of concurrent programming
|
|
in order to represent independent units of execution.
|
|
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]
|
|
__call_coro__, __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 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__).
|
|
|
|
Some applications do not use floating-point registers and can disable preserving
|
|
FPU registers for performance reasons.
|
|
|
|
[note According to the calling convention the FPU registers are preserved by
|
|
default.]
|
|
|
|
On POSIX systems, the coroutine context switch does not preserve signal masks
|
|
for performance reasons.
|
|
|
|
A context switch is done via __call_coro_op__, __push_coro_op__ and
|
|
__pull_coro_op__.
|
|
|
|
[warning Calling __call_coro_op__, __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::coroutines::symmetric_coroutine<void>::call_type coro(
|
|
[&](boost::coroutines::symmetric_coroutine<void>::yield_type& yield){
|
|
yield(coro); // yield to same symmetric_coroutine
|
|
});
|
|
coro();
|
|
|
|
|
|
[include asymmetric.qbk]
|
|
[include symmetric.qbk]
|
|
|
|
[endsect]
|