3914 lines
273 KiB
XML
3914 lines
273 KiB
XML
|
<?xml version="1.0" encoding="UTF-8"?>
|
||
|
<!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
|
||
|
<library id="context" name="Context" dirname="context" last-revision="$Date: 2019/10/02 06:15:27 $"
|
||
|
xmlns:xi="http://www.w3.org/2001/XInclude">
|
||
|
<libraryinfo>
|
||
|
<authorgroup>
|
||
|
<author>
|
||
|
<firstname>Oliver</firstname> <surname>Kowalke</surname>
|
||
|
</author>
|
||
|
</authorgroup>
|
||
|
<copyright>
|
||
|
<year>2014</year> <holder>Oliver Kowalke</holder>
|
||
|
</copyright>
|
||
|
<legalnotice id="context.legal">
|
||
|
<para>
|
||
|
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||
|
file LICENSE_1_0.txt or copy at <ulink url="http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</ulink>)
|
||
|
</para>
|
||
|
</legalnotice>
|
||
|
<librarypurpose>
|
||
|
C++ Library for swiching different user ctx
|
||
|
</librarypurpose>
|
||
|
<librarycategory name="category:text"></librarycategory>
|
||
|
</libraryinfo>
|
||
|
<title>Context</title>
|
||
|
<section id="context.overview">
|
||
|
<title><link linkend="context.overview">Overview</link></title>
|
||
|
<para>
|
||
|
<emphasis role="bold">Boost.Context</emphasis> is a foundational library that
|
||
|
provides a sort of cooperative multitasking on a single thread. By providing
|
||
|
an abstraction of the current execution state in the current thread, including
|
||
|
the stack (with local variables) and stack pointer, all registers and CPU flags,
|
||
|
and the instruction pointer, a execution context represents a specific point
|
||
|
in the application's execution path. This is useful for building higher-level
|
||
|
abstractions, like <emphasis>coroutines</emphasis>, <emphasis>cooperative threads
|
||
|
(userland threads)</emphasis> or an equivalent to <ulink url="http://msdn.microsoft.com/en-us/library/9k7k7cf0%28v=vs.80%29.aspx">C#
|
||
|
keyword <emphasis>yield</emphasis></ulink> in C++.
|
||
|
</para>
|
||
|
<para>
|
||
|
<link linkend="cc"><emphasis>callcc()</emphasis></link>/<link linkend="cc"><emphasis>continuation</emphasis></link>
|
||
|
provides the means to suspend the current execution path and to transfer execution
|
||
|
control, thereby permitting another context to run on the current thread. This
|
||
|
state full transfer mechanism enables a context to suspend execution from within
|
||
|
nested functions and, later, to resume from where it was suspended. While the
|
||
|
execution path represented by a <link linkend="cc"><emphasis>continuation</emphasis></link>
|
||
|
only runs on a single thread, it can be migrated to another thread at any given
|
||
|
time.
|
||
|
</para>
|
||
|
<para>
|
||
|
A <ulink url="http://en.wikipedia.org/wiki/Context_switch">context switch</ulink>
|
||
|
between threads requires system calls (involving the OS kernel), which can
|
||
|
cost more than thousand CPU cycles on x86 CPUs. By contrast, transferring control
|
||
|
vias <link linkend="cc"><emphasis>callcc()</emphasis></link>/<link linkend="cc"><emphasis>continuation</emphasis></link>
|
||
|
requires only few CPU cycles because it does not involve system calls as it
|
||
|
is done within a single thread.
|
||
|
</para>
|
||
|
<para>
|
||
|
All functions and classes are contained in the namespace <emphasis>boost::context</emphasis>.
|
||
|
</para>
|
||
|
<note>
|
||
|
<para>
|
||
|
This library requires C++11!
|
||
|
</para>
|
||
|
</note>
|
||
|
<important>
|
||
|
<para>
|
||
|
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).
|
||
|
</para>
|
||
|
</important>
|
||
|
</section>
|
||
|
<section id="context.requirements">
|
||
|
<title><link linkend="context.requirements">Requirements</link></title>
|
||
|
<para>
|
||
|
If <emphasis role="bold">Boost.Context</emphasis> uses fcontext_t (the default)
|
||
|
as its implementation, it must be built for the particular compiler(s) and
|
||
|
CPU architecture(s) being targeted. Using <link linkend="implementation"><emphasis>fcontext_t</emphasis></link>,
|
||
|
<emphasis role="bold">Boost.Context</emphasis> includes assembly code and,
|
||
|
therefore, requires GNU as and GNU preprocessor for supported POSIX systems,
|
||
|
MASM for Windows/x86 systems and ARMasm for Windows/arm systems.
|
||
|
</para>
|
||
|
<note>
|
||
|
<para>
|
||
|
MASM64 (ml64.exe) is a part of Microsoft's Windows Driver Kit.
|
||
|
</para>
|
||
|
</note>
|
||
|
<important>
|
||
|
<para>
|
||
|
Please note that <code><phrase role="identifier">address</phrase><phrase
|
||
|
role="special">-</phrase><phrase role="identifier">model</phrase><phrase
|
||
|
role="special">=</phrase><phrase role="number">64</phrase></code> must be
|
||
|
given to bjam command line on 64bit Windows for 64bit build; otherwise 32bit
|
||
|
code will be generated.
|
||
|
</para>
|
||
|
</important>
|
||
|
<important>
|
||
|
<para>
|
||
|
For cross-compiling the lib you must specify certain additional properties
|
||
|
at bjam command line: <code><phrase role="identifier">target</phrase><phrase
|
||
|
role="special">-</phrase><phrase role="identifier">os</phrase></code>, <code><phrase
|
||
|
role="identifier">abi</phrase></code>, <code><phrase role="identifier">binary</phrase><phrase
|
||
|
role="special">-</phrase><phrase role="identifier">format</phrase></code>,
|
||
|
<code><phrase role="identifier">architecture</phrase></code> and <code><phrase
|
||
|
role="identifier">address</phrase><phrase role="special">-</phrase><phrase
|
||
|
role="identifier">model</phrase></code>.
|
||
|
</para>
|
||
|
</important>
|
||
|
<important>
|
||
|
<para>
|
||
|
Windows using fcontext_t: for safe SEH the property 'asmflags=\safeseh' must
|
||
|
be specified at bjam command line.
|
||
|
</para>
|
||
|
</important>
|
||
|
<important>
|
||
|
<para>
|
||
|
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).
|
||
|
</para>
|
||
|
</important>
|
||
|
<para>
|
||
|
Because this library uses C++11 extensively, it requires a compatible compiler.
|
||
|
Known minimum working versions are as follows: Microsoft Visual Studio 2015
|
||
|
(msvc-14.0), GCC 4.8 (with -std=c++11), Clang 3.4 (with -std=c++11). Other
|
||
|
compilers may work, if they support the following language features: auto declarations,
|
||
|
constexpr, defaulted functions, final, hdr thread, hdr tuple, lambdas, noexcept,
|
||
|
nullptr, rvalue references, template aliases. thread local, variadic templates.
|
||
|
</para>
|
||
|
</section>
|
||
|
<section id="context.ff">
|
||
|
<title><anchor id="ff"/><link linkend="context.ff">Context switching with fibers</link></title>
|
||
|
<note>
|
||
|
<para>
|
||
|
<emphasis>fiber</emphasis> is the reference implementation of C++ proposal
|
||
|
<ulink url="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0876r0.pdf">P0876R0:
|
||
|
fibers without scheduler</ulink>.
|
||
|
</para>
|
||
|
</note>
|
||
|
<para>
|
||
|
A <emphasis>fiber</emphasis> represents the state of the control flow of a
|
||
|
program at a given point in time. Fibers can be suspended and resumed later
|
||
|
in order to change the control flow of a program.
|
||
|
</para>
|
||
|
<para>
|
||
|
Modern micro-processors are registers machines; the content of processor registers
|
||
|
represent a fiber of the executed program at a given point in time. Operating
|
||
|
systems simulate parallel execution of programs on a single processor by switching
|
||
|
between programs (context switch) by preserving and restoring the fiber, e.g.
|
||
|
the content of all registers.
|
||
|
</para>
|
||
|
<bridgehead renderas="sect3" id="context.ff.h0">
|
||
|
<phrase id="context.ff._link_linkend__ff___emphasis_fiber__emphasis___link_"/><link
|
||
|
linkend="context.ff._link_linkend__ff___emphasis_fiber__emphasis___link_"><link
|
||
|
linkend="ff"><emphasis>fiber</emphasis></link></link>
|
||
|
</bridgehead>
|
||
|
<para>
|
||
|
<link linkend="ff"><emphasis>fiber</emphasis></link> captures the current fiber
|
||
|
(the rest of the computation; code after <link linkend="ff"><emphasis>fiber</emphasis></link>)
|
||
|
and triggers a context switch. The context switch is achieved by preserving
|
||
|
certain registers (including instruction and stack pointer), defined by the
|
||
|
calling convention of the ABI, of the current fiber and restoring those registers
|
||
|
of the resumed fiber. The control flow of the resumed fiber continues. The
|
||
|
current fiber is suspended and passed as argument to the resumed fiber.
|
||
|
</para>
|
||
|
<para>
|
||
|
<link linkend="ff"><emphasis>fiber</emphasis></link> expects a <emphasis>context-function</emphasis>
|
||
|
with signature <code><phrase role="char">'fiber(fiber && f)'</phrase></code>.
|
||
|
The parameter <code><phrase role="identifier">f</phrase></code> represents
|
||
|
the current fiber from which this fiber was resumed (e.g. that has called
|
||
|
<link linkend="ff"><emphasis>fiber</emphasis></link>).
|
||
|
</para>
|
||
|
<para>
|
||
|
On return the <emphasis>context-function</emphasis> of the current fiber has
|
||
|
to specify an <link linkend="ff"><emphasis>fiber</emphasis></link> to which
|
||
|
the execution control is transferred after termination of the current fiber.
|
||
|
</para>
|
||
|
<para>
|
||
|
If an instance with valid state goes out of scope and the <emphasis>context-function</emphasis>
|
||
|
has not yet returned, the stack is traversed in order to access the control
|
||
|
structure (address stored at the first stack frame) and fiber's stack is deallocated
|
||
|
via the <emphasis>StackAllocator</emphasis>.
|
||
|
</para>
|
||
|
<note>
|
||
|
<para>
|
||
|
<link linkend="segmented"><emphasis>Segmented stacks</emphasis></link> are
|
||
|
supported by <link linkend="ff"><emphasis>fiber</emphasis></link> using
|
||
|
<link linkend="implementation"><emphasis>ucontext_t</emphasis></link>.
|
||
|
</para>
|
||
|
</note>
|
||
|
<para>
|
||
|
<link linkend="ff"><emphasis>fiber</emphasis></link> represents a <emphasis>fiber</emphasis>;
|
||
|
it contains the content of preserved registers and manages the associated stack
|
||
|
(allocation/deallocation). <link linkend="ff"><emphasis>fiber</emphasis></link>
|
||
|
is a one-shot fiber - it can be used only once, after calling <emphasis>continuation::resume()</emphasis>
|
||
|
or <emphasis>continuation::resume_with()</emphasis> it is invalidated.
|
||
|
</para>
|
||
|
<para>
|
||
|
<link linkend="ff"><emphasis>fiber</emphasis></link> is only move-constructible
|
||
|
and move-assignable.
|
||
|
</para>
|
||
|
<para>
|
||
|
As a first-class object <link linkend="ff"><emphasis>fiber</emphasis></link>
|
||
|
can be applied to and returned from a function, assigned to a variable or stored
|
||
|
in a container.
|
||
|
</para>
|
||
|
<para>
|
||
|
A fiber is continued by calling <code><phrase role="identifier">resume</phrase><phrase
|
||
|
role="special">()</phrase></code>/<code><phrase role="identifier">resume_with</phrase><phrase
|
||
|
role="special">()</phrase></code>.
|
||
|
</para>
|
||
|
<bridgehead renderas="sect3" id="context.ff.h1">
|
||
|
<phrase id="context.ff.usage"/><link linkend="context.ff.usage">Usage</link>
|
||
|
</bridgehead>
|
||
|
<programlisting><phrase role="keyword">namespace</phrase> <phrase role="identifier">ctx</phrase><phrase role="special">=</phrase><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">context</phrase><phrase role="special">;</phrase>
|
||
|
<phrase role="keyword">int</phrase> <phrase role="identifier">a</phrase><phrase role="special">;</phrase>
|
||
|
<phrase role="identifier">ctx</phrase><phrase role="special">::</phrase><phrase role="identifier">fiber</phrase> <phrase role="identifier">source</phrase><phrase role="special">{[&</phrase><phrase role="identifier">a</phrase><phrase role="special">](</phrase><phrase role="identifier">ctx</phrase><phrase role="special">::</phrase><phrase role="identifier">fiber</phrase><phrase role="special">&&</phrase> <phrase role="identifier">sink</phrase><phrase role="special">){</phrase>
|
||
|
<phrase role="identifier">a</phrase><phrase role="special">=</phrase><phrase role="number">0</phrase><phrase role="special">;</phrase>
|
||
|
<phrase role="keyword">int</phrase> <phrase role="identifier">b</phrase><phrase role="special">=</phrase><phrase role="number">1</phrase><phrase role="special">;</phrase>
|
||
|
<phrase role="keyword">for</phrase><phrase role="special">(;;){</phrase>
|
||
|
<phrase role="identifier">sink</phrase><phrase role="special">=</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">move</phrase><phrase role="special">(</phrase><phrase role="identifier">sink</phrase><phrase role="special">).</phrase><phrase role="identifier">resume</phrase><phrase role="special">();</phrase>
|
||
|
<phrase role="keyword">int</phrase> <phrase role="identifier">next</phrase><phrase role="special">=</phrase><phrase role="identifier">a</phrase><phrase role="special">+</phrase><phrase role="identifier">b</phrase><phrase role="special">;</phrase>
|
||
|
<phrase role="identifier">a</phrase><phrase role="special">=</phrase><phrase role="identifier">b</phrase><phrase role="special">;</phrase>
|
||
|
<phrase role="identifier">b</phrase><phrase role="special">=</phrase><phrase role="identifier">next</phrase><phrase role="special">;</phrase>
|
||
|
<phrase role="special">}</phrase>
|
||
|
<phrase role="keyword">return</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">move</phrase><phrase role="special">(</phrase><phrase role="identifier">sink</phrase><phrase role="special">);</phrase>
|
||
|
<phrase role="special">}};</phrase>
|
||
|
<phrase role="keyword">for</phrase> <phrase role="special">(</phrase><phrase role="keyword">int</phrase> <phrase role="identifier">j</phrase><phrase role="special">=</phrase><phrase role="number">0</phrase><phrase role="special">;</phrase><phrase role="identifier">j</phrase><phrase role="special"><</phrase><phrase role="number">10</phrase><phrase role="special">;++</phrase><phrase role="identifier">j</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
|
||
|
<phrase role="identifier">source</phrase><phrase role="special">=</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">move</phrase><phrase role="special">(</phrase><phrase role="identifier">source</phrase><phrase role="special">).</phrase><phrase role="identifier">resume</phrase><phrase role="special">();</phrase>
|
||
|
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cout</phrase> <phrase role="special"><<</phrase> <phrase role="identifier">a</phrase> <phrase role="special"><<</phrase> <phrase role="string">" "</phrase><phrase role="special">;</phrase>
|
||
|
<phrase role="special">}</phrase>
|
||
|
|
||
|
<phrase role="identifier">output</phrase><phrase role="special">:</phrase>
|
||
|
<phrase role="number">0</phrase> <phrase role="number">1</phrase> <phrase role="number">1</phrase> <phrase role="number">2</phrase> <phrase role="number">3</phrase> <phrase role="number">5</phrase> <phrase role="number">8</phrase> <phrase role="number">13</phrase> <phrase role="number">21</phrase> <phrase role="number">34</phrase>
|
||
|
</programlisting>
|
||
|
<para>
|
||
|
This simple example demonstrates the basic usage of <link linkend="ff"><emphasis>fiber</emphasis></link>
|
||
|
as a <emphasis>generator</emphasis>. The fiber <code><phrase role="identifier">sink</phrase></code>
|
||
|
represents the <emphasis>main</emphasis>-fiber (function <code><phrase role="identifier">main</phrase><phrase
|
||
|
role="special">()</phrase></code>). <code><phrase role="identifier">sink</phrase></code>
|
||
|
is captured (current-fiber) by invoking <link linkend="ff"><emphasis>fiber</emphasis></link>
|
||
|
and passed as parameter to the lambda.
|
||
|
</para>
|
||
|
<para>
|
||
|
Because the state is invalidated (one-shot fiber) by each call of <emphasis>continuation::resume()</emphasis>,
|
||
|
the new state of the <link linkend="ff"><emphasis>fiber</emphasis></link>,
|
||
|
returned by <emphasis>continuation::resume()</emphasis>, needs to be assigned
|
||
|
to <code><phrase role="identifier">sink</phrase></code> after each call. In
|
||
|
order to express the invalidation of the resumed fiber, the member functions
|
||
|
<code><phrase role="identifier">resume</phrase><phrase role="special">()</phrase></code>
|
||
|
and <code><phrase role="identifier">resume_with</phrase><phrase role="special">()</phrase></code>
|
||
|
are rvalue-ref qualified. Both functions bind only to rvalues. Thus an lvalue
|
||
|
fiber must be casted to an rvalue via <code><phrase role="identifier">std</phrase><phrase
|
||
|
role="special">::</phrase><phrase role="identifier">move</phrase><phrase role="special">()</phrase></code>.
|
||
|
</para>
|
||
|
<para>
|
||
|
The lambda that calculates the Fibonacci numbers is executed inside the fiber
|
||
|
represented by <code><phrase role="identifier">source</phrase></code>. Calculated
|
||
|
Fibonacci numbers are transferred between the two fibers via variable <code><phrase
|
||
|
role="identifier">a</phrase></code> (lambda capture reference).
|
||
|
</para>
|
||
|
<para>
|
||
|
The locale variables <code><phrase role="identifier">b</phrase></code> and
|
||
|
<code> <phrase role="identifier">next</phrase></code> remain their values during
|
||
|
each context switch. This is possible due <code><phrase role="identifier">source</phrase></code>
|
||
|
has its own stack and the stack is exchanged by each context switch.
|
||
|
</para>
|
||
|
<bridgehead renderas="sect3" id="context.ff.h2">
|
||
|
<phrase id="context.ff.parameter_passing"/><link linkend="context.ff.parameter_passing">Parameter
|
||
|
passing</link>
|
||
|
</bridgehead>
|
||
|
<para>
|
||
|
Data can be transferred between two fibers via global pointers, calling wrappers
|
||
|
(like <code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase
|
||
|
role="identifier">bind</phrase></code>) or lambda captures.
|
||
|
</para>
|
||
|
<programlisting><phrase role="keyword">namespace</phrase> <phrase role="identifier">ctx</phrase><phrase role="special">=</phrase><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">context</phrase><phrase role="special">;</phrase>
|
||
|
<phrase role="keyword">int</phrase> <phrase role="identifier">i</phrase><phrase role="special">=</phrase><phrase role="number">1</phrase><phrase role="special">;</phrase>
|
||
|
<phrase role="identifier">ctx</phrase><phrase role="special">::</phrase><phrase role="identifier">fiber</phrase> <phrase role="identifier">f1</phrase><phrase role="special">{[&</phrase><phrase role="identifier">i</phrase><phrase role="special">](</phrase><phrase role="identifier">ctx</phrase><phrase role="special">::</phrase><phrase role="identifier">fiber</phrase><phrase role="special">&&</phrase> <phrase role="identifier">f2</phrase><phrase role="special">){</phrase>
|
||
|
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">printf</phrase><phrase role="special">(</phrase><phrase role="string">"inside f1,i==%d\n"</phrase><phrase role="special">,</phrase><phrase role="identifier">i</phrase><phrase role="special">);</phrase>
|
||
|
<phrase role="identifier">i</phrase><phrase role="special">+=</phrase><phrase role="number">1</phrase><phrase role="special">;</phrase>
|
||
|
<phrase role="keyword">return</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">move</phrase><phrase role="special">(</phrase><phrase role="identifier">f2</phrase><phrase role="special">).</phrase><phrase role="identifier">resume</phrase><phrase role="special">();</phrase>
|
||
|
<phrase role="special">}};</phrase>
|
||
|
<phrase role="identifier">f1</phrase><phrase role="special">=</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">move</phrase><phrase role="special">(</phrase><phrase role="identifier">f1</phrase><phrase role="special">).</phrase><phrase role="identifier">resume</phrase><phrase role="special">();</phrase>
|
||
|
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">printf</phrase><phrase role="special">(</phrase><phrase role="string">"i==%d\n"</phrase><phrase role="special">,</phrase><phrase role="identifier">i</phrase><phrase role="special">);</phrase>
|
||
|
|
||
|
<phrase role="identifier">output</phrase><phrase role="special">:</phrase>
|
||
|
<phrase role="identifier">inside</phrase> <phrase role="identifier">c1</phrase><phrase role="special">,</phrase><phrase role="identifier">i</phrase><phrase role="special">==</phrase><phrase role="number">1</phrase>
|
||
|
<phrase role="identifier">i</phrase><phrase role="special">==</phrase><phrase role="number">2</phrase>
|
||
|
</programlisting>
|
||
|
<para>
|
||
|
<code><phrase role="identifier">f1</phrase><phrase role="special">.</phrase><phrase
|
||
|
role="identifier">resume</phrase><phrase role="special">()</phrase></code>
|
||
|
enters the lambda in fiber represented by <code><phrase role="identifier">f1</phrase></code>
|
||
|
with lambda capture reference <code><phrase role="identifier">i</phrase><phrase
|
||
|
role="special">=</phrase><phrase role="number">1</phrase></code>. The expression
|
||
|
<code><phrase role="identifier">f2</phrase><phrase role="special">.</phrase><phrase
|
||
|
role="identifier">resume</phrase><phrase role="special">()</phrase></code>
|
||
|
resumes the fiber <code><phrase role="identifier">f2</phrase></code>. On return
|
||
|
of <code><phrase role="identifier">f1</phrase><phrase role="special">.</phrase><phrase
|
||
|
role="identifier">resume</phrase><phrase role="special">()</phrase></code>,
|
||
|
the variable <code><phrase role="identifier">i</phrase></code> has the value
|
||
|
of <code><phrase role="identifier">i</phrase><phrase role="special">+</phrase><phrase
|
||
|
role="number">1</phrase></code>.
|
||
|
</para>
|
||
|
<bridgehead renderas="sect3" id="context.ff.h3">
|
||
|
<phrase id="context.ff.exception_handling"/><link linkend="context.ff.exception_handling">Exception
|
||
|
handling</link>
|
||
|
</bridgehead>
|
||
|
<para>
|
||
|
If the function executed inside a <emphasis>context-function</emphasis> emits
|
||
|
an exception, the application is terminated by calling <code><phrase role="identifier">std</phrase><phrase
|
||
|
role="special">::</phrase><phrase role="identifier">terminate</phrase><phrase
|
||
|
role="special">()</phrase></code>. <code><phrase role="identifier">std</phrase><phrase
|
||
|
role="special">::</phrase><phrase role="identifier">exception_ptr</phrase></code>
|
||
|
can be used to transfer exceptions between different fibers.
|
||
|
</para>
|
||
|
<important>
|
||
|
<para>
|
||
|
Do not jump from inside a catch block and then re-throw the exception in
|
||
|
another fiber.
|
||
|
</para>
|
||
|
</important>
|
||
|
<anchor id="ff_ontop"/>
|
||
|
<bridgehead renderas="sect3" id="context.ff.h4">
|
||
|
<phrase id="context.ff.executing_function_on_top_of_a_fiber"/><link linkend="context.ff.executing_function_on_top_of_a_fiber">Executing
|
||
|
function on top of a fiber</link>
|
||
|
</bridgehead>
|
||
|
<para>
|
||
|
Sometimes it is useful to execute a new function on top of a resumed fiber.
|
||
|
For this purpose <emphasis>continuation::resume_with()</emphasis> has to be
|
||
|
used. The function passed as argument must accept a rvalue reference to <link
|
||
|
linkend="ff"><emphasis>fiber</emphasis></link> and return <code><phrase role="keyword">void</phrase></code>.
|
||
|
</para>
|
||
|
<programlisting><phrase role="keyword">namespace</phrase> <phrase role="identifier">ctx</phrase><phrase role="special">=</phrase><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">context</phrase><phrase role="special">;</phrase>
|
||
|
<phrase role="keyword">int</phrase> <phrase role="identifier">data</phrase><phrase role="special">=</phrase><phrase role="number">0</phrase><phrase role="special">;</phrase>
|
||
|
<phrase role="identifier">ctx</phrase><phrase role="special">::</phrase><phrase role="identifier">fiber</phrase> <phrase role="identifier">f1</phrase><phrase role="special">{[&</phrase><phrase role="identifier">data</phrase><phrase role="special">](</phrase><phrase role="identifier">ctx</phrase><phrase role="special">::</phrase><phrase role="identifier">fiber</phrase><phrase role="special">&&</phrase> <phrase role="identifier">f2</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
|
||
|
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cout</phrase> <phrase role="special"><<</phrase> <phrase role="string">"f1: entered first time: "</phrase> <phrase role="special"><<</phrase> <phrase role="identifier">data</phrase> <phrase role="special"><<</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">endl</phrase><phrase role="special">;</phrase>
|
||
|
<phrase role="identifier">data</phrase><phrase role="special">+=</phrase><phrase role="number">1</phrase><phrase role="special">;</phrase>
|
||
|
<phrase role="identifier">f2</phrase><phrase role="special">=</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">move</phrase><phrase role="special">(</phrase><phrase role="identifier">f2</phrase><phrase role="special">).</phrase><phrase role="identifier">resume</phrase><phrase role="special">();</phrase>
|
||
|
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cout</phrase> <phrase role="special"><<</phrase> <phrase role="string">"f1: entered second time: "</phrase> <phrase role="special"><<</phrase> <phrase role="identifier">data</phrase> <phrase role="special"><<</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">endl</phrase><phrase role="special">;</phrase>
|
||
|
<phrase role="identifier">data</phrase><phrase role="special">+=</phrase><phrase role="number">1</phrase><phrase role="special">;</phrase>
|
||
|
<phrase role="identifier">f2</phrase><phrase role="special">=</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">move</phrase><phrase role="special">(</phrase><phrase role="identifier">f2</phrase><phrase role="special">).</phrase><phrase role="identifier">resume</phrase><phrase role="special">();</phrase>
|
||
|
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cout</phrase> <phrase role="special"><<</phrase> <phrase role="string">"f1: entered third time: "</phrase> <phrase role="special"><<</phrase> <phrase role="identifier">data</phrase> <phrase role="special"><<</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">endl</phrase><phrase role="special">;</phrase>
|
||
|
<phrase role="keyword">return</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">move</phrase><phrase role="special">(</phrase><phrase role="identifier">f2</phrase><phrase role="special">);</phrase>
|
||
|
<phrase role="special">}};</phrase>
|
||
|
<phrase role="identifier">f1</phrase><phrase role="special">=</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">move</phrase><phrase role="special">(</phrase><phrase role="identifier">f1</phrase><phrase role="special">).</phrase><phrase role="identifier">resume</phrase><phrase role="special">();</phrase>
|
||
|
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cout</phrase> <phrase role="special"><<</phrase> <phrase role="string">"f1: returned first time: "</phrase> <phrase role="special"><<</phrase> <phrase role="identifier">data</phrase> <phrase role="special"><<</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">endl</phrase><phrase role="special">;</phrase>
|
||
|
<phrase role="identifier">data</phrase><phrase role="special">+=</phrase><phrase role="number">1</phrase><phrase role="special">;</phrase>
|
||
|
<phrase role="identifier">f1</phrase><phrase role="special">=</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">move</phrase><phrase role="special">(</phrase><phrase role="identifier">f1</phrase><phrase role="special">).</phrase><phrase role="identifier">resume</phrase><phrase role="special">();</phrase>
|
||
|
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cout</phrase> <phrase role="special"><<</phrase> <phrase role="string">"f1: returned second time: "</phrase> <phrase role="special"><<</phrase> <phrase role="identifier">data</phrase> <phrase role="special"><<</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">endl</phrase><phrase role="special">;</phrase>
|
||
|
<phrase role="identifier">data</phrase><phrase role="special">+=</phrase><phrase role="number">1</phrase><phrase role="special">;</phrase>
|
||
|
<phrase role="identifier">f1</phrase><phrase role="special">=</phrase><phrase role="identifier">f1</phrase><phrase role="special">.</phrase><phrase role="identifier">resume_with</phrase><phrase role="special">([&</phrase><phrase role="identifier">data</phrase><phrase role="special">](</phrase><phrase role="identifier">ctx</phrase><phrase role="special">::</phrase><phrase role="identifier">fiber</phrase><phrase role="special">&&</phrase> <phrase role="identifier">f2</phrase><phrase role="special">){</phrase>
|
||
|
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cout</phrase> <phrase role="special"><<</phrase> <phrase role="string">"f2: entered: "</phrase> <phrase role="special"><<</phrase> <phrase role="identifier">data</phrase> <phrase role="special"><<</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">endl</phrase><phrase role="special">;</phrase>
|
||
|
<phrase role="identifier">data</phrase><phrase role="special">=-</phrase><phrase role="number">1</phrase><phrase role="special">;</phrase>
|
||
|
<phrase role="keyword">return</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">move</phrase><phrase role="special">(</phrase><phrase role="identifier">f2</phrase><phrase role="special">);</phrase>
|
||
|
<phrase role="special">});</phrase>
|
||
|
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cout</phrase> <phrase role="special"><<</phrase> <phrase role="string">"f1: returned third time"</phrase> <phrase role="special"><<</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">endl</phrase><phrase role="special">;</phrase>
|
||
|
|
||
|
<phrase role="identifier">output</phrase><phrase role="special">:</phrase>
|
||
|
<phrase role="identifier">f1</phrase><phrase role="special">:</phrase> <phrase role="identifier">entered</phrase> <phrase role="identifier">first</phrase> <phrase role="identifier">time</phrase><phrase role="special">:</phrase> <phrase role="number">0</phrase>
|
||
|
<phrase role="identifier">f1</phrase><phrase role="special">:</phrase> <phrase role="identifier">returned</phrase> <phrase role="identifier">first</phrase> <phrase role="identifier">time</phrase><phrase role="special">:</phrase> <phrase role="number">1</phrase>
|
||
|
<phrase role="identifier">f1</phrase><phrase role="special">:</phrase> <phrase role="identifier">entered</phrase> <phrase role="identifier">second</phrase> <phrase role="identifier">time</phrase><phrase role="special">:</phrase> <phrase role="number">2</phrase>
|
||
|
<phrase role="identifier">f1</phrase><phrase role="special">:</phrase> <phrase role="identifier">returned</phrase> <phrase role="identifier">second</phrase> <phrase role="identifier">time</phrase><phrase role="special">:</phrase> <phrase role="number">3</phrase>
|
||
|
<phrase role="identifier">f2</phrase><phrase role="special">:</phrase> <phrase role="identifier">entered</phrase><phrase role="special">:</phrase> <phrase role="number">4</phrase>
|
||
|
<phrase role="identifier">f1</phrase><phrase role="special">:</phrase> <phrase role="identifier">entered</phrase> <phrase role="identifier">third</phrase> <phrase role="identifier">time</phrase><phrase role="special">:</phrase> <phrase role="special">-</phrase><phrase role="number">1</phrase>
|
||
|
<phrase role="identifier">f1</phrase><phrase role="special">:</phrase> <phrase role="identifier">returned</phrase> <phrase role="identifier">third</phrase> <phrase role="identifier">time</phrase>
|
||
|
</programlisting>
|
||
|
<para>
|
||
|
The expression <code><phrase role="identifier">f1</phrase><phrase role="special">.</phrase><phrase
|
||
|
role="identifier">resume_with</phrase><phrase role="special">(...)</phrase></code>
|
||
|
executes a lambda on top of fiber <code><phrase role="identifier">f1</phrase></code>,
|
||
|
e.g. an additional stack frame is allocated on top of the stack. This lambda
|
||
|
assigns <code><phrase role="special">-</phrase><phrase role="number">1</phrase></code>
|
||
|
to <code><phrase role="identifier">data</phrase></code> and returns to the
|
||
|
second invocation of <code><phrase role="identifier">f1</phrase><phrase role="special">.</phrase><phrase
|
||
|
role="identifier">resume</phrase><phrase role="special">()</phrase></code>.
|
||
|
</para>
|
||
|
<para>
|
||
|
Another option is to execute a function on top of the fiber that throws an
|
||
|
exception.
|
||
|
</para>
|
||
|
<programlisting><phrase role="keyword">namespace</phrase> <phrase role="identifier">ctx</phrase><phrase role="special">=</phrase><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">context</phrase><phrase role="special">;</phrase>
|
||
|
<phrase role="keyword">struct</phrase> <phrase role="identifier">my_exception</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">runtime_error</phrase> <phrase role="special">{</phrase>
|
||
|
<phrase role="identifier">ctx</phrase><phrase role="special">::</phrase><phrase role="identifier">fiber</phrase> <phrase role="identifier">f</phrase><phrase role="special">;</phrase>
|
||
|
<phrase role="identifier">my_exception</phrase><phrase role="special">(</phrase><phrase role="identifier">ctx</phrase><phrase role="special">::</phrase><phrase role="identifier">fiber</phrase><phrase role="special">&&</phrase> <phrase role="identifier">f_</phrase><phrase role="special">,</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">what</phrase><phrase role="special">)</phrase> <phrase role="special">:</phrase>
|
||
|
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">runtime_error</phrase><phrase role="special">{</phrase> <phrase role="identifier">what</phrase> <phrase role="special">},</phrase>
|
||
|
<phrase role="identifier">f</phrase><phrase role="special">{</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">move</phrase><phrase role="special">(</phrase><phrase role="identifier">f_</phrase><phrase role="special">)</phrase> <phrase role="special">}</phrase> <phrase role="special">{</phrase>
|
||
|
<phrase role="special">}</phrase>
|
||
|
<phrase role="special">};</phrase>
|
||
|
|
||
|
<phrase role="identifier">ctx</phrase><phrase role="special">::</phrase><phrase role="identifier">fiber</phrase> <phrase role="identifier">f</phrase><phrase role="special">{[](</phrase><phrase role="identifier">ctx</phrase><phrase role="special">::</phrase><phrase role="identifier">fiber</phrase> <phrase role="special">&&</phrase> <phrase role="identifier">f</phrase><phrase role="special">)</phrase> <phrase role="special">-></phrase><phrase role="identifier">ctx</phrase><phrase role="special">::</phrase><phrase role="identifier">fiber</phrase> <phrase role="special">{</phrase>
|
||
|
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cout</phrase> <phrase role="special"><<</phrase> <phrase role="string">"entered"</phrase> <phrase role="special"><<</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">endl</phrase><phrase role="special">;</phrase>
|
||
|
<phrase role="keyword">try</phrase> <phrase role="special">{</phrase>
|
||
|
<phrase role="identifier">f</phrase><phrase role="special">=</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">move</phrase><phrase role="special">(</phrase><phrase role="identifier">f</phrase><phrase role="special">).</phrase><phrase role="identifier">resume</phrase><phrase role="special">();</phrase>
|
||
|
<phrase role="special">}</phrase> <phrase role="keyword">catch</phrase> <phrase role="special">(</phrase><phrase role="identifier">my_exception</phrase> <phrase role="special">&</phrase> <phrase role="identifier">ex</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
|
||
|
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cerr</phrase> <phrase role="special"><<</phrase> <phrase role="string">"my_exception: "</phrase> <phrase role="special"><<</phrase> <phrase role="identifier">ex</phrase><phrase role="special">.</phrase><phrase role="identifier">what</phrase><phrase role="special">()</phrase> <phrase role="special"><<</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">endl</phrase><phrase role="special">;</phrase>
|
||
|
<phrase role="keyword">return</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">move</phrase><phrase role="special">(</phrase><phrase role="identifier">ex</phrase><phrase role="special">.</phrase><phrase role="identifier">f</phrase><phrase role="special">);</phrase>
|
||
|
<phrase role="special">}</phrase>
|
||
|
<phrase role="keyword">return</phrase> <phrase role="special">{};</phrase>
|
||
|
<phrase role="special">});</phrase>
|
||
|
<phrase role="identifier">f</phrase><phrase role="special">=</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">move</phrase><phrase role="special">(</phrase><phrase role="identifier">f</phrase><phrase role="special">).</phrase><phrase role="identifier">resume</phrase><phrase role="special">();</phrase>
|
||
|
<phrase role="identifier">f</phrase><phrase role="special">=</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">move</phrase><phrase role="special">(</phrase><phrase role="identifier">f</phrase><phrase role="special">).</phrase><phrase role="identifier">resume_with</phrase><phrase role="special">([](</phrase><phrase role="identifier">ctx</phrase><phrase role="special">::</phrase><phrase role="identifier">fiber</phrase> <phrase role="special">&&</phrase> <phrase role="identifier">f</phrase><phrase role="special">)</phrase> <phrase role="special">-></phrase><phrase role="identifier">ctx</phrase><phrase role="special">::</phrase><phrase role="identifier">fiber</phrase> <phrase role="special">{</phrase>
|
||
|
<phrase role="keyword">throw</phrase> <phrase role="identifier">my_exception</phrase><phrase role="special">(</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">move</phrase><phrase role="special">(</phrase><phrase role="identifier">f</phrase><phrase role="special">),</phrase><phrase role="string">"abc"</phrase><phrase role="special">);</phrase>
|
||
|
<phrase role="keyword">return</phrase> <phrase role="special">{};</phrase>
|
||
|
<phrase role="special">});</phrase>
|
||
|
|
||
|
<phrase role="identifier">output</phrase><phrase role="special">:</phrase>
|
||
|
<phrase role="identifier">entered</phrase>
|
||
|
<phrase role="identifier">my_exception</phrase><phrase role="special">:</phrase> <phrase role="identifier">abc</phrase>
|
||
|
</programlisting>
|
||
|
<para>
|
||
|
In this exception <code><phrase role="identifier">my_exception</phrase></code>
|
||
|
is throw from a function invoked on-top of fiber <code><phrase role="identifier">f</phrase></code>
|
||
|
and catched inside the <code><phrase role="keyword">for</phrase></code>-loop.
|
||
|
</para>
|
||
|
<bridgehead renderas="sect3" id="context.ff.h5">
|
||
|
<phrase id="context.ff.stack_unwinding"/><link linkend="context.ff.stack_unwinding">Stack
|
||
|
unwinding</link>
|
||
|
</bridgehead>
|
||
|
<para>
|
||
|
On construction of <link linkend="ff"><emphasis>fiber</emphasis></link> a stack
|
||
|
is allocated. If the <emphasis>context-function</emphasis> returns the stack
|
||
|
will be destructed. If the <emphasis>context-function</emphasis> has not yet
|
||
|
returned and the destructor of an valid <link linkend="ff"><emphasis>fiber</emphasis></link>
|
||
|
instance (e.g. <emphasis>fiber::operator bool()</emphasis> returns <code><phrase
|
||
|
role="keyword">true</phrase></code>) is called, the stack will be destructed
|
||
|
too.
|
||
|
</para>
|
||
|
<important>
|
||
|
<para>
|
||
|
Code executed by <emphasis>context-function</emphasis> must not prevent the
|
||
|
propagation ofs the <emphasis>detail::forced_unwind</emphasis> exception.
|
||
|
Absorbing that exception will cause stack unwinding to fail. Thus, any code
|
||
|
that catches all exceptions must re-throw any pending <emphasis>detail::forced_unwind</emphasis>
|
||
|
exception.
|
||
|
</para>
|
||
|
</important>
|
||
|
<anchor id="ff_prealloc"/>
|
||
|
<bridgehead renderas="sect3" id="context.ff.h6">
|
||
|
<phrase id="context.ff.allocating_control_structures_on_top_of_stack"/><link
|
||
|
linkend="context.ff.allocating_control_structures_on_top_of_stack">Allocating
|
||
|
control structures on top of stack</link>
|
||
|
</bridgehead>
|
||
|
<para>
|
||
|
Allocating control structures on top of the stack requires to allocated the
|
||
|
<emphasis>stack_context</emphasis> and create the control structure with placement
|
||
|
new before <link linkend="ff"><emphasis>fiber</emphasis></link> is created.
|
||
|
</para>
|
||
|
<note>
|
||
|
<para>
|
||
|
The user is responsible for destructing the control structure at the top
|
||
|
of the stack.
|
||
|
</para>
|
||
|
</note>
|
||
|
<programlisting><phrase role="keyword">namespace</phrase> <phrase role="identifier">ctx</phrase><phrase role="special">=</phrase><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">context</phrase><phrase role="special">;</phrase>
|
||
|
<phrase role="comment">// stack-allocator used for (de-)allocating stack</phrase>
|
||
|
<phrase role="identifier">fixedsize_stack</phrase> <phrase role="identifier">salloc</phrase><phrase role="special">(</phrase><phrase role="number">4048</phrase><phrase role="special">);</phrase>
|
||
|
<phrase role="comment">// allocate stack space</phrase>
|
||
|
<phrase role="identifier">stack_context</phrase> <phrase role="identifier">sctx</phrase><phrase role="special">(</phrase><phrase role="identifier">salloc</phrase><phrase role="special">.</phrase><phrase role="identifier">allocate</phrase><phrase role="special">());</phrase>
|
||
|
<phrase role="comment">// reserve space for control structure on top of the stack</phrase>
|
||
|
<phrase role="keyword">void</phrase> <phrase role="special">*</phrase> <phrase role="identifier">sp</phrase><phrase role="special">=</phrase><phrase role="keyword">static_cast</phrase><phrase role="special"><</phrase><phrase role="keyword">char</phrase><phrase role="special">*>(</phrase><phrase role="identifier">sctx</phrase><phrase role="special">.</phrase><phrase role="identifier">sp</phrase><phrase role="special">)-</phrase><phrase role="keyword">sizeof</phrase><phrase role="special">(</phrase><phrase role="identifier">my_control_structure</phrase><phrase role="special">);</phrase>
|
||
|
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">size</phrase><phrase role="special">=</phrase><phrase role="identifier">sctx</phrase><phrase role="special">.</phrase><phrase role="identifier">size</phrase><phrase role="special">-</phrase><phrase role="keyword">sizeof</phrase><phrase role="special">(</phrase><phrase role="identifier">my_control_structure</phrase><phrase role="special">);</phrase>
|
||
|
<phrase role="comment">// placement new creates control structure on reserved space</phrase>
|
||
|
<phrase role="identifier">my_control_structure</phrase> <phrase role="special">*</phrase> <phrase role="identifier">cs</phrase><phrase role="special">=</phrase><phrase role="keyword">new</phrase><phrase role="special">(</phrase><phrase role="identifier">sp</phrase><phrase role="special">)</phrase><phrase role="identifier">my_control_structure</phrase><phrase role="special">(</phrase><phrase role="identifier">sp</phrase><phrase role="special">,</phrase><phrase role="identifier">size</phrase><phrase role="special">,</phrase><phrase role="identifier">sctx</phrase><phrase role="special">,</phrase><phrase role="identifier">salloc</phrase><phrase role="special">);</phrase>
|
||
|
<phrase role="special">...</phrase>
|
||
|
<phrase role="comment">// destructing the control structure</phrase>
|
||
|
<phrase role="identifier">cs</phrase><phrase role="special">->~</phrase><phrase role="identifier">my_control_structure</phrase><phrase role="special">();</phrase>
|
||
|
<phrase role="special">...</phrase>
|
||
|
<phrase role="keyword">struct</phrase> <phrase role="identifier">my_control_structure</phrase> <phrase role="special">{</phrase>
|
||
|
<phrase role="comment">// captured fiber</phrase>
|
||
|
<phrase role="identifier">ctx</phrase><phrase role="special">::</phrase><phrase role="identifier">fiber</phrase> <phrase role="identifier">f</phrase><phrase role="special">;</phrase>
|
||
|
|
||
|
<phrase role="keyword">template</phrase><phrase role="special"><</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">StackAllocator</phrase> <phrase role="special">></phrase>
|
||
|
<phrase role="identifier">my_control_structure</phrase><phrase role="special">(</phrase><phrase role="keyword">void</phrase> <phrase role="special">*</phrase> <phrase role="identifier">sp</phrase><phrase role="special">,</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">size</phrase><phrase role="special">,</phrase><phrase role="identifier">stack_context</phrase> <phrase role="identifier">sctx</phrase><phrase role="special">,</phrase><phrase role="identifier">StackAllocator</phrase> <phrase role="identifier">salloc</phrase><phrase role="special">)</phrase> <phrase role="special">:</phrase>
|
||
|
<phrase role="comment">// create captured fiber</phrase>
|
||
|
<phrase role="identifier">f</phrase><phrase role="special">{</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">allocator_arg</phrase><phrase role="special">,</phrase><phrase role="identifier">preallocated</phrase><phrase role="special">(</phrase><phrase role="identifier">sp</phrase><phrase role="special">,</phrase><phrase role="identifier">size</phrase><phrase role="special">,</phrase><phrase role="identifier">sctx</phrase><phrase role="special">),</phrase><phrase role="identifier">salloc</phrase><phrase role="special">,</phrase><phrase role="identifier">entry_func</phrase><phrase role="special">}</phrase> <phrase role="special">{</phrase>
|
||
|
<phrase role="special">}</phrase>
|
||
|
<phrase role="special">...</phrase>
|
||
|
<phrase role="special">};</phrase>
|
||
|
</programlisting>
|
||
|
<bridgehead renderas="sect3" id="context.ff.h7">
|
||
|
<phrase id="context.ff.inverting_the_control_flow"/><link linkend="context.ff.inverting_the_control_flow">Inverting
|
||
|
the control flow</link>
|
||
|
</bridgehead>
|
||
|
<programlisting><phrase role="keyword">namespace</phrase> <phrase role="identifier">ctx</phrase><phrase role="special">=</phrase><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">context</phrase><phrase role="special">;</phrase>
|
||
|
<phrase role="comment">/*
|
||
|
* grammar:
|
||
|
* P ---> E '\0'
|
||
|
* E ---> T {('+'|'-') T}
|
||
|
* T ---> S {('*'|'/') S}
|
||
|
* S ---> digit | '(' E ')'
|
||
|
*/</phrase>
|
||
|
<phrase role="keyword">class</phrase> <phrase role="identifier">Parser</phrase><phrase role="special">{</phrase>
|
||
|
<phrase role="keyword">char</phrase> <phrase role="identifier">next</phrase><phrase role="special">;</phrase>
|
||
|
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">istream</phrase><phrase role="special">&</phrase> <phrase role="identifier">is</phrase><phrase role="special">;</phrase>
|
||
|
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">function</phrase><phrase role="special"><</phrase><phrase role="keyword">void</phrase><phrase role="special">(</phrase><phrase role="keyword">char</phrase><phrase role="special">)></phrase> <phrase role="identifier">cb</phrase><phrase role="special">;</phrase>
|
||
|
|
||
|
<phrase role="keyword">char</phrase> <phrase role="identifier">pull</phrase><phrase role="special">(){</phrase>
|
||
|
<phrase role="keyword">return</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">char_traits</phrase><phrase role="special"><</phrase><phrase role="keyword">char</phrase><phrase role="special">>::</phrase><phrase role="identifier">to_char_type</phrase><phrase role="special">(</phrase><phrase role="identifier">is</phrase><phrase role="special">.</phrase><phrase role="identifier">get</phrase><phrase role="special">());</phrase>
|
||
|
<phrase role="special">}</phrase>
|
||
|
|
||
|
<phrase role="keyword">void</phrase> <phrase role="identifier">scan</phrase><phrase role="special">(){</phrase>
|
||
|
<phrase role="keyword">do</phrase><phrase role="special">{</phrase>
|
||
|
<phrase role="identifier">next</phrase><phrase role="special">=</phrase><phrase role="identifier">pull</phrase><phrase role="special">();</phrase>
|
||
|
<phrase role="special">}</phrase>
|
||
|
<phrase role="keyword">while</phrase><phrase role="special">(</phrase><phrase role="identifier">isspace</phrase><phrase role="special">(</phrase><phrase role="identifier">next</phrase><phrase role="special">));</phrase>
|
||
|
<phrase role="special">}</phrase>
|
||
|
|
||
|
<phrase role="keyword">public</phrase><phrase role="special">:</phrase>
|
||
|
<phrase role="identifier">Parser</phrase><phrase role="special">(</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">istream</phrase><phrase role="special">&</phrase> <phrase role="identifier">is_</phrase><phrase role="special">,</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">function</phrase><phrase role="special"><</phrase><phrase role="keyword">void</phrase><phrase role="special">(</phrase><phrase role="keyword">char</phrase><phrase role="special">)></phrase> <phrase role="identifier">cb_</phrase><phrase role="special">)</phrase> <phrase role="special">:</phrase>
|
||
|
<phrase role="identifier">next</phrase><phrase role="special">(),</phrase> <phrase role="identifier">is</phrase><phrase role="special">(</phrase><phrase role="identifier">is_</phrase><phrase role="special">),</phrase> <phrase role="identifier">cb</phrase><phrase role="special">(</phrase><phrase role="identifier">cb_</phrase><phrase role="special">)</phrase>
|
||
|
<phrase role="special">{}</phrase>
|
||
|
|
||
|
<phrase role="keyword">void</phrase> <phrase role="identifier">run</phrase><phrase role="special">()</phrase> <phrase role="special">{</phrase>
|
||
|
<phrase role="identifier">scan</phrase><phrase role="special">();</phrase>
|
||
|
<phrase role="identifier">E</phrase><phrase role="special">();</phrase>
|
||
|
<phrase role="special">}</phrase>
|
||
|
|
||
|
<phrase role="keyword">private</phrase><phrase role="special">:</phrase>
|
||
|
<phrase role="keyword">void</phrase> <phrase role="identifier">E</phrase><phrase role="special">(){</phrase>
|
||
|
<phrase role="identifier">T</phrase><phrase role="special">();</phrase>
|
||
|
<phrase role="keyword">while</phrase> <phrase role="special">(</phrase><phrase role="identifier">next</phrase><phrase role="special">==</phrase><phrase role="char">'+'</phrase><phrase role="special">||</phrase><phrase role="identifier">next</phrase><phrase role="special">==</phrase><phrase role="char">'-'</phrase><phrase role="special">){</phrase>
|
||
|
<phrase role="identifier">cb</phrase><phrase role="special">(</phrase><phrase role="identifier">next</phrase><phrase role="special">);</phrase>
|
||
|
<phrase role="identifier">scan</phrase><phrase role="special">();</phrase>
|
||
|
<phrase role="identifier">T</phrase><phrase role="special">();</phrase>
|
||
|
<phrase role="special">}</phrase>
|
||
|
<phrase role="special">}</phrase>
|
||
|
|
||
|
<phrase role="keyword">void</phrase> <phrase role="identifier">T</phrase><phrase role="special">(){</phrase>
|
||
|
<phrase role="identifier">S</phrase><phrase role="special">();</phrase>
|
||
|
<phrase role="keyword">while</phrase> <phrase role="special">(</phrase><phrase role="identifier">next</phrase><phrase role="special">==</phrase><phrase role="char">'*'</phrase><phrase role="special">||</phrase><phrase role="identifier">next</phrase><phrase role="special">==</phrase><phrase role="char">'/'</phrase><phrase role="special">){</phrase>
|
||
|
<phrase role="identifier">cb</phrase><phrase role="special">(</phrase><phrase role="identifier">next</phrase><phrase role="special">);</phrase>
|
||
|
<phrase role="identifier">scan</phrase><phrase role="special">();</phrase>
|
||
|
<phrase role="identifier">S</phrase><phrase role="special">();</phrase>
|
||
|
<phrase role="special">}</phrase>
|
||
|
<phrase role="special">}</phrase>
|
||
|
|
||
|
<phrase role="keyword">void</phrase> <phrase role="identifier">S</phrase><phrase role="special">(){</phrase>
|
||
|
<phrase role="keyword">if</phrase> <phrase role="special">(</phrase><phrase role="identifier">isdigit</phrase><phrase role="special">(</phrase><phrase role="identifier">next</phrase><phrase role="special">)){</phrase>
|
||
|
<phrase role="identifier">cb</phrase><phrase role="special">(</phrase><phrase role="identifier">next</phrase><phrase role="special">);</phrase>
|
||
|
<phrase role="identifier">scan</phrase><phrase role="special">();</phrase>
|
||
|
<phrase role="special">}</phrase>
|
||
|
<phrase role="keyword">else</phrase> <phrase role="keyword">if</phrase><phrase role="special">(</phrase><phrase role="identifier">next</phrase><phrase role="special">==</phrase><phrase role="char">'('</phrase><phrase role="special">){</phrase>
|
||
|
<phrase role="identifier">cb</phrase><phrase role="special">(</phrase><phrase role="identifier">next</phrase><phrase role="special">);</phrase>
|
||
|
<phrase role="identifier">scan</phrase><phrase role="special">();</phrase>
|
||
|
<phrase role="identifier">E</phrase><phrase role="special">();</phrase>
|
||
|
<phrase role="keyword">if</phrase> <phrase role="special">(</phrase><phrase role="identifier">next</phrase><phrase role="special">==</phrase><phrase role="char">')'</phrase><phrase role="special">){</phrase>
|
||
|
<phrase role="identifier">cb</phrase><phrase role="special">(</phrase><phrase role="identifier">next</phrase><phrase role="special">);</phrase>
|
||
|
<phrase role="identifier">scan</phrase><phrase role="special">();</phrase>
|
||
|
<phrase role="special">}</phrase><phrase role="keyword">else</phrase><phrase role="special">{</phrase>
|
||
|
<phrase role="keyword">throw</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">runtime_error</phrase><phrase role="special">(</phrase><phrase role="string">"parsing failed"</phrase><phrase role="special">);</phrase>
|
||
|
<phrase role="special">}</phrase>
|
||
|
<phrase role="special">}</phrase>
|
||
|
<phrase role="keyword">else</phrase><phrase role="special">{</phrase>
|
||
|
<phrase role="keyword">throw</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">runtime_error</phrase><phrase role="special">(</phrase><phrase role="string">"parsing failed"</phrase><phrase role="special">);</phrase>
|
||
|
<phrase role="special">}</phrase>
|
||
|
<phrase role="special">}</phrase>
|
||
|
<phrase role="special">};</phrase>
|
||
|
|
||
|
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">istringstream</phrase> <phrase role="identifier">is</phrase><phrase role="special">(</phrase><phrase role="string">"1+1"</phrase><phrase role="special">);</phrase>
|
||
|
<phrase role="comment">// user-code pulls parsed data from parser</phrase>
|
||
|
<phrase role="comment">// invert control flow</phrase>
|
||
|
<phrase role="keyword">char</phrase> <phrase role="identifier">c</phrase><phrase role="special">;</phrase>
|
||
|
<phrase role="keyword">bool</phrase> <phrase role="identifier">done</phrase><phrase role="special">=</phrase><phrase role="keyword">false</phrase><phrase role="special">;</phrase>
|
||
|
<phrase role="comment">// execute parser in new fiber</phrase>
|
||
|
<phrase role="identifier">ctx</phrase><phrase role="special">::</phrase><phrase role="identifier">fiber</phrase> <phrase role="identifier">source</phrase><phrase role="special">{[&</phrase><phrase role="identifier">is</phrase><phrase role="special">,&</phrase><phrase role="identifier">c</phrase><phrase role="special">,&</phrase><phrase role="identifier">done</phrase><phrase role="special">](</phrase><phrase role="identifier">ctx</phrase><phrase role="special">::</phrase><phrase role="identifier">fiber</phrase><phrase role="special">&&</phrase> <phrase role="identifier">sink</phrase><phrase role="special">){</phrase>
|
||
|
<phrase role="comment">// create parser with callback function</phrase>
|
||
|
<phrase role="identifier">Parser</phrase> <phrase role="identifier">p</phrase><phrase role="special">(</phrase><phrase role="identifier">is</phrase><phrase role="special">,</phrase>
|
||
|
<phrase role="special">[&</phrase><phrase role="identifier">sink</phrase><phrase role="special">,&</phrase><phrase role="identifier">c</phrase><phrase role="special">](</phrase><phrase role="keyword">char</phrase> <phrase role="identifier">c_</phrase><phrase role="special">){</phrase>
|
||
|
<phrase role="comment">// resume main fiber</phrase>
|
||
|
<phrase role="identifier">c</phrase><phrase role="special">=</phrase><phrase role="identifier">c_</phrase><phrase role="special">;</phrase>
|
||
|
<phrase role="identifier">sink</phrase><phrase role="special">=</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">move</phrase><phrase role="special">(</phrase><phrase role="identifier">sink</phrase><phrase role="special">).</phrase><phrase role="identifier">resume</phrase><phrase role="special">();</phrase>
|
||
|
<phrase role="special">});</phrase>
|
||
|
<phrase role="comment">// start recursive parsing</phrase>
|
||
|
<phrase role="identifier">p</phrase><phrase role="special">.</phrase><phrase role="identifier">run</phrase><phrase role="special">();</phrase>
|
||
|
<phrase role="comment">// signal termination</phrase>
|
||
|
<phrase role="identifier">done</phrase><phrase role="special">=</phrase><phrase role="keyword">true</phrase><phrase role="special">;</phrase>
|
||
|
<phrase role="comment">// resume main fiber</phrase>
|
||
|
<phrase role="keyword">return</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">move</phrase><phrase role="special">(</phrase><phrase role="identifier">sink</phrase><phrase role="special">);</phrase>
|
||
|
<phrase role="special">}};</phrase>
|
||
|
<phrase role="identifier">source</phrase><phrase role="special">=</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">move</phrase><phrase role="special">(</phrase><phrase role="identifier">source</phrase><phrase role="special">).</phrase><phrase role="identifier">resume</phrase><phrase role="special">();</phrase>
|
||
|
<phrase role="keyword">while</phrase><phrase role="special">(!</phrase><phrase role="identifier">done</phrase><phrase role="special">){</phrase>
|
||
|
<phrase role="identifier">printf</phrase><phrase role="special">(</phrase><phrase role="string">"Parsed: %c\n"</phrase><phrase role="special">,</phrase><phrase role="identifier">c</phrase><phrase role="special">);</phrase>
|
||
|
<phrase role="identifier">source</phrase><phrase role="special">=</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">Move</phrase><phrase role="special">(</phrase><phrase role="identifier">source</phrase><phrase role="special">).</phrase><phrase role="identifier">resume</phrase><phrase role="special">();</phrase>
|
||
|
<phrase role="special">}</phrase>
|
||
|
|
||
|
<phrase role="identifier">output</phrase><phrase role="special">:</phrase>
|
||
|
<phrase role="identifier">Parsed</phrase><phrase role="special">:</phrase> <phrase role="number">1</phrase>
|
||
|
<phrase role="identifier">Parsed</phrase><phrase role="special">:</phrase> <phrase role="special">+</phrase>
|
||
|
<phrase role="identifier">Parsed</phrase><phrase role="special">:</phrase> <phrase role="number">1</phrase>
|
||
|
</programlisting>
|
||
|
<para>
|
||
|
In this example a recursive descent parser uses a callback to emit a newly
|
||
|
passed symbol. Using <link linkend="ff"><emphasis>fiber</emphasis></link> the
|
||
|
control flow can be inverted, e.g. the user-code pulls parsed symbols from
|
||
|
the parser - instead to get pushed from the parser (via callback).
|
||
|
</para>
|
||
|
<para>
|
||
|
The data (character) is transferred between the two fibers.
|
||
|
</para>
|
||
|
<section id="context.ff.implementations__fcontext_t__ucontext_t_and_winfiber">
|
||
|
<title><anchor id="implementation"/><link linkend="context.ff.implementations__fcontext_t__ucontext_t_and_winfiber">Implementations:
|
||
|
fcontext_t, ucontext_t and WinFiber</link></title>
|
||
|
<bridgehead renderas="sect4" id="context.ff.implementations__fcontext_t__ucontext_t_and_winfiber.h0">
|
||
|
<phrase id="context.ff.implementations__fcontext_t__ucontext_t_and_winfiber.fcontext_t"/><link
|
||
|
linkend="context.ff.implementations__fcontext_t__ucontext_t_and_winfiber.fcontext_t">fcontext_t</link>
|
||
|
</bridgehead>
|
||
|
<para>
|
||
|
The implementation uses <emphasis>fcontext_t</emphasis> per default. fcontext_t
|
||
|
is based on assembler and not available for all platforms. It provides a
|
||
|
much better performance than <emphasis>ucontext_t</emphasis> (the context
|
||
|
switch takes two magnitudes of order less CPU cycles; see section <link linkend="performance"><emphasis>performance</emphasis></link>)
|
||
|
and <emphasis>WinFiber</emphasis>.
|
||
|
</para>
|
||
|
<note>
|
||
|
<para>
|
||
|
Because the TIB (thread information block on Windows) is not fully described
|
||
|
in the MSDN, it might be possible that not all required TIB-parts are swapped.
|
||
|
Using WinFiber implementation migh be an alternative.
|
||
|
</para>
|
||
|
</note>
|
||
|
<bridgehead renderas="sect4" id="context.ff.implementations__fcontext_t__ucontext_t_and_winfiber.h1">
|
||
|
<phrase id="context.ff.implementations__fcontext_t__ucontext_t_and_winfiber.ucontext_t"/><link
|
||
|
linkend="context.ff.implementations__fcontext_t__ucontext_t_and_winfiber.ucontext_t">ucontext_t</link>
|
||
|
</bridgehead>
|
||
|
<para>
|
||
|
As an alternative, <ulink url="https://en.wikipedia.org/wiki/Setcontext"><emphasis>ucontext_t</emphasis></ulink>
|
||
|
can be used by compiling with <code><phrase role="identifier">BOOST_USE_UCONTEXT</phrase></code>
|
||
|
and b2 property <code><phrase role="identifier">context</phrase><phrase role="special">-</phrase><phrase
|
||
|
role="identifier">impl</phrase><phrase role="special">=</phrase><phrase role="identifier">ucontext</phrase></code>.
|
||
|
<emphasis>ucontext_t</emphasis> might be available on a broader range of
|
||
|
POSIX-platforms but has some <link linkend="ucontext"><emphasis>disadvantages</emphasis></link>
|
||
|
(for instance deprecated since POSIX.1-2003, not C99 conform).
|
||
|
</para>
|
||
|
<note>
|
||
|
<para>
|
||
|
<link linkend="ff"><emphasis>fiber</emphasis></link> supports <link linkend="segmented"><emphasis>Segmented
|
||
|
stacks</emphasis></link> only with <emphasis>ucontext_t</emphasis> as its
|
||
|
implementation.
|
||
|
</para>
|
||
|
</note>
|
||
|
<bridgehead renderas="sect4" id="context.ff.implementations__fcontext_t__ucontext_t_and_winfiber.h2">
|
||
|
<phrase id="context.ff.implementations__fcontext_t__ucontext_t_and_winfiber.winfiber"/><link
|
||
|
linkend="context.ff.implementations__fcontext_t__ucontext_t_and_winfiber.winfiber">WinFiber</link>
|
||
|
</bridgehead>
|
||
|
<para>
|
||
|
With <code><phrase role="identifier">BOOST_USE_WINFIB</phrase></code> and
|
||
|
b2 property <code><phrase role="identifier">context</phrase><phrase role="special">-</phrase><phrase
|
||
|
role="identifier">impl</phrase><phrase role="special">=</phrase><phrase role="identifier">winfib</phrase></code>
|
||
|
Win32-Fibers are used as implementation for <link linkend="ff"><emphasis>fiber</emphasis></link>.
|
||
|
</para>
|
||
|
<note>
|
||
|
<para>
|
||
|
The first call of <link linkend="ff"><emphasis>fiber</emphasis></link>
|
||
|
converts the thread into a Windows fiber by invoking <code><phrase role="identifier">ConvertThreadToFiber</phrase><phrase
|
||
|
role="special">()</phrase></code>. If desired, <code><phrase role="identifier">ConvertFiberToThread</phrase><phrase
|
||
|
role="special">()</phrase></code> has to be called by the user explicitly
|
||
|
in order to release resources allocated by <code><phrase role="identifier">ConvertThreadToFiber</phrase><phrase
|
||
|
role="special">()</phrase></code> (e.g. after using boost.context).
|
||
|
</para>
|
||
|
</note>
|
||
|
</section>
|
||
|
<section id="context.ff.class__fiber_">
|
||
|
<title><link linkend="context.ff.class__fiber_">Class <code><phrase role="identifier">fiber</phrase></code></link></title>
|
||
|
<programlisting><phrase role="preprocessor">#include</phrase> <phrase role="special"><</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">context</phrase><phrase role="special">/</phrase><phrase role="identifier">fiber</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">></phrase>
|
||
|
|
||
|
<phrase role="keyword">class</phrase> <phrase role="identifier">fiber</phrase> <phrase role="special">{</phrase>
|
||
|
<phrase role="keyword">public</phrase><phrase role="special">:</phrase>
|
||
|
<phrase role="identifier">fiber</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
|
||
|
|
||
|
<phrase role="keyword">template</phrase><phrase role="special"><</phrase><phrase role="keyword">typename</phrase> <phrase role="identifier">Fn</phrase><phrase role="special">></phrase>
|
||
|
<phrase role="identifier">fiber</phrase><phrase role="special">(</phrase><phrase role="identifier">Fn</phrase> <phrase role="special">&&</phrase> <phrase role="identifier">fn</phrase><phrase role="special">);</phrase>
|
||
|
|
||
|
<phrase role="keyword">template</phrase><phrase role="special"><</phrase><phrase role="keyword">typename</phrase> <phrase role="identifier">StackAlloc</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Fn</phrase><phrase role="special">></phrase>
|
||
|
<phrase role="identifier">fiber</phrase><phrase role="special">(</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">allocator_arg_t</phrase><phrase role="special">,</phrase> <phrase role="identifier">StackAlloc</phrase> <phrase role="special">&&</phrase> <phrase role="identifier">salloc</phrase><phrase role="special">,</phrase> <phrase role="identifier">Fn</phrase> <phrase role="special">&&</phrase> <phrase role="identifier">fn</phrase><phrase role="special">);</phrase>
|
||
|
|
||
|
<phrase role="special">~</phrase><phrase role="identifier">fiber</phrase><phrase role="special">();</phrase>
|
||
|
|
||
|
<phrase role="identifier">fiber</phrase><phrase role="special">(</phrase><phrase role="identifier">fiber</phrase> <phrase role="special">&&</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
|
||
|
|
||
|
<phrase role="identifier">fiber</phrase> <phrase role="special">&</phrase> <phrase role="keyword">operator</phrase><phrase role="special">=(</phrase><phrase role="identifier">fiber</phrase> <phrase role="special">&&</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
|
||
|
|
||
|
<phrase role="identifier">fiber</phrase><phrase role="special">(</phrase><phrase role="identifier">fiber</phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase> <phrase role="special">=</phrase> <phrase role="keyword">delete</phrase><phrase role="special">;</phrase>
|
||
|
<phrase role="identifier">fiber</phrase> <phrase role="special">&</phrase> <phrase role="keyword">operator</phrase><phrase role="special">=(</phrase><phrase role="identifier">fiber</phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase> <phrase role="special">=</phrase> <phrase role="keyword">delete</phrase><phrase role="special">;</phrase>
|
||
|
|
||
|
<phrase role="identifier">fiber</phrase> <phrase role="identifier">resume</phrase><phrase role="special">()</phrase> <phrase role="special">&&;</phrase>
|
||
|
|
||
|
<phrase role="keyword">template</phrase><phrase role="special"><</phrase><phrase role="keyword">typename</phrase> <phrase role="identifier">Fn</phrase><phrase role="special">></phrase>
|
||
|
<phrase role="identifier">fiber</phrase> <phrase role="identifier">resume_with</phrase><phrase role="special">(</phrase><phrase role="identifier">Fn</phrase> <phrase role="special">&&</phrase> <phrase role="identifier">fn</phrase><phrase role="special">)</phrase> <phrase role="special">&&;</phrase>
|
||
|
|
||
|
<phrase role="keyword">explicit</phrase> <phrase role="keyword">operator</phrase> <phrase role="keyword">bool</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
|
||
|
|
||
|
<phrase role="keyword">bool</phrase> <phrase role="keyword">operator</phrase><phrase role="special">!()</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
|
||
|
|
||
|
<phrase role="keyword">bool</phrase> <phrase role="keyword">operator</phrase><phrase role="special">==(</phrase><phrase role="identifier">fiber</phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
|
||
|
|
||
|
<phrase role="keyword">bool</phrase> <phrase role="keyword">operator</phrase><phrase role="special">!=(</phrase><phrase role="identifier">fiber</phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
|
||
|
|
||
|
<phrase role="keyword">bool</phrase> <phrase role="keyword">operator</phrase><phrase role="special"><(</phrase><phrase role="identifier">fiber</phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
|
||
|
|
||
|
<phrase role="keyword">bool</phrase> <phrase role="keyword">operator</phrase><phrase role="special">>(</phrase><phrase role="identifier">fiber</phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
|
||
|
|
||
|
<phrase role="keyword">bool</phrase> <phrase role="keyword">operator</phrase><phrase role="special"><=(</phrase><phrase role="identifier">fiber</phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
|
||
|
|
||
|
<phrase role="keyword">bool</phrase> <phrase role="keyword">operator</phrase><phrase role="special">>=(</phrase><phrase role="identifier">fiber</phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
|
||
|
|
||
|
<phrase role="keyword">template</phrase><phrase role="special"><</phrase><phrase role="keyword">typename</phrase> <phrase role="identifier">charT</phrase><phrase role="special">,</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">traitsT</phrase><phrase role="special">></phrase>
|
||
|
<phrase role="keyword">friend</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">basic_ostream</phrase><phrase role="special"><</phrase><phrase role="identifier">charT</phrase><phrase role="special">,</phrase><phrase role="identifier">traitsT</phrase><phrase role="special">></phrase> <phrase role="special">&</phrase>
|
||
|
<phrase role="keyword">operator</phrase><phrase role="special"><<(</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">basic_ostream</phrase><phrase role="special"><</phrase><phrase role="identifier">charT</phrase><phrase role="special">,</phrase><phrase role="identifier">traitsT</phrase><phrase role="special">></phrase> <phrase role="special">&</phrase> <phrase role="identifier">os</phrase><phrase role="special">,</phrase><phrase role="identifier">fiber</phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
|
||
|
|
||
|
<phrase role="keyword">void</phrase> <phrase role="identifier">swap</phrase><phrase role="special">(</phrase><phrase role="identifier">fiber</phrase> <phrase role="special">&</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
|
||
|
<phrase role="special">};</phrase>
|
||
|
</programlisting>
|
||
|
<para>
|
||
|
<bridgehead renderas="sect4" id="ff_constructor1_bridgehead">
|
||
|
<phrase id="ff_constructor1"/>
|
||
|
<link linkend="ff_constructor1">Constructor</link>
|
||
|
</bridgehead>
|
||
|
</para>
|
||
|
<programlisting><phrase role="identifier">fiber</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
|
||
|
</programlisting>
|
||
|
<variablelist>
|
||
|
<title></title>
|
||
|
<varlistentry>
|
||
|
<term>Effects:</term>
|
||
|
<listitem>
|
||
|
<para>
|
||
|
Creates a invalid fiber.
|
||
|
</para>
|
||
|
</listitem>
|
||
|
</varlistentry>
|
||
|
<varlistentry>
|
||
|
<term>Throws:</term>
|
||
|
<listitem>
|
||
|
<para>
|
||
|
Nothing.
|
||
|
</para>
|
||
|
</listitem>
|
||
|
</varlistentry>
|
||
|
</variablelist>
|
||
|
<para>
|
||
|
<bridgehead renderas="sect4" id="ff_constructor2_bridgehead">
|
||
|
<phrase id="ff_constructor2"/>
|
||
|
<link linkend="ff_constructor2">Constructor</link>
|
||
|
</bridgehead>
|
||
|
</para>
|
||
|
<programlisting><phrase role="keyword">template</phrase><phrase role="special"><</phrase><phrase role="keyword">typename</phrase> <phrase role="identifier">Fn</phrase><phrase role="special">></phrase>
|
||
|
<phrase role="identifier">fiber</phrase><phrase role="special">(</phrase><phrase role="identifier">Fn</phrase> <phrase role="special">&&</phrase> <phrase role="identifier">fn</phrase><phrase role="special">);</phrase>
|
||
|
|
||
|
<phrase role="keyword">template</phrase><phrase role="special"><</phrase><phrase role="keyword">typename</phrase> <phrase role="identifier">StackAlloc</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Fn</phrase><phrase role="special">></phrase>
|
||
|
<phrase role="identifier">fiber</phrase><phrase role="special">(</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">allocator_arg_t</phrase><phrase role="special">,</phrase> <phrase role="identifier">StackAlloc</phrase> <phrase role="special">&&</phrase> <phrase role="identifier">salloc</phrase><phrase role="special">,</phrase> <phrase role="identifier">Fn</phrase> <phrase role="special">&&</phrase> <phrase role="identifier">fn</phrase><phrase role="special">);</phrase>
|
||
|
</programlisting>
|
||
|
<variablelist>
|
||
|
<title></title>
|
||
|
<varlistentry>
|
||
|
<term>Effects:</term>
|
||
|
<listitem>
|
||
|
<para>
|
||
|
Creates a new fiber and prepares the context to execute <code><phrase
|
||
|
role="identifier">fn</phrase></code>. <code><phrase role="identifier">fixedsize_stack</phrase></code>
|
||
|
is used as default stack allocator (stack size == fixedsize_stack::traits::default_size()).
|
||
|
The constructor with argument type <code><phrase role="identifier">preallocated</phrase></code>,
|
||
|
is used to create a user defined data <link linkend="ff_prealloc">(for
|
||
|
instance additional control structures)</link> on top of the stack.
|
||
|
</para>
|
||
|
</listitem>
|
||
|
</varlistentry>
|
||
|
</variablelist>
|
||
|
<para>
|
||
|
<bridgehead renderas="sect4" id="ff_destructor destructor_bridgehead">
|
||
|
<phrase id="ff_destructor destructor"/>
|
||
|
<link linkend="ff_destructor
|
||
|
destructor">Destructor</link>
|
||
|
</bridgehead>
|
||
|
</para>
|
||
|
<programlisting><phrase role="special">~</phrase><phrase role="identifier">fiber</phrase><phrase role="special">();</phrase>
|
||
|
</programlisting>
|
||
|
<variablelist>
|
||
|
<title></title>
|
||
|
<varlistentry>
|
||
|
<term>Effects:</term>
|
||
|
<listitem>
|
||
|
<para>
|
||
|
Destructs the associated stack if <code><phrase role="special">*</phrase><phrase
|
||
|
role="keyword">this</phrase></code> is a valid fiber, e.g. <emphasis>fiber::operator
|
||
|
bool()</emphasis> returns <code><phrase role="keyword">true</phrase></code>.
|
||
|
</para>
|
||
|
</listitem>
|
||
|
</varlistentry>
|
||
|
<varlistentry>
|
||
|
<term>Throws:</term>
|
||
|
<listitem>
|
||
|
<para>
|
||
|
Nothing.
|
||
|
</para>
|
||
|
</listitem>
|
||
|
</varlistentry>
|
||
|
</variablelist>
|
||
|
<para>
|
||
|
<bridgehead renderas="sect4" id="ff_move constructor_bridgehead">
|
||
|
<phrase id="ff_move constructor"/>
|
||
|
<link linkend="ff_move constructor">Move
|
||
|
constructor</link>
|
||
|
</bridgehead>
|
||
|
</para>
|
||
|
<programlisting><phrase role="identifier">fiber</phrase><phrase role="special">(</phrase><phrase role="identifier">fiber</phrase> <phrase role="special">&&</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
|
||
|
</programlisting>
|
||
|
<variablelist>
|
||
|
<title></title>
|
||
|
<varlistentry>
|
||
|
<term>Effects:</term>
|
||
|
<listitem>
|
||
|
<para>
|
||
|
Moves underlying capture fiber to <code><phrase role="special">*</phrase><phrase
|
||
|
role="keyword">this</phrase></code>.
|
||
|
</para>
|
||
|
</listitem>
|
||
|
</varlistentry>
|
||
|
<varlistentry>
|
||
|
<term>Throws:</term>
|
||
|
<listitem>
|
||
|
<para>
|
||
|
Nothing.
|
||
|
</para>
|
||
|
</listitem>
|
||
|
</varlistentry>
|
||
|
</variablelist>
|
||
|
<para>
|
||
|
<bridgehead renderas="sect4" id="ff_move assignment_bridgehead">
|
||
|
<phrase id="ff_move assignment"/>
|
||
|
<link linkend="ff_move assignment">Move assignment
|
||
|
operator</link>
|
||
|
</bridgehead>
|
||
|
</para>
|
||
|
<programlisting><phrase role="identifier">fiber</phrase> <phrase role="special">&</phrase> <phrase role="keyword">operator</phrase><phrase role="special">=(</phrase><phrase role="identifier">fiber</phrase> <phrase role="special">&&</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
|
||
|
</programlisting>
|
||
|
<variablelist>
|
||
|
<title></title>
|
||
|
<varlistentry>
|
||
|
<term>Effects:</term>
|
||
|
<listitem>
|
||
|
<para>
|
||
|
Moves the state of <code><phrase role="identifier">other</phrase></code>
|
||
|
to <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>
|
||
|
using move semantics.
|
||
|
</para>
|
||
|
</listitem>
|
||
|
</varlistentry>
|
||
|
<varlistentry>
|
||
|
<term>Throws:</term>
|
||
|
<listitem>
|
||
|
<para>
|
||
|
Nothing.
|
||
|
</para>
|
||
|
</listitem>
|
||
|
</varlistentry>
|
||
|
</variablelist>
|
||
|
<para>
|
||
|
<bridgehead renderas="sect4" id="ff_operator_call_bridgehead">
|
||
|
<phrase id="ff_operator_call"/>
|
||
|
<link linkend="ff_operator_call">Member function
|
||
|
<code>operator()</code>()</link>
|
||
|
</bridgehead>
|
||
|
</para>
|
||
|
<programlisting><phrase role="identifier">fiber</phrase> <phrase role="identifier">resume</phrase><phrase role="special">()</phrase> <phrase role="special">&&;</phrase>
|
||
|
|
||
|
<phrase role="keyword">template</phrase><phrase role="special"><</phrase><phrase role="keyword">typename</phrase> <phrase role="identifier">Fn</phrase><phrase role="special">></phrase>
|
||
|
<phrase role="identifier">fiber</phrase> <phrase role="identifier">resume_with</phrase><phrase role="special">(</phrase><phrase role="identifier">Fn</phrase> <phrase role="special">&&</phrase> <phrase role="identifier">fn</phrase><phrase role="special">)</phrase> <phrase role="special">&&;</phrase>
|
||
|
</programlisting>
|
||
|
<variablelist>
|
||
|
<title></title>
|
||
|
<varlistentry>
|
||
|
<term>Effects:</term>
|
||
|
<listitem>
|
||
|
<para>
|
||
|
Captures current fiber and resumes <code><phrase role="special">*</phrase><phrase
|
||
|
role="keyword">this</phrase></code>. The function <code><phrase role="identifier">resume_with</phrase></code>,
|
||
|
is used to execute function <code><phrase role="identifier">fn</phrase></code>
|
||
|
in the execution context of <code><phrase role="special">*</phrase><phrase
|
||
|
role="keyword">this</phrase></code> (e.g. the stack frame of <code><phrase
|
||
|
role="identifier">fn</phrase></code> is allocated on stack of <code><phrase
|
||
|
role="special">*</phrase><phrase role="keyword">this</phrase></code>).
|
||
|
</para>
|
||
|
</listitem>
|
||
|
</varlistentry>
|
||
|
<varlistentry>
|
||
|
<term>Returns:</term>
|
||
|
<listitem>
|
||
|
<para>
|
||
|
The fiber representing the fiber that has been suspended.
|
||
|
</para>
|
||
|
</listitem>
|
||
|
</varlistentry>
|
||
|
<varlistentry>
|
||
|
<term>Note:</term>
|
||
|
<listitem>
|
||
|
<para>
|
||
|
Because <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>
|
||
|
gets invalidated, <code><phrase role="identifier">resume</phrase><phrase
|
||
|
role="special">()</phrase></code> and <code><phrase role="identifier">resume_with</phrase><phrase
|
||
|
role="special">()</phrase></code> are rvalue-ref qualified and bind
|
||
|
only to rvalues.
|
||
|
</para>
|
||
|
</listitem>
|
||
|
</varlistentry>
|
||
|
<varlistentry>
|
||
|
<term>Note:</term>
|
||
|
<listitem>
|
||
|
<para>
|
||
|
Function <code><phrase role="identifier">fn</phrase></code> needs to
|
||
|
return <code><phrase role="identifier">fiber</phrase></code>.
|
||
|
</para>
|
||
|
</listitem>
|
||
|
</varlistentry>
|
||
|
<varlistentry>
|
||
|
<term>Note:</term>
|
||
|
<listitem>
|
||
|
<para>
|
||
|
The returned fiber indicates if the suspended fiber has terminated
|
||
|
(return from context-function) via <code><phrase role="keyword">bool</phrase>
|
||
|
<phrase role="keyword">operator</phrase><phrase role="special">()</phrase></code>.
|
||
|
</para>
|
||
|
</listitem>
|
||
|
</varlistentry>
|
||
|
</variablelist>
|
||
|
<para>
|
||
|
<bridgehead renderas="sect4" id="ff_operator_bool_bridgehead">
|
||
|
<phrase id="ff_operator_bool"/>
|
||
|
<link linkend="ff_operator_bool">Member function
|
||
|
<code>operator bool</code>()</link>
|
||
|
</bridgehead>
|
||
|
</para>
|
||
|
<programlisting><phrase role="keyword">explicit</phrase> <phrase role="keyword">operator</phrase> <phrase role="keyword">bool</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
|
||
|
</programlisting>
|
||
|
<variablelist>
|
||
|
<title></title>
|
||
|
<varlistentry>
|
||
|
<term>Returns:</term>
|
||
|
<listitem>
|
||
|
<para>
|
||
|
<code><phrase role="keyword">true</phrase></code> if <code><phrase
|
||
|
role="special">*</phrase><phrase role="keyword">this</phrase></code>
|
||
|
points to a captured fiber.
|
||
|
</para>
|
||
|
</listitem>
|
||
|
</varlistentry>
|
||
|
<varlistentry>
|
||
|
<term>Throws:</term>
|
||
|
<listitem>
|
||
|
<para>
|
||
|
Nothing.
|
||
|
</para>
|
||
|
</listitem>
|
||
|
</varlistentry>
|
||
|
</variablelist>
|
||
|
<para>
|
||
|
<bridgehead renderas="sect4" id="ff_operator_not_bridgehead">
|
||
|
<phrase id="ff_operator_not"/>
|
||
|
<link linkend="ff_operator_not">Member function <code>operator!</code>()</link>
|
||
|
</bridgehead>
|
||
|
</para>
|
||
|
<programlisting><phrase role="keyword">bool</phrase> <phrase role="keyword">operator</phrase><phrase role="special">!()</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
|
||
|
</programlisting>
|
||
|
<variablelist>
|
||
|
<title></title>
|
||
|
<varlistentry>
|
||
|
<term>Returns:</term>
|
||
|
<listitem>
|
||
|
<para>
|
||
|
<code><phrase role="keyword">true</phrase></code> if <code><phrase
|
||
|
role="special">*</phrase><phrase role="keyword">this</phrase></code>
|
||
|
does not point to a captured fiber.
|
||
|
</para>
|
||
|
</listitem>
|
||
|
</varlistentry>
|
||
|
<varlistentry>
|
||
|
<term>Throws:</term>
|
||
|
<listitem>
|
||
|
<para>
|
||
|
Nothing.
|
||
|
</para>
|
||
|
</listitem>
|
||
|
</varlistentry>
|
||
|
</variablelist>
|
||
|
<para>
|
||
|
<bridgehead renderas="sect4" id="ff_operator_equal_bridgehead">
|
||
|
<phrase id="ff_operator_equal"/>
|
||
|
<link linkend="ff_operator_equal">Member function
|
||
|
<code>operator==</code>()</link>
|
||
|
</bridgehead>
|
||
|
</para>
|
||
|
<programlisting><phrase role="keyword">bool</phrase> <phrase role="keyword">operator</phrase><phrase role="special">==(</phrase><phrase role="identifier">fiber</phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
|
||
|
</programlisting>
|
||
|
<variablelist>
|
||
|
<title></title>
|
||
|
<varlistentry>
|
||
|
<term>Returns:</term>
|
||
|
<listitem>
|
||
|
<para>
|
||
|
<code><phrase role="keyword">true</phrase></code> if <code><phrase
|
||
|
role="special">*</phrase><phrase role="keyword">this</phrase></code>
|
||
|
and <code><phrase role="identifier">other</phrase></code> represent
|
||
|
the same fiber, <code><phrase role="keyword">false</phrase></code>
|
||
|
otherwise.
|
||
|
</para>
|
||
|
</listitem>
|
||
|
</varlistentry>
|
||
|
<varlistentry>
|
||
|
<term>Throws:</term>
|
||
|
<listitem>
|
||
|
<para>
|
||
|
Nothing.
|
||
|
</para>
|
||
|
</listitem>
|
||
|
</varlistentry>
|
||
|
</variablelist>
|
||
|
<para>
|
||
|
<bridgehead renderas="sect4" id="ff_operator_notequal_bridgehead">
|
||
|
<phrase id="ff_operator_notequal"/>
|
||
|
<link linkend="ff_operator_notequal">Member
|
||
|
function <code>operator!=</code>()</link>
|
||
|
</bridgehead>
|
||
|
</para>
|
||
|
<programlisting><phrase role="keyword">bool</phrase> <phrase role="keyword">operator</phrase><phrase role="special">!=(</phrase><phrase role="identifier">fiber</phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
|
||
|
</programlisting>
|
||
|
<variablelist>
|
||
|
<title></title>
|
||
|
<varlistentry>
|
||
|
<term>Returns:</term>
|
||
|
<listitem>
|
||
|
<para>
|
||
|
<code>! (other == * this)</code>
|
||
|
</para>
|
||
|
</listitem>
|
||
|
</varlistentry>
|
||
|
<varlistentry>
|
||
|
<term>Throws:</term>
|
||
|
<listitem>
|
||
|
<para>
|
||
|
Nothing.
|
||
|
</para>
|
||
|
</listitem>
|
||
|
</varlistentry>
|
||
|
</variablelist>
|
||
|
<para>
|
||
|
<bridgehead renderas="sect4" id="ff_operator_less_bridgehead">
|
||
|
<phrase id="ff_operator_less"/>
|
||
|
<link linkend="ff_operator_less">Member function
|
||
|
<code>operator<</code>()</link>
|
||
|
</bridgehead>
|
||
|
</para>
|
||
|
<programlisting><phrase role="keyword">bool</phrase> <phrase role="keyword">operator</phrase><phrase role="special"><(</phrase><phrase role="identifier">fiber</phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
|
||
|
</programlisting>
|
||
|
<variablelist>
|
||
|
<title></title>
|
||
|
<varlistentry>
|
||
|
<term>Returns:</term>
|
||
|
<listitem>
|
||
|
<para>
|
||
|
<code><phrase role="keyword">true</phrase></code> if <code><phrase
|
||
|
role="special">*</phrase><phrase role="keyword">this</phrase> <phrase
|
||
|
role="special">!=</phrase> <phrase role="identifier">other</phrase></code>
|
||
|
is true and the implementation-defined total order of <code><phrase
|
||
|
role="identifier">fiber</phrase></code> values places <code><phrase
|
||
|
role="special">*</phrase><phrase role="keyword">this</phrase></code>
|
||
|
before <code><phrase role="identifier">other</phrase></code>, false
|
||
|
otherwise.
|
||
|
</para>
|
||
|
</listitem>
|
||
|
</varlistentry>
|
||
|
<varlistentry>
|
||
|
<term>Throws:</term>
|
||
|
<listitem>
|
||
|
<para>
|
||
|
Nothing.
|
||
|
</para>
|
||
|
</listitem>
|
||
|
</varlistentry>
|
||
|
</variablelist>
|
||
|
<para>
|
||
|
<bridgehead renderas="sect4" id="ff_operator_greater_bridgehead">
|
||
|
<phrase id="ff_operator_greater"/>
|
||
|
<link linkend="ff_operator_greater">Member
|
||
|
function <code>operator></code>()</link>
|
||
|
</bridgehead>
|
||
|
</para>
|
||
|
<programlisting><phrase role="keyword">bool</phrase> <phrase role="keyword">operator</phrase><phrase role="special">>(</phrase><phrase role="identifier">fiber</phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
|
||
|
</programlisting>
|
||
|
<variablelist>
|
||
|
<title></title>
|
||
|
<varlistentry>
|
||
|
<term>Returns:</term>
|
||
|
<listitem>
|
||
|
<para>
|
||
|
<code><phrase role="identifier">other</phrase> <phrase role="special"><</phrase>
|
||
|
<phrase role="special">*</phrase> <phrase role="keyword">this</phrase></code>
|
||
|
</para>
|
||
|
</listitem>
|
||
|
</varlistentry>
|
||
|
<varlistentry>
|
||
|
<term>Throws:</term>
|
||
|
<listitem>
|
||
|
<para>
|
||
|
Nothing.
|
||
|
</para>
|
||
|
</listitem>
|
||
|
</varlistentry>
|
||
|
</variablelist>
|
||
|
<para>
|
||
|
<bridgehead renderas="sect4" id="ff_operator_lesseq_bridgehead">
|
||
|
<phrase id="ff_operator_lesseq"/>
|
||
|
<link linkend="ff_operator_lesseq">Member function
|
||
|
<code>operator<=</code>()</link>
|
||
|
</bridgehead>
|
||
|
</para>
|
||
|
<programlisting><phrase role="keyword">bool</phrase> <phrase role="keyword">operator</phrase><phrase role="special"><=(</phrase><phrase role="identifier">fiber</phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
|
||
|
</programlisting>
|
||
|
<variablelist>
|
||
|
<title></title>
|
||
|
<varlistentry>
|
||
|
<term>Returns:</term>
|
||
|
<listitem>
|
||
|
<para>
|
||
|
<code><phrase role="special">!</phrase> <phrase role="special">(</phrase><phrase
|
||
|
role="identifier">other</phrase> <phrase role="special"><</phrase>
|
||
|
<phrase role="special">*</phrase> <phrase role="keyword">this</phrase><phrase
|
||
|
role="special">)</phrase></code>
|
||
|
</para>
|
||
|
</listitem>
|
||
|
</varlistentry>
|
||
|
<varlistentry>
|
||
|
<term>Throws:</term>
|
||
|
<listitem>
|
||
|
<para>
|
||
|
Nothing.
|
||
|
</para>
|
||
|
</listitem>
|
||
|
</varlistentry>
|
||
|
</variablelist>
|
||
|
<para>
|
||
|
<bridgehead renderas="sect4" id="ff_operator_greatereq_bridgehead">
|
||
|
<phrase id="ff_operator_greatereq"/>
|
||
|
<link linkend="ff_operator_greatereq">Member
|
||
|
function <code>operator>=</code>()</link>
|
||
|
</bridgehead>
|
||
|
</para>
|
||
|
<programlisting><phrase role="keyword">bool</phrase> <phrase role="keyword">operator</phrase><phrase role="special">>=(</phrase><phrase role="identifier">fiber</phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
|
||
|
</programlisting>
|
||
|
<variablelist>
|
||
|
<title></title>
|
||
|
<varlistentry>
|
||
|
<term>Returns:</term>
|
||
|
<listitem>
|
||
|
<para>
|
||
|
<code><phrase role="special">!</phrase> <phrase role="special">(*</phrase>
|
||
|
<phrase role="keyword">this</phrase> <phrase role="special"><</phrase>
|
||
|
<phrase role="identifier">other</phrase><phrase role="special">)</phrase></code>
|
||
|
</para>
|
||
|
</listitem>
|
||
|
</varlistentry>
|
||
|
<varlistentry>
|
||
|
<term>Throws:</term>
|
||
|
<listitem>
|
||
|
<para>
|
||
|
Nothing.
|
||
|
</para>
|
||
|
</listitem>
|
||
|
</varlistentry>
|
||
|
</variablelist>
|
||
|
<para>
|
||
|
<bridgehead renderas="sect4" id="ff__bridgehead">
|
||
|
<phrase id="ff_"/>
|
||
|
<link linkend="ff_">Non-member function <code>operator<<()</code></link>
|
||
|
</bridgehead>
|
||
|
</para>
|
||
|
<programlisting><phrase role="keyword">template</phrase><phrase role="special"><</phrase><phrase role="keyword">typename</phrase> <phrase role="identifier">charT</phrase><phrase role="special">,</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">traitsT</phrase><phrase role="special">></phrase>
|
||
|
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">basic_ostream</phrase><phrase role="special"><</phrase><phrase role="identifier">charT</phrase><phrase role="special">,</phrase><phrase role="identifier">traitsT</phrase><phrase role="special">></phrase> <phrase role="special">&</phrase>
|
||
|
<phrase role="keyword">operator</phrase><phrase role="special"><<(</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">basic_ostream</phrase><phrase role="special"><</phrase><phrase role="identifier">charT</phrase><phrase role="special">,</phrase><phrase role="identifier">traitsT</phrase><phrase role="special">></phrase> <phrase role="special">&</phrase> <phrase role="identifier">os</phrase><phrase role="special">,</phrase><phrase role="identifier">fiber</phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">other</phrase><phrase role="special">);</phrase>
|
||
|
</programlisting>
|
||
|
<variablelist>
|
||
|
<title></title>
|
||
|
<varlistentry>
|
||
|
<term>Effects:</term>
|
||
|
<listitem>
|
||
|
<para>
|
||
|
Writes the representation of <code><phrase role="identifier">other</phrase></code>
|
||
|
to stream <code><phrase role="identifier">os</phrase></code>.
|
||
|
</para>
|
||
|
</listitem>
|
||
|
</varlistentry>
|
||
|
<varlistentry>
|
||
|
<term>Returns:</term>
|
||
|
<listitem>
|
||
|
<para>
|
||
|
<code><phrase role="identifier">os</phrase></code>
|
||
|
</para>
|
||
|
</listitem>
|
||
|
</varlistentry>
|
||
|
</variablelist>
|
||
|
</section>
|
||
|
</section>
|
||
|
<section id="context.cc">
|
||
|
<title><anchor id="cc"/><link linkend="context.cc">Context switching with call/cc</link></title>
|
||
|
<note>
|
||
|
<para>
|
||
|
<emphasis>call/cc</emphasis> is the reference implementation of C++ proposal
|
||
|
<ulink url="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0534r3.pdf">P0534R3:
|
||
|
call/cc (call-with-current-continuation): A low-level API for stackful context
|
||
|
switching</ulink>.
|
||
|
</para>
|
||
|
</note>
|
||
|
<para>
|
||
|
<emphasis>call/cc</emphasis> (call with current continuation) is a universal
|
||
|
control operator (well-known from the programming language Scheme) that captures
|
||
|
the current continuation as a first-class object and pass it as an argument
|
||
|
to another continuation.
|
||
|
</para>
|
||
|
<para>
|
||
|
A continuation (abstract concept of functional programming languages) represents
|
||
|
the state of the control flow of a program at a given point in time. Continuations
|
||
|
can be suspended and resumed later in order to change the control flow of a
|
||
|
program.
|
||
|
</para>
|
||
|
<para>
|
||
|
Modern micro-processors are registers machines; the content of processor registers
|
||
|
represent a continuation of the executed program at a given point in time.
|
||
|
Operating systems simulate parallel execution of programs on a single processor
|
||
|
by switching between programs (context switch) by preserving and restoring
|
||
|
the continuation, e.g. the content of all registers.
|
||
|
</para>
|
||
|
<bridgehead renderas="sect3" id="context.cc.h0">
|
||
|
<phrase id="context.cc._link_linkend__cc___emphasis_callcc____emphasis___link_"/><link
|
||
|
linkend="context.cc._link_linkend__cc___emphasis_callcc____emphasis___link_"><link
|
||
|
linkend="cc"><emphasis>callcc()</emphasis></link></link>
|
||
|
</bridgehead>
|
||
|
<para>
|
||
|
<link linkend="cc"><emphasis>callcc()</emphasis></link> is the C++ equivalent
|
||
|
to Scheme's <emphasis>call/cc</emphasis> operator. It captures the current
|
||
|
continuation (the rest of the computation; code after <link linkend="cc"><emphasis>callcc()</emphasis></link>)
|
||
|
and triggers a context switch. The context switch is achieved by preserving
|
||
|
certain registers (including instruction and stack pointer), defined by the
|
||
|
calling convention of the ABI, of the current continuation and restoring those
|
||
|
registers of the resumed continuation. The control flow of the resumed continuation
|
||
|
continues. The current continuation is suspended and passed as argument to
|
||
|
the resumed continuation.
|
||
|
</para>
|
||
|
<para>
|
||
|
<link linkend="cc"><emphasis>callcc()</emphasis></link> expects a <emphasis>context-function</emphasis>
|
||
|
with signature <code><phrase role="char">'continuation(continuation &&
|
||
|
c)'</phrase></code>. The parameter <code><phrase role="identifier">c</phrase></code>
|
||
|
represents the current continuation from which this continuation was resumed
|
||
|
(e.g. that has called <link linkend="cc"><emphasis>callcc()</emphasis></link>).
|
||
|
</para>
|
||
|
<para>
|
||
|
On return the <emphasis>context-function</emphasis> of the current continuation
|
||
|
has to specify an <link linkend="cc"><emphasis>continuation</emphasis></link>
|
||
|
to which the execution control is transferred after termination of the current
|
||
|
continuation.
|
||
|
</para>
|
||
|
<para>
|
||
|
If an instance with valid state goes out of scope and the <emphasis>context-function</emphasis>
|
||
|
has not yet returned, the stack is traversed in order to access the control
|
||
|
structure (address stored at the first stack frame) and continuation's stack
|
||
|
is deallocated via the <emphasis>StackAllocator</emphasis>.
|
||
|
</para>
|
||
|
<note>
|
||
|
<para>
|
||
|
<link linkend="segmented"><emphasis>Segmented stacks</emphasis></link> are
|
||
|
supported by <link linkend="cc"><emphasis>callcc()</emphasis></link> using
|
||
|
<link linkend="implementation"><emphasis>ucontext_t</emphasis></link>.
|
||
|
</para>
|
||
|
</note>
|
||
|
<bridgehead renderas="sect3" id="context.cc.h1">
|
||
|
<phrase id="context.cc._link_linkend__cc___emphasis_continuation__emphasis___link_"/><link
|
||
|
linkend="context.cc._link_linkend__cc___emphasis_continuation__emphasis___link_"><link
|
||
|
linkend="cc"><emphasis>continuation</emphasis></link></link>
|
||
|
</bridgehead>
|
||
|
<para>
|
||
|
<link linkend="cc"><emphasis>continuation</emphasis></link> represents a continuation;
|
||
|
it contains the content of preserved registers and manages the associated stack
|
||
|
(allocation/deallocation). <link linkend="cc"><emphasis>continuation</emphasis></link>
|
||
|
is a one-shot continuation - it can be used only once, after calling <emphasis>continuation::resume()</emphasis>
|
||
|
or <emphasis>continuation::resume_with()</emphasis> it is invalidated.
|
||
|
</para>
|
||
|
<para>
|
||
|
<link linkend="cc"><emphasis>continuation</emphasis></link> is only move-constructible
|
||
|
and move-assignable.
|
||
|
</para>
|
||
|
<para>
|
||
|
As a first-class object <link linkend="cc"><emphasis>continuation</emphasis></link>
|
||
|
can be applied to and returned from a function, assigned to a variable or stored
|
||
|
in a container.
|
||
|
</para>
|
||
|
<para>
|
||
|
A continuation is continued by calling <code><phrase role="identifier">resume</phrase><phrase
|
||
|
role="special">()</phrase></code>/<code><phrase role="identifier">resume_with</phrase><phrase
|
||
|
role="special">()</phrase></code>.
|
||
|
</para>
|
||
|
<bridgehead renderas="sect3" id="context.cc.h2">
|
||
|
<phrase id="context.cc.usage"/><link linkend="context.cc.usage">Usage</link>
|
||
|
</bridgehead>
|
||
|
<programlisting><phrase role="keyword">namespace</phrase> <phrase role="identifier">ctx</phrase><phrase role="special">=</phrase><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">context</phrase><phrase role="special">;</phrase>
|
||
|
<phrase role="keyword">int</phrase> <phrase role="identifier">a</phrase><phrase role="special">;</phrase>
|
||
|
<phrase role="identifier">ctx</phrase><phrase role="special">::</phrase><phrase role="identifier">continuation</phrase> <phrase role="identifier">source</phrase><phrase role="special">=</phrase><phrase role="identifier">ctx</phrase><phrase role="special">::</phrase><phrase role="identifier">callcc</phrase><phrase role="special">(</phrase>
|
||
|
<phrase role="special">[&</phrase><phrase role="identifier">a</phrase><phrase role="special">](</phrase><phrase role="identifier">ctx</phrase><phrase role="special">::</phrase><phrase role="identifier">continuation</phrase> <phrase role="special">&&</phrase> <phrase role="identifier">sink</phrase><phrase role="special">){</phrase>
|
||
|
<phrase role="identifier">a</phrase><phrase role="special">=</phrase><phrase role="number">0</phrase><phrase role="special">;</phrase>
|
||
|
<phrase role="keyword">int</phrase> <phrase role="identifier">b</phrase><phrase role="special">=</phrase><phrase role="number">1</phrase><phrase role="special">;</phrase>
|
||
|
<phrase role="keyword">for</phrase><phrase role="special">(;;){</phrase>
|
||
|
<phrase role="identifier">sink</phrase><phrase role="special">=</phrase><phrase role="identifier">sink</phrase><phrase role="special">.</phrase><phrase role="identifier">resume</phrase><phrase role="special">();</phrase>
|
||
|
<phrase role="keyword">int</phrase> <phrase role="identifier">next</phrase><phrase role="special">=</phrase><phrase role="identifier">a</phrase><phrase role="special">+</phrase><phrase role="identifier">b</phrase><phrase role="special">;</phrase>
|
||
|
<phrase role="identifier">a</phrase><phrase role="special">=</phrase><phrase role="identifier">b</phrase><phrase role="special">;</phrase>
|
||
|
<phrase role="identifier">b</phrase><phrase role="special">=</phrase><phrase role="identifier">next</phrase><phrase role="special">;</phrase>
|
||
|
<phrase role="special">}</phrase>
|
||
|
<phrase role="keyword">return</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">move</phrase><phrase role="special">(</phrase><phrase role="identifier">sink</phrase><phrase role="special">);</phrase>
|
||
|
<phrase role="special">});</phrase>
|
||
|
<phrase role="keyword">for</phrase> <phrase role="special">(</phrase><phrase role="keyword">int</phrase> <phrase role="identifier">j</phrase><phrase role="special">=</phrase><phrase role="number">0</phrase><phrase role="special">;</phrase><phrase role="identifier">j</phrase><phrase role="special"><</phrase><phrase role="number">10</phrase><phrase role="special">;++</phrase><phrase role="identifier">j</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
|
||
|
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cout</phrase> <phrase role="special"><<</phrase> <phrase role="identifier">a</phrase> <phrase role="special"><<</phrase> <phrase role="string">" "</phrase><phrase role="special">;</phrase>
|
||
|
<phrase role="identifier">source</phrase><phrase role="special">=</phrase><phrase role="identifier">source</phrase><phrase role="special">.</phrase><phrase role="identifier">resume</phrase><phrase role="special">();</phrase>
|
||
|
<phrase role="special">}</phrase>
|
||
|
|
||
|
<phrase role="identifier">output</phrase><phrase role="special">:</phrase>
|
||
|
<phrase role="number">0</phrase> <phrase role="number">1</phrase> <phrase role="number">1</phrase> <phrase role="number">2</phrase> <phrase role="number">3</phrase> <phrase role="number">5</phrase> <phrase role="number">8</phrase> <phrase role="number">13</phrase> <phrase role="number">21</phrase> <phrase role="number">34</phrase>
|
||
|
</programlisting>
|
||
|
<para>
|
||
|
This simple example demonstrates the basic usage of <emphasis>call/cc</emphasis>
|
||
|
as a <emphasis>generator</emphasis>. The continuation <code><phrase role="identifier">sink</phrase></code>
|
||
|
represents the <emphasis>main</emphasis>-continuation (function <code><phrase
|
||
|
role="identifier">main</phrase><phrase role="special">()</phrase></code>).
|
||
|
<code><phrase role="identifier">sink</phrase></code> is captured (current-continuation)
|
||
|
by invoking <link linkend="cc"><emphasis>callcc()</emphasis></link> and passed
|
||
|
as parameter to the lambda.
|
||
|
</para>
|
||
|
<para>
|
||
|
Because the state is invalidated (one-shot continuation) by each call of <emphasis>continuation::resume()</emphasis>,
|
||
|
the new state of the <link linkend="cc"><emphasis>continuation</emphasis></link>,
|
||
|
returned by <emphasis>continuation::resume()</emphasis>, needs to be assigned
|
||
|
to <code><phrase role="identifier">sink</phrase></code> after each call.
|
||
|
</para>
|
||
|
<para>
|
||
|
The lambda that calculates the Fibonacci numbers is executed inside the continuation
|
||
|
represented by <code><phrase role="identifier">source</phrase></code>. Calculated
|
||
|
Fibonacci numbers are transferred between the two continuations via variable
|
||
|
<code><phrase role="identifier">a</phrase></code> (lambda capture reference).
|
||
|
</para>
|
||
|
<para>
|
||
|
The locale variables <code><phrase role="identifier">b</phrase></code> and
|
||
|
<code> <phrase role="identifier">next</phrase></code> remain their values during
|
||
|
each context switch. This is possible due <code><phrase role="identifier">source</phrase></code>
|
||
|
has its own stack and the stack is exchanged by each context switch.
|
||
|
</para>
|
||
|
<bridgehead renderas="sect3" id="context.cc.h3">
|
||
|
<phrase id="context.cc.parameter_passing"/><link linkend="context.cc.parameter_passing">Parameter
|
||
|
passing</link>
|
||
|
</bridgehead>
|
||
|
<para>
|
||
|
Data can be transferred between two continuations via global pointers, calling
|
||
|
wrappers (like <code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase
|
||
|
role="identifier">bind</phrase></code>) or lambda captures.
|
||
|
</para>
|
||
|
<programlisting><phrase role="keyword">namespace</phrase> <phrase role="identifier">ctx</phrase><phrase role="special">=</phrase><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">context</phrase><phrase role="special">;</phrase>
|
||
|
<phrase role="keyword">int</phrase> <phrase role="identifier">i</phrase><phrase role="special">=</phrase><phrase role="number">1</phrase><phrase role="special">;</phrase>
|
||
|
<phrase role="identifier">ctx</phrase><phrase role="special">::</phrase><phrase role="identifier">continuation</phrase> <phrase role="identifier">c1</phrase><phrase role="special">=</phrase><phrase role="identifier">callcc</phrase><phrase role="special">([&</phrase><phrase role="identifier">i</phrase><phrase role="special">](</phrase><phrase role="identifier">ctx</phrase><phrase role="special">::</phrase><phrase role="identifier">continuation</phrase> <phrase role="special">&&</phrase> <phrase role="identifier">c2</phrase><phrase role="special">){</phrase>
|
||
|
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">printf</phrase><phrase role="special">(</phrase><phrase role="string">"inside c1,i==%d\n"</phrase><phrase role="special">,</phrase><phrase role="identifier">i</phrase><phrase role="special">);</phrase>
|
||
|
<phrase role="identifier">i</phrase><phrase role="special">+=</phrase><phrase role="number">1</phrase><phrase role="special">;</phrase>
|
||
|
<phrase role="keyword">return</phrase> <phrase role="identifier">c2</phrase><phrase role="special">.</phrase><phrase role="identifier">resume</phrase><phrase role="special">();</phrase>
|
||
|
<phrase role="special">});</phrase>
|
||
|
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">printf</phrase><phrase role="special">(</phrase><phrase role="string">"i==%d\n"</phrase><phrase role="special">,</phrase><phrase role="identifier">i</phrase><phrase role="special">);</phrase>
|
||
|
|
||
|
<phrase role="identifier">output</phrase><phrase role="special">:</phrase>
|
||
|
<phrase role="identifier">inside</phrase> <phrase role="identifier">c1</phrase><phrase role="special">,</phrase><phrase role="identifier">i</phrase><phrase role="special">==</phrase><phrase role="number">1</phrase>
|
||
|
<phrase role="identifier">i</phrase><phrase role="special">==</phrase><phrase role="number">2</phrase>
|
||
|
</programlisting>
|
||
|
<para>
|
||
|
<code><phrase role="identifier">callcc</phrase><phrase role="special">(<</phrase><phrase
|
||
|
role="identifier">lambda</phrase><phrase role="special">>)</phrase></code>
|
||
|
enters the lambda in continuation represented by <code><phrase role="identifier">c1</phrase></code>
|
||
|
with lambda capture reference <code><phrase role="identifier">i</phrase><phrase
|
||
|
role="special">=</phrase><phrase role="number">1</phrase></code>. The expression
|
||
|
<code><phrase role="identifier">c2</phrase><phrase role="special">.</phrase><phrase
|
||
|
role="identifier">resume</phrase><phrase role="special">()</phrase></code>
|
||
|
resumes the continuation <code><phrase role="identifier">c2</phrase></code>.
|
||
|
On return of <code><phrase role="identifier">callcc</phrase><phrase role="special">(<</phrase><phrase
|
||
|
role="identifier">lambda</phrase><phrase role="special">>)</phrase></code>,
|
||
|
the variable <code><phrase role="identifier">i</phrase></code> has the value
|
||
|
of <code><phrase role="identifier">i</phrase><phrase role="special">+</phrase><phrase
|
||
|
role="number">1</phrase></code>.
|
||
|
</para>
|
||
|
<bridgehead renderas="sect3" id="context.cc.h4">
|
||
|
<phrase id="context.cc.exception_handling"/><link linkend="context.cc.exception_handling">Exception
|
||
|
handling</link>
|
||
|
</bridgehead>
|
||
|
<para>
|
||
|
If the function executed inside a <emphasis>context-function</emphasis> emits
|
||
|
an exception, the application is terminated by calling <code><phrase role="identifier">std</phrase><phrase
|
||
|
role="special">::</phrase><phrase role="identifier">terminate</phrase><phrase
|
||
|
role="special">()</phrase></code>. <code><phrase role="identifier">std</phrase><phrase
|
||
|
role="special">::</phrase><phrase role="identifier">exception_ptr</phrase></code>
|
||
|
can be used to transfer exceptions between different continuations.
|
||
|
</para>
|
||
|
<important>
|
||
|
<para>
|
||
|
Do not jump from inside a catch block and then re-throw the exception in
|
||
|
another continuation.
|
||
|
</para>
|
||
|
</important>
|
||
|
<anchor id="cc_ontop"/>
|
||
|
<bridgehead renderas="sect3" id="context.cc.h5">
|
||
|
<phrase id="context.cc.executing_function_on_top_of_a_continuation"/><link
|
||
|
linkend="context.cc.executing_function_on_top_of_a_continuation">Executing
|
||
|
function on top of a continuation</link>
|
||
|
</bridgehead>
|
||
|
<para>
|
||
|
Sometimes it is useful to execute a new function on top of a resumed continuation.
|
||
|
For this purpose <emphasis>continuation::resume_with()</emphasis> has to be
|
||
|
used. The function passed as argument must accept a rvalue reference to <link
|
||
|
linkend="cc"><emphasis>continuation</emphasis></link> and return <code><phrase
|
||
|
role="keyword">void</phrase></code>.
|
||
|
</para>
|
||
|
<programlisting><phrase role="keyword">namespace</phrase> <phrase role="identifier">ctx</phrase><phrase role="special">=</phrase><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">context</phrase><phrase role="special">;</phrase>
|
||
|
<phrase role="keyword">int</phrase> <phrase role="identifier">data</phrase><phrase role="special">=</phrase><phrase role="number">0</phrase><phrase role="special">;</phrase>
|
||
|
<phrase role="identifier">ctx</phrase><phrase role="special">::</phrase><phrase role="identifier">continuation</phrase> <phrase role="identifier">c</phrase><phrase role="special">=</phrase><phrase role="identifier">ctx</phrase><phrase role="special">::</phrase><phrase role="identifier">callcc</phrase><phrase role="special">([&</phrase><phrase role="identifier">data</phrase><phrase role="special">](</phrase><phrase role="identifier">ctx</phrase><phrase role="special">::</phrase><phrase role="identifier">continuation</phrase> <phrase role="special">&&</phrase> <phrase role="identifier">c</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
|
||
|
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cout</phrase> <phrase role="special"><<</phrase> <phrase role="string">"f1: entered first time: "</phrase> <phrase role="special"><<</phrase> <phrase role="identifier">data</phrase> <phrase role="special"><<</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">endl</phrase><phrase role="special">;</phrase>
|
||
|
<phrase role="identifier">data</phrase><phrase role="special">+=</phrase><phrase role="number">1</phrase><phrase role="special">;</phrase>
|
||
|
<phrase role="identifier">c</phrase><phrase role="special">=</phrase><phrase role="identifier">c</phrase><phrase role="special">.</phrase><phrase role="identifier">resume</phrase><phrase role="special">();</phrase>
|
||
|
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cout</phrase> <phrase role="special"><<</phrase> <phrase role="string">"f1: entered second time: "</phrase> <phrase role="special"><<</phrase> <phrase role="identifier">data</phrase> <phrase role="special"><<</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">endl</phrase><phrase role="special">;</phrase>
|
||
|
<phrase role="identifier">data</phrase><phrase role="special">+=</phrase><phrase role="number">1</phrase><phrase role="special">;</phrase>
|
||
|
<phrase role="identifier">c</phrase><phrase role="special">=</phrase><phrase role="identifier">c</phrase><phrase role="special">.</phrase><phrase role="identifier">resume</phrase><phrase role="special">();</phrase>
|
||
|
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cout</phrase> <phrase role="special"><<</phrase> <phrase role="string">"f1: entered third time: "</phrase> <phrase role="special"><<</phrase> <phrase role="identifier">data</phrase> <phrase role="special"><<</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">endl</phrase><phrase role="special">;</phrase>
|
||
|
<phrase role="keyword">return</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">move</phrase><phrase role="special">(</phrase><phrase role="identifier">c</phrase><phrase role="special">);</phrase>
|
||
|
<phrase role="special">});</phrase>
|
||
|
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cout</phrase> <phrase role="special"><<</phrase> <phrase role="string">"f1: returned first time: "</phrase> <phrase role="special"><<</phrase> <phrase role="identifier">data</phrase> <phrase role="special"><<</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">endl</phrase><phrase role="special">;</phrase>
|
||
|
<phrase role="identifier">data</phrase><phrase role="special">+=</phrase><phrase role="number">1</phrase><phrase role="special">;</phrase>
|
||
|
<phrase role="identifier">c</phrase><phrase role="special">=</phrase><phrase role="identifier">c</phrase><phrase role="special">.</phrase><phrase role="identifier">resume</phrase><phrase role="special">();</phrase>
|
||
|
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cout</phrase> <phrase role="special"><<</phrase> <phrase role="string">"f1: returned second time: "</phrase> <phrase role="special"><<</phrase> <phrase role="identifier">data</phrase> <phrase role="special"><<</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">endl</phrase><phrase role="special">;</phrase>
|
||
|
<phrase role="identifier">data</phrase><phrase role="special">+=</phrase><phrase role="number">1</phrase><phrase role="special">;</phrase>
|
||
|
<phrase role="identifier">c</phrase><phrase role="special">=</phrase><phrase role="identifier">c</phrase><phrase role="special">.</phrase><phrase role="identifier">resume_with</phrase><phrase role="special">([&</phrase><phrase role="identifier">data</phrase><phrase role="special">](</phrase><phrase role="identifier">ctx</phrase><phrase role="special">::</phrase><phrase role="identifier">continuation</phrase> <phrase role="special">&&</phrase> <phrase role="identifier">c</phrase><phrase role="special">){</phrase>
|
||
|
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cout</phrase> <phrase role="special"><<</phrase> <phrase role="string">"f2: entered: "</phrase> <phrase role="special"><<</phrase> <phrase role="identifier">data</phrase> <phrase role="special"><<</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">endl</phrase><phrase role="special">;</phrase>
|
||
|
<phrase role="identifier">data</phrase><phrase role="special">=-</phrase><phrase role="number">1</phrase><phrase role="special">;</phrase>
|
||
|
<phrase role="keyword">return</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">move</phrase><phrase role="special">(</phrase> <phrase role="identifier">c</phrase><phrase role="special">);</phrase>
|
||
|
<phrase role="special">});</phrase>
|
||
|
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cout</phrase> <phrase role="special"><<</phrase> <phrase role="string">"f1: returned third time"</phrase> <phrase role="special"><<</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">endl</phrase><phrase role="special">;</phrase>
|
||
|
|
||
|
<phrase role="identifier">output</phrase><phrase role="special">:</phrase>
|
||
|
<phrase role="identifier">f1</phrase><phrase role="special">:</phrase> <phrase role="identifier">entered</phrase> <phrase role="identifier">first</phrase> <phrase role="identifier">time</phrase><phrase role="special">:</phrase> <phrase role="number">0</phrase>
|
||
|
<phrase role="identifier">f1</phrase><phrase role="special">:</phrase> <phrase role="identifier">returned</phrase> <phrase role="identifier">first</phrase> <phrase role="identifier">time</phrase><phrase role="special">:</phrase> <phrase role="number">1</phrase>
|
||
|
<phrase role="identifier">f1</phrase><phrase role="special">:</phrase> <phrase role="identifier">entered</phrase> <phrase role="identifier">second</phrase> <phrase role="identifier">time</phrase><phrase role="special">:</phrase> <phrase role="number">2</phrase>
|
||
|
<phrase role="identifier">f1</phrase><phrase role="special">:</phrase> <phrase role="identifier">returned</phrase> <phrase role="identifier">second</phrase> <phrase role="identifier">time</phrase><phrase role="special">:</phrase> <phrase role="number">3</phrase>
|
||
|
<phrase role="identifier">f2</phrase><phrase role="special">:</phrase> <phrase role="identifier">entered</phrase><phrase role="special">:</phrase> <phrase role="number">4</phrase>
|
||
|
<phrase role="identifier">f1</phrase><phrase role="special">:</phrase> <phrase role="identifier">entered</phrase> <phrase role="identifier">third</phrase> <phrase role="identifier">time</phrase><phrase role="special">:</phrase> <phrase role="special">-</phrase><phrase role="number">1</phrase>
|
||
|
<phrase role="identifier">f1</phrase><phrase role="special">:</phrase> <phrase role="identifier">returned</phrase> <phrase role="identifier">third</phrase> <phrase role="identifier">time</phrase>
|
||
|
</programlisting>
|
||
|
<para>
|
||
|
The expression <code><phrase role="identifier">c</phrase><phrase role="special">.</phrase><phrase
|
||
|
role="identifier">resume_with</phrase><phrase role="special">(...)</phrase></code>
|
||
|
executes a lambda on top of continuation <code><phrase role="identifier">c</phrase></code>,
|
||
|
e.g. an additional stack frame is allocated on top of the stack. This lambda
|
||
|
assigns <code><phrase role="special">-</phrase><phrase role="number">1</phrase></code>
|
||
|
to <code><phrase role="identifier">data</phrase></code> and returns to the
|
||
|
second invocation of <code><phrase role="identifier">c</phrase><phrase role="special">.</phrase><phrase
|
||
|
role="identifier">resume</phrase><phrase role="special">()</phrase></code>.
|
||
|
</para>
|
||
|
<para>
|
||
|
Another option is to execute a function on top of the continuation that throws
|
||
|
an exception.
|
||
|
</para>
|
||
|
<programlisting><phrase role="keyword">namespace</phrase> <phrase role="identifier">ctx</phrase><phrase role="special">=</phrase><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">context</phrase><phrase role="special">;</phrase>
|
||
|
<phrase role="keyword">struct</phrase> <phrase role="identifier">my_exception</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">runtime_error</phrase> <phrase role="special">{</phrase>
|
||
|
<phrase role="identifier">ctx</phrase><phrase role="special">::</phrase><phrase role="identifier">continuation</phrase> <phrase role="identifier">c</phrase><phrase role="special">;</phrase>
|
||
|
<phrase role="identifier">my_exception</phrase><phrase role="special">(</phrase><phrase role="identifier">ctx</phrase><phrase role="special">::</phrase><phrase role="identifier">continuation</phrase> <phrase role="special">&&</phrase> <phrase role="identifier">c_</phrase><phrase role="special">,</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">what</phrase><phrase role="special">)</phrase> <phrase role="special">:</phrase>
|
||
|
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">runtime_error</phrase><phrase role="special">{</phrase> <phrase role="identifier">what</phrase> <phrase role="special">},</phrase>
|
||
|
<phrase role="identifier">c</phrase><phrase role="special">{</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">move</phrase><phrase role="special">(</phrase> <phrase role="identifier">c_</phrase><phrase role="special">)</phrase> <phrase role="special">}</phrase> <phrase role="special">{</phrase>
|
||
|
<phrase role="special">}</phrase>
|
||
|
<phrase role="special">};</phrase>
|
||
|
|
||
|
<phrase role="identifier">ctx</phrase><phrase role="special">::</phrase><phrase role="identifier">continuation</phrase> <phrase role="identifier">c</phrase><phrase role="special">=</phrase><phrase role="identifier">ctx</phrase><phrase role="special">::</phrase><phrase role="identifier">callcc</phrase><phrase role="special">([](</phrase><phrase role="identifier">ctx</phrase><phrase role="special">::</phrase><phrase role="identifier">continuation</phrase> <phrase role="special">&&</phrase> <phrase role="identifier">c</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
|
||
|
<phrase role="keyword">for</phrase> <phrase role="special">(;;)</phrase> <phrase role="special">{</phrase>
|
||
|
<phrase role="keyword">try</phrase> <phrase role="special">{</phrase>
|
||
|
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cout</phrase> <phrase role="special"><<</phrase> <phrase role="string">"entered"</phrase> <phrase role="special"><<</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">endl</phrase><phrase role="special">;</phrase>
|
||
|
<phrase role="identifier">c</phrase><phrase role="special">=</phrase><phrase role="identifier">c</phrase><phrase role="special">.</phrase><phrase role="identifier">resume</phrase><phrase role="special">();</phrase>
|
||
|
<phrase role="special">}</phrase> <phrase role="keyword">catch</phrase> <phrase role="special">(</phrase><phrase role="identifier">my_exception</phrase> <phrase role="special">&</phrase> <phrase role="identifier">ex</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
|
||
|
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cerr</phrase> <phrase role="special"><<</phrase> <phrase role="string">"my_exception: "</phrase> <phrase role="special"><<</phrase> <phrase role="identifier">ex</phrase><phrase role="special">.</phrase><phrase role="identifier">what</phrase><phrase role="special">()</phrase> <phrase role="special"><<</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">endl</phrase><phrase role="special">;</phrase>
|
||
|
<phrase role="keyword">return</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">move</phrase><phrase role="special">(</phrase><phrase role="identifier">ex</phrase><phrase role="special">.</phrase><phrase role="identifier">c</phrase><phrase role="special">);</phrase>
|
||
|
<phrase role="special">}</phrase>
|
||
|
<phrase role="special">}</phrase>
|
||
|
<phrase role="keyword">return</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">move</phrase><phrase role="special">(</phrase><phrase role="identifier">c</phrase><phrase role="special">);</phrase>
|
||
|
<phrase role="special">});</phrase>
|
||
|
<phrase role="identifier">c</phrase> <phrase role="special">=</phrase> <phrase role="identifier">c</phrase><phrase role="special">.</phrase><phrase role="identifier">resume_with</phrase><phrase role="special">(</phrase>
|
||
|
<phrase role="special">[](</phrase><phrase role="identifier">ctx</phrase><phrase role="special">::</phrase><phrase role="identifier">continuation</phrase> <phrase role="special">&&</phrase> <phrase role="identifier">c</phrase><phrase role="special">){</phrase>
|
||
|
<phrase role="keyword">throw</phrase> <phrase role="identifier">my_exception</phrase><phrase role="special">(</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">move</phrase><phrase role="special">(</phrase><phrase role="identifier">c</phrase><phrase role="special">),</phrase><phrase role="string">"abc"</phrase><phrase role="special">);</phrase>
|
||
|
<phrase role="keyword">return</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">move</phrase><phrase role="special">(</phrase> <phrase role="identifier">c</phrase><phrase role="special">);</phrase>
|
||
|
<phrase role="special">});</phrase>
|
||
|
|
||
|
<phrase role="identifier">output</phrase><phrase role="special">:</phrase>
|
||
|
<phrase role="identifier">entered</phrase>
|
||
|
<phrase role="identifier">my_exception</phrase><phrase role="special">:</phrase> <phrase role="identifier">abc</phrase>
|
||
|
</programlisting>
|
||
|
<para>
|
||
|
In this exception <code><phrase role="identifier">my_exception</phrase></code>
|
||
|
is throw from a function invoked on-top of continuation <code><phrase role="identifier">c</phrase></code>
|
||
|
and catched inside the <code><phrase role="keyword">for</phrase></code>-loop.
|
||
|
</para>
|
||
|
<bridgehead renderas="sect3" id="context.cc.h6">
|
||
|
<phrase id="context.cc.stack_unwinding"/><link linkend="context.cc.stack_unwinding">Stack
|
||
|
unwinding</link>
|
||
|
</bridgehead>
|
||
|
<para>
|
||
|
On construction of <link linkend="cc"><emphasis>continuation</emphasis></link>
|
||
|
a stack is allocated. If the <emphasis>context-function</emphasis> returns
|
||
|
the stack will be destructed. If the <emphasis>context-function</emphasis>
|
||
|
has not yet returned and the destructor of an valid <link linkend="cc"><emphasis>continuation</emphasis></link>
|
||
|
instance (e.g. <emphasis>continuation::operator bool()</emphasis> returns
|
||
|
<code><phrase role="keyword">true</phrase></code>) is called, the stack will
|
||
|
be destructed too.
|
||
|
</para>
|
||
|
<important>
|
||
|
<para>
|
||
|
Code executed by <emphasis>context-function</emphasis> must not prevent the
|
||
|
propagation ofs the <emphasis>detail::forced_unwind</emphasis> exception.
|
||
|
Absorbing that exception will cause stack unwinding to fail. Thus, any code
|
||
|
that catches all exceptions must re-throw any pending <emphasis>detail::forced_unwind</emphasis>
|
||
|
exception.
|
||
|
</para>
|
||
|
</important>
|
||
|
<anchor id="cc_prealloc"/>
|
||
|
<bridgehead renderas="sect3" id="context.cc.h7">
|
||
|
<phrase id="context.cc.allocating_control_structures_on_top_of_stack"/><link
|
||
|
linkend="context.cc.allocating_control_structures_on_top_of_stack">Allocating
|
||
|
control structures on top of stack</link>
|
||
|
</bridgehead>
|
||
|
<para>
|
||
|
Allocating control structures on top of the stack requires to allocated the
|
||
|
<emphasis>stack_context</emphasis> and create the control structure with placement
|
||
|
new before <link linkend="cc"><emphasis>continuation</emphasis></link> is created.
|
||
|
</para>
|
||
|
<note>
|
||
|
<para>
|
||
|
The user is responsible for destructing the control structure at the top
|
||
|
of the stack.
|
||
|
</para>
|
||
|
</note>
|
||
|
<programlisting><phrase role="keyword">namespace</phrase> <phrase role="identifier">ctx</phrase><phrase role="special">=</phrase><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">context</phrase><phrase role="special">;</phrase>
|
||
|
<phrase role="comment">// stack-allocator used for (de-)allocating stack</phrase>
|
||
|
<phrase role="identifier">fixedsize_stack</phrase> <phrase role="identifier">salloc</phrase><phrase role="special">(</phrase><phrase role="number">4048</phrase><phrase role="special">);</phrase>
|
||
|
<phrase role="comment">// allocate stack space</phrase>
|
||
|
<phrase role="identifier">stack_context</phrase> <phrase role="identifier">sctx</phrase><phrase role="special">(</phrase><phrase role="identifier">salloc</phrase><phrase role="special">.</phrase><phrase role="identifier">allocate</phrase><phrase role="special">());</phrase>
|
||
|
<phrase role="comment">// reserve space for control structure on top of the stack</phrase>
|
||
|
<phrase role="keyword">void</phrase> <phrase role="special">*</phrase> <phrase role="identifier">sp</phrase><phrase role="special">=</phrase><phrase role="keyword">static_cast</phrase><phrase role="special"><</phrase><phrase role="keyword">char</phrase><phrase role="special">*>(</phrase><phrase role="identifier">sctx</phrase><phrase role="special">.</phrase><phrase role="identifier">sp</phrase><phrase role="special">)-</phrase><phrase role="keyword">sizeof</phrase><phrase role="special">(</phrase><phrase role="identifier">my_control_structure</phrase><phrase role="special">);</phrase>
|
||
|
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">size</phrase><phrase role="special">=</phrase><phrase role="identifier">sctx</phrase><phrase role="special">.</phrase><phrase role="identifier">size</phrase><phrase role="special">-</phrase><phrase role="keyword">sizeof</phrase><phrase role="special">(</phrase><phrase role="identifier">my_control_structure</phrase><phrase role="special">);</phrase>
|
||
|
<phrase role="comment">// placement new creates control structure on reserved space</phrase>
|
||
|
<phrase role="identifier">my_control_structure</phrase> <phrase role="special">*</phrase> <phrase role="identifier">cs</phrase><phrase role="special">=</phrase><phrase role="keyword">new</phrase><phrase role="special">(</phrase><phrase role="identifier">sp</phrase><phrase role="special">)</phrase><phrase role="identifier">my_control_structure</phrase><phrase role="special">(</phrase><phrase role="identifier">sp</phrase><phrase role="special">,</phrase><phrase role="identifier">size</phrase><phrase role="special">,</phrase><phrase role="identifier">sctx</phrase><phrase role="special">,</phrase><phrase role="identifier">salloc</phrase><phrase role="special">);</phrase>
|
||
|
<phrase role="special">...</phrase>
|
||
|
<phrase role="comment">// destructing the control structure</phrase>
|
||
|
<phrase role="identifier">cs</phrase><phrase role="special">->~</phrase><phrase role="identifier">my_control_structure</phrase><phrase role="special">();</phrase>
|
||
|
<phrase role="special">...</phrase>
|
||
|
<phrase role="keyword">struct</phrase> <phrase role="identifier">my_control_structure</phrase> <phrase role="special">{</phrase>
|
||
|
<phrase role="comment">// captured continuation</phrase>
|
||
|
<phrase role="identifier">ctx</phrase><phrase role="special">::</phrase><phrase role="identifier">continuation</phrase> <phrase role="identifier">c</phrase><phrase role="special">;</phrase>
|
||
|
|
||
|
<phrase role="keyword">template</phrase><phrase role="special"><</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">StackAllocator</phrase> <phrase role="special">></phrase>
|
||
|
<phrase role="identifier">my_control_structure</phrase><phrase role="special">(</phrase><phrase role="keyword">void</phrase> <phrase role="special">*</phrase> <phrase role="identifier">sp</phrase><phrase role="special">,</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">size</phrase><phrase role="special">,</phrase><phrase role="identifier">stack_context</phrase> <phrase role="identifier">sctx</phrase><phrase role="special">,</phrase><phrase role="identifier">StackAllocator</phrase> <phrase role="identifier">salloc</phrase><phrase role="special">)</phrase> <phrase role="special">:</phrase>
|
||
|
<phrase role="comment">// create captured continuation</phrase>
|
||
|
<phrase role="identifier">c</phrase><phrase role="special">{}</phrase> <phrase role="special">{</phrase>
|
||
|
<phrase role="identifier">c</phrase><phrase role="special">=</phrase><phrase role="identifier">ctx</phrase><phrase role="special">::</phrase><phrase role="identifier">callcc</phrase><phrase role="special">(</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">allocator_arg</phrase><phrase role="special">,</phrase><phrase role="identifier">preallocated</phrase><phrase role="special">(</phrase><phrase role="identifier">sp</phrase><phrase role="special">,</phrase><phrase role="identifier">size</phrase><phrase role="special">,</phrase><phrase role="identifier">sctx</phrase><phrase role="special">),</phrase><phrase role="identifier">salloc</phrase><phrase role="special">,</phrase><phrase role="identifier">entry_func</phrase><phrase role="special">);</phrase>
|
||
|
<phrase role="special">}</phrase>
|
||
|
<phrase role="special">...</phrase>
|
||
|
<phrase role="special">};</phrase>
|
||
|
</programlisting>
|
||
|
<bridgehead renderas="sect3" id="context.cc.h8">
|
||
|
<phrase id="context.cc.inverting_the_control_flow"/><link linkend="context.cc.inverting_the_control_flow">Inverting
|
||
|
the control flow</link>
|
||
|
</bridgehead>
|
||
|
<programlisting><phrase role="keyword">namespace</phrase> <phrase role="identifier">ctx</phrase><phrase role="special">=</phrase><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">context</phrase><phrase role="special">;</phrase>
|
||
|
<phrase role="comment">/*
|
||
|
* grammar:
|
||
|
* P ---> E '\0'
|
||
|
* E ---> T {('+'|'-') T}
|
||
|
* T ---> S {('*'|'/') S}
|
||
|
* S ---> digit | '(' E ')'
|
||
|
*/</phrase>
|
||
|
<phrase role="keyword">class</phrase> <phrase role="identifier">Parser</phrase><phrase role="special">{</phrase>
|
||
|
<phrase role="keyword">char</phrase> <phrase role="identifier">next</phrase><phrase role="special">;</phrase>
|
||
|
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">istream</phrase><phrase role="special">&</phrase> <phrase role="identifier">is</phrase><phrase role="special">;</phrase>
|
||
|
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">function</phrase><phrase role="special"><</phrase><phrase role="keyword">void</phrase><phrase role="special">(</phrase><phrase role="keyword">char</phrase><phrase role="special">)></phrase> <phrase role="identifier">cb</phrase><phrase role="special">;</phrase>
|
||
|
|
||
|
<phrase role="keyword">char</phrase> <phrase role="identifier">pull</phrase><phrase role="special">(){</phrase>
|
||
|
<phrase role="keyword">return</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">char_traits</phrase><phrase role="special"><</phrase><phrase role="keyword">char</phrase><phrase role="special">>::</phrase><phrase role="identifier">to_char_type</phrase><phrase role="special">(</phrase><phrase role="identifier">is</phrase><phrase role="special">.</phrase><phrase role="identifier">get</phrase><phrase role="special">());</phrase>
|
||
|
<phrase role="special">}</phrase>
|
||
|
|
||
|
<phrase role="keyword">void</phrase> <phrase role="identifier">scan</phrase><phrase role="special">(){</phrase>
|
||
|
<phrase role="keyword">do</phrase><phrase role="special">{</phrase>
|
||
|
<phrase role="identifier">next</phrase><phrase role="special">=</phrase><phrase role="identifier">pull</phrase><phrase role="special">();</phrase>
|
||
|
<phrase role="special">}</phrase>
|
||
|
<phrase role="keyword">while</phrase><phrase role="special">(</phrase><phrase role="identifier">isspace</phrase><phrase role="special">(</phrase><phrase role="identifier">next</phrase><phrase role="special">));</phrase>
|
||
|
<phrase role="special">}</phrase>
|
||
|
|
||
|
<phrase role="keyword">public</phrase><phrase role="special">:</phrase>
|
||
|
<phrase role="identifier">Parser</phrase><phrase role="special">(</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">istream</phrase><phrase role="special">&</phrase> <phrase role="identifier">is_</phrase><phrase role="special">,</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">function</phrase><phrase role="special"><</phrase><phrase role="keyword">void</phrase><phrase role="special">(</phrase><phrase role="keyword">char</phrase><phrase role="special">)></phrase> <phrase role="identifier">cb_</phrase><phrase role="special">)</phrase> <phrase role="special">:</phrase>
|
||
|
<phrase role="identifier">next</phrase><phrase role="special">(),</phrase> <phrase role="identifier">is</phrase><phrase role="special">(</phrase><phrase role="identifier">is_</phrase><phrase role="special">),</phrase> <phrase role="identifier">cb</phrase><phrase role="special">(</phrase><phrase role="identifier">cb_</phrase><phrase role="special">)</phrase>
|
||
|
<phrase role="special">{}</phrase>
|
||
|
|
||
|
<phrase role="keyword">void</phrase> <phrase role="identifier">run</phrase><phrase role="special">()</phrase> <phrase role="special">{</phrase>
|
||
|
<phrase role="identifier">scan</phrase><phrase role="special">();</phrase>
|
||
|
<phrase role="identifier">E</phrase><phrase role="special">();</phrase>
|
||
|
<phrase role="special">}</phrase>
|
||
|
|
||
|
<phrase role="keyword">private</phrase><phrase role="special">:</phrase>
|
||
|
<phrase role="keyword">void</phrase> <phrase role="identifier">E</phrase><phrase role="special">(){</phrase>
|
||
|
<phrase role="identifier">T</phrase><phrase role="special">();</phrase>
|
||
|
<phrase role="keyword">while</phrase> <phrase role="special">(</phrase><phrase role="identifier">next</phrase><phrase role="special">==</phrase><phrase role="char">'+'</phrase><phrase role="special">||</phrase><phrase role="identifier">next</phrase><phrase role="special">==</phrase><phrase role="char">'-'</phrase><phrase role="special">){</phrase>
|
||
|
<phrase role="identifier">cb</phrase><phrase role="special">(</phrase><phrase role="identifier">next</phrase><phrase role="special">);</phrase>
|
||
|
<phrase role="identifier">scan</phrase><phrase role="special">();</phrase>
|
||
|
<phrase role="identifier">T</phrase><phrase role="special">();</phrase>
|
||
|
<phrase role="special">}</phrase>
|
||
|
<phrase role="special">}</phrase>
|
||
|
|
||
|
<phrase role="keyword">void</phrase> <phrase role="identifier">T</phrase><phrase role="special">(){</phrase>
|
||
|
<phrase role="identifier">S</phrase><phrase role="special">();</phrase>
|
||
|
<phrase role="keyword">while</phrase> <phrase role="special">(</phrase><phrase role="identifier">next</phrase><phrase role="special">==</phrase><phrase role="char">'*'</phrase><phrase role="special">||</phrase><phrase role="identifier">next</phrase><phrase role="special">==</phrase><phrase role="char">'/'</phrase><phrase role="special">){</phrase>
|
||
|
<phrase role="identifier">cb</phrase><phrase role="special">(</phrase><phrase role="identifier">next</phrase><phrase role="special">);</phrase>
|
||
|
<phrase role="identifier">scan</phrase><phrase role="special">();</phrase>
|
||
|
<phrase role="identifier">S</phrase><phrase role="special">();</phrase>
|
||
|
<phrase role="special">}</phrase>
|
||
|
<phrase role="special">}</phrase>
|
||
|
|
||
|
<phrase role="keyword">void</phrase> <phrase role="identifier">S</phrase><phrase role="special">(){</phrase>
|
||
|
<phrase role="keyword">if</phrase> <phrase role="special">(</phrase><phrase role="identifier">isdigit</phrase><phrase role="special">(</phrase><phrase role="identifier">next</phrase><phrase role="special">)){</phrase>
|
||
|
<phrase role="identifier">cb</phrase><phrase role="special">(</phrase><phrase role="identifier">next</phrase><phrase role="special">);</phrase>
|
||
|
<phrase role="identifier">scan</phrase><phrase role="special">();</phrase>
|
||
|
<phrase role="special">}</phrase>
|
||
|
<phrase role="keyword">else</phrase> <phrase role="keyword">if</phrase><phrase role="special">(</phrase><phrase role="identifier">next</phrase><phrase role="special">==</phrase><phrase role="char">'('</phrase><phrase role="special">){</phrase>
|
||
|
<phrase role="identifier">cb</phrase><phrase role="special">(</phrase><phrase role="identifier">next</phrase><phrase role="special">);</phrase>
|
||
|
<phrase role="identifier">scan</phrase><phrase role="special">();</phrase>
|
||
|
<phrase role="identifier">E</phrase><phrase role="special">();</phrase>
|
||
|
<phrase role="keyword">if</phrase> <phrase role="special">(</phrase><phrase role="identifier">next</phrase><phrase role="special">==</phrase><phrase role="char">')'</phrase><phrase role="special">){</phrase>
|
||
|
<phrase role="identifier">cb</phrase><phrase role="special">(</phrase><phrase role="identifier">next</phrase><phrase role="special">);</phrase>
|
||
|
<phrase role="identifier">scan</phrase><phrase role="special">();</phrase>
|
||
|
<phrase role="special">}</phrase><phrase role="keyword">else</phrase><phrase role="special">{</phrase>
|
||
|
<phrase role="keyword">throw</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">runtime_error</phrase><phrase role="special">(</phrase><phrase role="string">"parsing failed"</phrase><phrase role="special">);</phrase>
|
||
|
<phrase role="special">}</phrase>
|
||
|
<phrase role="special">}</phrase>
|
||
|
<phrase role="keyword">else</phrase><phrase role="special">{</phrase>
|
||
|
<phrase role="keyword">throw</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">runtime_error</phrase><phrase role="special">(</phrase><phrase role="string">"parsing failed"</phrase><phrase role="special">);</phrase>
|
||
|
<phrase role="special">}</phrase>
|
||
|
<phrase role="special">}</phrase>
|
||
|
<phrase role="special">};</phrase>
|
||
|
|
||
|
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">istringstream</phrase> <phrase role="identifier">is</phrase><phrase role="special">(</phrase><phrase role="string">"1+1"</phrase><phrase role="special">);</phrase>
|
||
|
<phrase role="comment">// execute parser in new continuation</phrase>
|
||
|
<phrase role="identifier">ctx</phrase><phrase role="special">::</phrase><phrase role="identifier">continuation</phrase> <phrase role="identifier">source</phrase><phrase role="special">;</phrase>
|
||
|
<phrase role="comment">// user-code pulls parsed data from parser</phrase>
|
||
|
<phrase role="comment">// invert control flow</phrase>
|
||
|
<phrase role="keyword">char</phrase> <phrase role="identifier">c</phrase><phrase role="special">;</phrase>
|
||
|
<phrase role="keyword">bool</phrase> <phrase role="identifier">done</phrase><phrase role="special">=</phrase><phrase role="keyword">false</phrase><phrase role="special">;</phrase>
|
||
|
<phrase role="identifier">source</phrase><phrase role="special">=</phrase><phrase role="identifier">ctx</phrase><phrase role="special">::</phrase><phrase role="identifier">callcc</phrase><phrase role="special">(</phrase>
|
||
|
<phrase role="special">[&</phrase><phrase role="identifier">is</phrase><phrase role="special">,&</phrase><phrase role="identifier">c</phrase><phrase role="special">,&</phrase><phrase role="identifier">done</phrase><phrase role="special">](</phrase><phrase role="identifier">ctx</phrase><phrase role="special">::</phrase><phrase role="identifier">continuation</phrase> <phrase role="special">&&</phrase> <phrase role="identifier">sink</phrase><phrase role="special">){</phrase>
|
||
|
<phrase role="comment">// create parser with callback function</phrase>
|
||
|
<phrase role="identifier">Parser</phrase> <phrase role="identifier">p</phrase><phrase role="special">(</phrase><phrase role="identifier">is</phrase><phrase role="special">,</phrase>
|
||
|
<phrase role="special">[&</phrase><phrase role="identifier">sink</phrase><phrase role="special">,&</phrase><phrase role="identifier">c</phrase><phrase role="special">](</phrase><phrase role="keyword">char</phrase> <phrase role="identifier">c_</phrase><phrase role="special">){</phrase>
|
||
|
<phrase role="comment">// resume main continuation</phrase>
|
||
|
<phrase role="identifier">c</phrase><phrase role="special">=</phrase><phrase role="identifier">c_</phrase><phrase role="special">;</phrase>
|
||
|
<phrase role="identifier">sink</phrase><phrase role="special">=</phrase><phrase role="identifier">sink</phrase><phrase role="special">.</phrase><phrase role="identifier">resume</phrase><phrase role="special">();</phrase>
|
||
|
<phrase role="special">});</phrase>
|
||
|
<phrase role="comment">// start recursive parsing</phrase>
|
||
|
<phrase role="identifier">p</phrase><phrase role="special">.</phrase><phrase role="identifier">run</phrase><phrase role="special">();</phrase>
|
||
|
<phrase role="comment">// signal termination</phrase>
|
||
|
<phrase role="identifier">done</phrase><phrase role="special">=</phrase><phrase role="keyword">true</phrase><phrase role="special">;</phrase>
|
||
|
<phrase role="comment">// resume main continuation</phrase>
|
||
|
<phrase role="keyword">return</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">move</phrase><phrase role="special">(</phrase><phrase role="identifier">sink</phrase><phrase role="special">);</phrase>
|
||
|
<phrase role="special">});</phrase>
|
||
|
<phrase role="keyword">while</phrase><phrase role="special">(!</phrase><phrase role="identifier">done</phrase><phrase role="special">){</phrase>
|
||
|
<phrase role="identifier">printf</phrase><phrase role="special">(</phrase><phrase role="string">"Parsed: %c\n"</phrase><phrase role="special">,</phrase><phrase role="identifier">c</phrase><phrase role="special">);</phrase>
|
||
|
<phrase role="identifier">source</phrase><phrase role="special">=</phrase><phrase role="identifier">source</phrase><phrase role="special">.</phrase><phrase role="identifier">resume</phrase><phrase role="special">();</phrase>
|
||
|
<phrase role="special">}</phrase>
|
||
|
|
||
|
<phrase role="identifier">output</phrase><phrase role="special">:</phrase>
|
||
|
<phrase role="identifier">Parsed</phrase><phrase role="special">:</phrase> <phrase role="number">1</phrase>
|
||
|
<phrase role="identifier">Parsed</phrase><phrase role="special">:</phrase> <phrase role="special">+</phrase>
|
||
|
<phrase role="identifier">Parsed</phrase><phrase role="special">:</phrase> <phrase role="number">1</phrase>
|
||
|
</programlisting>
|
||
|
<para>
|
||
|
In this example a recursive descent parser uses a callback to emit a newly
|
||
|
passed symbol. Using <emphasis>call/cc</emphasis> the control flow can be inverted,
|
||
|
e.g. the user-code pulls parsed symbols from the parser - instead to get pushed
|
||
|
from the parser (via callback).
|
||
|
</para>
|
||
|
<para>
|
||
|
The data (character) is transferred between the two continuations.
|
||
|
</para>
|
||
|
<section id="context.cc.implementations__fcontext_t__ucontext_t_and_winfiber">
|
||
|
<title><anchor id="implementation0"/><link linkend="context.cc.implementations__fcontext_t__ucontext_t_and_winfiber">Implementations:
|
||
|
fcontext_t, ucontext_t and WinFiber</link></title>
|
||
|
<bridgehead renderas="sect4" id="context.cc.implementations__fcontext_t__ucontext_t_and_winfiber.h0">
|
||
|
<phrase id="context.cc.implementations__fcontext_t__ucontext_t_and_winfiber.fcontext_t"/><link
|
||
|
linkend="context.cc.implementations__fcontext_t__ucontext_t_and_winfiber.fcontext_t">fcontext_t</link>
|
||
|
</bridgehead>
|
||
|
<para>
|
||
|
The implementation uses <emphasis>fcontext_t</emphasis> per default. fcontext_t
|
||
|
is based on assembler and not available for all platforms. It provides a
|
||
|
much better performance than <emphasis>ucontext_t</emphasis> (the context
|
||
|
switch takes two magnitudes of order less CPU cycles; see section <link linkend="performance"><emphasis>performance</emphasis></link>)
|
||
|
and <emphasis>WinFiber</emphasis>.
|
||
|
</para>
|
||
|
<note>
|
||
|
<para>
|
||
|
Because the TIB (thread information block on Windows) is not fully described
|
||
|
in the MSDN, it might be possible that not all required TIB-parts are swapped.
|
||
|
Using WinFiber implementation migh be an alternative.
|
||
|
</para>
|
||
|
</note>
|
||
|
<bridgehead renderas="sect4" id="context.cc.implementations__fcontext_t__ucontext_t_and_winfiber.h1">
|
||
|
<phrase id="context.cc.implementations__fcontext_t__ucontext_t_and_winfiber.ucontext_t"/><link
|
||
|
linkend="context.cc.implementations__fcontext_t__ucontext_t_and_winfiber.ucontext_t">ucontext_t</link>
|
||
|
</bridgehead>
|
||
|
<para>
|
||
|
As an alternative, <ulink url="https://en.wikipedia.org/wiki/Setcontext"><emphasis>ucontext_t</emphasis></ulink>
|
||
|
can be used by compiling with <code><phrase role="identifier">BOOST_USE_UCONTEXT</phrase></code>
|
||
|
and b2 property <code><phrase role="identifier">context</phrase><phrase role="special">-</phrase><phrase
|
||
|
role="identifier">impl</phrase><phrase role="special">=</phrase><phrase role="identifier">ucontext</phrase></code>.
|
||
|
<emphasis>ucontext_t</emphasis> might be available on a broader range of
|
||
|
POSIX-platforms but has some <link linkend="ucontext"><emphasis>disadvantages</emphasis></link>
|
||
|
(for instance deprecated since POSIX.1-2003, not C99 conform).
|
||
|
</para>
|
||
|
<note>
|
||
|
<para>
|
||
|
<link linkend="cc"><emphasis>callcc()</emphasis></link> supports <link
|
||
|
linkend="segmented"><emphasis>Segmented stacks</emphasis></link> only with
|
||
|
<emphasis>ucontext_t</emphasis> as its implementation.
|
||
|
</para>
|
||
|
</note>
|
||
|
<bridgehead renderas="sect4" id="context.cc.implementations__fcontext_t__ucontext_t_and_winfiber.h2">
|
||
|
<phrase id="context.cc.implementations__fcontext_t__ucontext_t_and_winfiber.winfiber"/><link
|
||
|
linkend="context.cc.implementations__fcontext_t__ucontext_t_and_winfiber.winfiber">WinFiber</link>
|
||
|
</bridgehead>
|
||
|
<para>
|
||
|
With <code><phrase role="identifier">BOOST_USE_WINFIB</phrase></code> and
|
||
|
b2 property <code><phrase role="identifier">context</phrase><phrase role="special">-</phrase><phrase
|
||
|
role="identifier">impl</phrase><phrase role="special">=</phrase><phrase role="identifier">winfib</phrase></code>
|
||
|
Win32-Fibers are used as implementation for <link linkend="cc"><emphasis>callcc()</emphasis></link>.
|
||
|
</para>
|
||
|
<note>
|
||
|
<para>
|
||
|
The first call of <link linkend="cc"><emphasis>callcc()</emphasis></link>
|
||
|
converts the thread into a Windows fiber by invoking <code><phrase role="identifier">ConvertThreadToFiber</phrase><phrase
|
||
|
role="special">()</phrase></code>. If desired, <code><phrase role="identifier">ConvertFiberToThread</phrase><phrase
|
||
|
role="special">()</phrase></code> has to be called by the user explicitly
|
||
|
in order to release resources allocated by <code><phrase role="identifier">ConvertThreadToFiber</phrase><phrase
|
||
|
role="special">()</phrase></code> (e.g. after using boost.context).
|
||
|
</para>
|
||
|
</note>
|
||
|
</section>
|
||
|
<section id="context.cc.class__continuation_">
|
||
|
<title><link linkend="context.cc.class__continuation_">Class <code><phrase
|
||
|
role="identifier">continuation</phrase></code></link></title>
|
||
|
<programlisting><phrase role="preprocessor">#include</phrase> <phrase role="special"><</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">context</phrase><phrase role="special">/</phrase><phrase role="identifier">continuation</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">></phrase>
|
||
|
|
||
|
<phrase role="keyword">class</phrase> <phrase role="identifier">continuation</phrase> <phrase role="special">{</phrase>
|
||
|
<phrase role="keyword">public</phrase><phrase role="special">:</phrase>
|
||
|
<phrase role="identifier">continuation</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase> <phrase role="special">=</phrase> <phrase role="keyword">default</phrase><phrase role="special">;</phrase>
|
||
|
|
||
|
<phrase role="special">~</phrase><phrase role="identifier">continuation</phrase><phrase role="special">();</phrase>
|
||
|
|
||
|
<phrase role="identifier">continuation</phrase><phrase role="special">(</phrase><phrase role="identifier">continuation</phrase> <phrase role="special">&&</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
|
||
|
|
||
|
<phrase role="identifier">continuation</phrase> <phrase role="special">&</phrase> <phrase role="keyword">operator</phrase><phrase role="special">=(</phrase><phrase role="identifier">continuation</phrase> <phrase role="special">&&</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
|
||
|
|
||
|
<phrase role="identifier">continuation</phrase><phrase role="special">(</phrase><phrase role="identifier">continuation</phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase> <phrase role="special">=</phrase> <phrase role="keyword">delete</phrase><phrase role="special">;</phrase>
|
||
|
<phrase role="identifier">continuation</phrase> <phrase role="special">&</phrase> <phrase role="keyword">operator</phrase><phrase role="special">=(</phrase><phrase role="identifier">continuation</phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase> <phrase role="special">=</phrase> <phrase role="keyword">delete</phrase><phrase role="special">;</phrase>
|
||
|
|
||
|
<phrase role="identifier">continuation</phrase> <phrase role="identifier">resume</phrase><phrase role="special">();</phrase>
|
||
|
|
||
|
<phrase role="keyword">template</phrase><phrase role="special"><</phrase><phrase role="keyword">typename</phrase> <phrase role="identifier">Fn</phrase><phrase role="special">></phrase>
|
||
|
<phrase role="identifier">continuation</phrase> <phrase role="identifier">resume_with</phrase><phrase role="special">(</phrase><phrase role="identifier">Fn</phrase> <phrase role="special">&&</phrase> <phrase role="identifier">fn</phrase><phrase role="special">);</phrase>
|
||
|
|
||
|
<phrase role="keyword">explicit</phrase> <phrase role="keyword">operator</phrase> <phrase role="keyword">bool</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
|
||
|
|
||
|
<phrase role="keyword">bool</phrase> <phrase role="keyword">operator</phrase><phrase role="special">!()</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
|
||
|
|
||
|
<phrase role="keyword">bool</phrase> <phrase role="keyword">operator</phrase><phrase role="special">==(</phrase><phrase role="identifier">continuation</phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
|
||
|
|
||
|
<phrase role="keyword">bool</phrase> <phrase role="keyword">operator</phrase><phrase role="special">!=(</phrase><phrase role="identifier">continuation</phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
|
||
|
|
||
|
<phrase role="keyword">bool</phrase> <phrase role="keyword">operator</phrase><phrase role="special"><(</phrase><phrase role="identifier">continuation</phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
|
||
|
|
||
|
<phrase role="keyword">bool</phrase> <phrase role="keyword">operator</phrase><phrase role="special">>(</phrase><phrase role="identifier">continuation</phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
|
||
|
|
||
|
<phrase role="keyword">bool</phrase> <phrase role="keyword">operator</phrase><phrase role="special"><=(</phrase><phrase role="identifier">continuation</phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
|
||
|
|
||
|
<phrase role="keyword">bool</phrase> <phrase role="keyword">operator</phrase><phrase role="special">>=(</phrase><phrase role="identifier">continuation</phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
|
||
|
|
||
|
<phrase role="keyword">template</phrase><phrase role="special"><</phrase><phrase role="keyword">typename</phrase> <phrase role="identifier">charT</phrase><phrase role="special">,</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">traitsT</phrase><phrase role="special">></phrase>
|
||
|
<phrase role="keyword">friend</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">basic_ostream</phrase><phrase role="special"><</phrase><phrase role="identifier">charT</phrase><phrase role="special">,</phrase><phrase role="identifier">traitsT</phrase><phrase role="special">></phrase> <phrase role="special">&</phrase>
|
||
|
<phrase role="keyword">operator</phrase><phrase role="special"><<(</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">basic_ostream</phrase><phrase role="special"><</phrase><phrase role="identifier">charT</phrase><phrase role="special">,</phrase><phrase role="identifier">traitsT</phrase><phrase role="special">></phrase> <phrase role="special">&</phrase> <phrase role="identifier">os</phrase><phrase role="special">,</phrase><phrase role="identifier">continuation</phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
|
||
|
|
||
|
<phrase role="keyword">void</phrase> <phrase role="identifier">swap</phrase><phrase role="special">(</phrase><phrase role="identifier">continuation</phrase> <phrase role="special">&</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
|
||
|
<phrase role="special">};</phrase>
|
||
|
</programlisting>
|
||
|
<para>
|
||
|
<bridgehead renderas="sect4" id="cc_constructor_bridgehead">
|
||
|
<phrase id="cc_constructor"/>
|
||
|
<link linkend="cc_constructor">Constructor</link>
|
||
|
</bridgehead>
|
||
|
</para>
|
||
|
<programlisting><phrase role="identifier">continuation</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
|
||
|
</programlisting>
|
||
|
<variablelist>
|
||
|
<title></title>
|
||
|
<varlistentry>
|
||
|
<term>Effects:</term>
|
||
|
<listitem>
|
||
|
<para>
|
||
|
Creates a invalid continuation.
|
||
|
</para>
|
||
|
</listitem>
|
||
|
</varlistentry>
|
||
|
<varlistentry>
|
||
|
<term>Throws:</term>
|
||
|
<listitem>
|
||
|
<para>
|
||
|
Nothing.
|
||
|
</para>
|
||
|
</listitem>
|
||
|
</varlistentry>
|
||
|
</variablelist>
|
||
|
<para>
|
||
|
<bridgehead renderas="sect4" id="cc_destructor destructor_bridgehead">
|
||
|
<phrase id="cc_destructor destructor"/>
|
||
|
<link linkend="cc_destructor
|
||
|
destructor">Destructor</link>
|
||
|
</bridgehead>
|
||
|
</para>
|
||
|
<programlisting><phrase role="special">~</phrase><phrase role="identifier">continuation</phrase><phrase role="special">();</phrase>
|
||
|
</programlisting>
|
||
|
<variablelist>
|
||
|
<title></title>
|
||
|
<varlistentry>
|
||
|
<term>Effects:</term>
|
||
|
<listitem>
|
||
|
<para>
|
||
|
Destructs the associated stack if <code><phrase role="special">*</phrase><phrase
|
||
|
role="keyword">this</phrase></code> is a valid continuation, e.g.
|
||
|
<emphasis>continuation::operator bool()</emphasis> returns <code><phrase
|
||
|
role="keyword">true</phrase></code>.
|
||
|
</para>
|
||
|
</listitem>
|
||
|
</varlistentry>
|
||
|
<varlistentry>
|
||
|
<term>Throws:</term>
|
||
|
<listitem>
|
||
|
<para>
|
||
|
Nothing.
|
||
|
</para>
|
||
|
</listitem>
|
||
|
</varlistentry>
|
||
|
</variablelist>
|
||
|
<para>
|
||
|
<bridgehead renderas="sect4" id="cc_move constructor_bridgehead">
|
||
|
<phrase id="cc_move constructor"/>
|
||
|
<link linkend="cc_move constructor">Move
|
||
|
constructor</link>
|
||
|
</bridgehead>
|
||
|
</para>
|
||
|
<programlisting><phrase role="identifier">continuation</phrase><phrase role="special">(</phrase><phrase role="identifier">continuation</phrase> <phrase role="special">&&</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
|
||
|
</programlisting>
|
||
|
<variablelist>
|
||
|
<title></title>
|
||
|
<varlistentry>
|
||
|
<term>Effects:</term>
|
||
|
<listitem>
|
||
|
<para>
|
||
|
Moves underlying capture continuation to <code><phrase role="special">*</phrase><phrase
|
||
|
role="keyword">this</phrase></code>.
|
||
|
</para>
|
||
|
</listitem>
|
||
|
</varlistentry>
|
||
|
<varlistentry>
|
||
|
<term>Throws:</term>
|
||
|
<listitem>
|
||
|
<para>
|
||
|
Nothing.
|
||
|
</para>
|
||
|
</listitem>
|
||
|
</varlistentry>
|
||
|
</variablelist>
|
||
|
<para>
|
||
|
<bridgehead renderas="sect4" id="cc_move assignment_bridgehead">
|
||
|
<phrase id="cc_move assignment"/>
|
||
|
<link linkend="cc_move assignment">Move assignment
|
||
|
operator</link>
|
||
|
</bridgehead>
|
||
|
</para>
|
||
|
<programlisting><phrase role="identifier">continuation</phrase> <phrase role="special">&</phrase> <phrase role="keyword">operator</phrase><phrase role="special">=(</phrase><phrase role="identifier">continuation</phrase> <phrase role="special">&&</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
|
||
|
</programlisting>
|
||
|
<variablelist>
|
||
|
<title></title>
|
||
|
<varlistentry>
|
||
|
<term>Effects:</term>
|
||
|
<listitem>
|
||
|
<para>
|
||
|
Moves the state of <code><phrase role="identifier">other</phrase></code>
|
||
|
to <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>
|
||
|
using move semantics.
|
||
|
</para>
|
||
|
</listitem>
|
||
|
</varlistentry>
|
||
|
<varlistentry>
|
||
|
<term>Throws:</term>
|
||
|
<listitem>
|
||
|
<para>
|
||
|
Nothing.
|
||
|
</para>
|
||
|
</listitem>
|
||
|
</varlistentry>
|
||
|
</variablelist>
|
||
|
<para>
|
||
|
<bridgehead renderas="sect4" id="cc_operator_call_bridgehead">
|
||
|
<phrase id="cc_operator_call"/>
|
||
|
<link linkend="cc_operator_call">Member function
|
||
|
<code>operator()</code>()</link>
|
||
|
</bridgehead>
|
||
|
</para>
|
||
|
<programlisting><phrase role="identifier">continuation</phrase> <phrase role="identifier">resume</phrase><phrase role="special">();</phrase>
|
||
|
|
||
|
<phrase role="keyword">template</phrase><phrase role="special"><</phrase><phrase role="keyword">typename</phrase> <phrase role="identifier">Fn</phrase><phrase role="special">></phrase>
|
||
|
<phrase role="identifier">continuation</phrase> <phrase role="identifier">resume_with</phrase><phrase role="special">(</phrase><phrase role="identifier">Fn</phrase> <phrase role="special">&&</phrase> <phrase role="identifier">fn</phrase><phrase role="special">);</phrase>
|
||
|
</programlisting>
|
||
|
<variablelist>
|
||
|
<title></title>
|
||
|
<varlistentry>
|
||
|
<term>Effects:</term>
|
||
|
<listitem>
|
||
|
<para>
|
||
|
Captures current continuation and resumes <code><phrase role="special">*</phrase><phrase
|
||
|
role="keyword">this</phrase></code>. The function <code><phrase role="identifier">resume_with</phrase></code>,
|
||
|
is used to execute function <code><phrase role="identifier">fn</phrase></code>
|
||
|
in the execution context of <code><phrase role="special">*</phrase><phrase
|
||
|
role="keyword">this</phrase></code> (e.g. the stack frame of <code><phrase
|
||
|
role="identifier">fn</phrase></code> is allocated on stack of <code><phrase
|
||
|
role="special">*</phrase><phrase role="keyword">this</phrase></code>).
|
||
|
</para>
|
||
|
</listitem>
|
||
|
</varlistentry>
|
||
|
<varlistentry>
|
||
|
<term>Returns:</term>
|
||
|
<listitem>
|
||
|
<para>
|
||
|
The continuation representing the continuation that has been suspended.
|
||
|
</para>
|
||
|
</listitem>
|
||
|
</varlistentry>
|
||
|
<varlistentry>
|
||
|
<term>Note:</term>
|
||
|
<listitem>
|
||
|
<para>
|
||
|
Function <code><phrase role="identifier">fn</phrase></code> needs to
|
||
|
return <code><phrase role="identifier">continuation</phrase></code>.
|
||
|
</para>
|
||
|
</listitem>
|
||
|
</varlistentry>
|
||
|
<varlistentry>
|
||
|
<term>Note:</term>
|
||
|
<listitem>
|
||
|
<para>
|
||
|
The returned continuation indicates if the suspended continuation has
|
||
|
terminated (return from context-function) via <code><phrase role="keyword">bool</phrase>
|
||
|
<phrase role="keyword">operator</phrase><phrase role="special">()</phrase></code>.
|
||
|
</para>
|
||
|
</listitem>
|
||
|
</varlistentry>
|
||
|
</variablelist>
|
||
|
<para>
|
||
|
<bridgehead renderas="sect4" id="cc_operator_bool_bridgehead">
|
||
|
<phrase id="cc_operator_bool"/>
|
||
|
<link linkend="cc_operator_bool">Member function
|
||
|
<code>operator bool</code>()</link>
|
||
|
</bridgehead>
|
||
|
</para>
|
||
|
<programlisting><phrase role="keyword">explicit</phrase> <phrase role="keyword">operator</phrase> <phrase role="keyword">bool</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
|
||
|
</programlisting>
|
||
|
<variablelist>
|
||
|
<title></title>
|
||
|
<varlistentry>
|
||
|
<term>Returns:</term>
|
||
|
<listitem>
|
||
|
<para>
|
||
|
<code><phrase role="keyword">true</phrase></code> if <code><phrase
|
||
|
role="special">*</phrase><phrase role="keyword">this</phrase></code>
|
||
|
points to a captured continuation.
|
||
|
</para>
|
||
|
</listitem>
|
||
|
</varlistentry>
|
||
|
<varlistentry>
|
||
|
<term>Throws:</term>
|
||
|
<listitem>
|
||
|
<para>
|
||
|
Nothing.
|
||
|
</para>
|
||
|
</listitem>
|
||
|
</varlistentry>
|
||
|
</variablelist>
|
||
|
<para>
|
||
|
<bridgehead renderas="sect4" id="cc_operator_not_bridgehead">
|
||
|
<phrase id="cc_operator_not"/>
|
||
|
<link linkend="cc_operator_not">Member function <code>operator!</code>()</link>
|
||
|
</bridgehead>
|
||
|
</para>
|
||
|
<programlisting><phrase role="keyword">bool</phrase> <phrase role="keyword">operator</phrase><phrase role="special">!()</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
|
||
|
</programlisting>
|
||
|
<variablelist>
|
||
|
<title></title>
|
||
|
<varlistentry>
|
||
|
<term>Returns:</term>
|
||
|
<listitem>
|
||
|
<para>
|
||
|
<code><phrase role="keyword">true</phrase></code> if <code><phrase
|
||
|
role="special">*</phrase><phrase role="keyword">this</phrase></code>
|
||
|
does not point to a captured continuation.
|
||
|
</para>
|
||
|
</listitem>
|
||
|
</varlistentry>
|
||
|
<varlistentry>
|
||
|
<term>Throws:</term>
|
||
|
<listitem>
|
||
|
<para>
|
||
|
Nothing.
|
||
|
</para>
|
||
|
</listitem>
|
||
|
</varlistentry>
|
||
|
</variablelist>
|
||
|
<para>
|
||
|
<bridgehead renderas="sect4" id="cc_operator_equal_bridgehead">
|
||
|
<phrase id="cc_operator_equal"/>
|
||
|
<link linkend="cc_operator_equal">Member function
|
||
|
<code>operator==</code>()</link>
|
||
|
</bridgehead>
|
||
|
</para>
|
||
|
<programlisting><phrase role="keyword">bool</phrase> <phrase role="keyword">operator</phrase><phrase role="special">==(</phrase><phrase role="identifier">continuation</phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
|
||
|
</programlisting>
|
||
|
<variablelist>
|
||
|
<title></title>
|
||
|
<varlistentry>
|
||
|
<term>Returns:</term>
|
||
|
<listitem>
|
||
|
<para>
|
||
|
<code><phrase role="keyword">true</phrase></code> if <code><phrase
|
||
|
role="special">*</phrase><phrase role="keyword">this</phrase></code>
|
||
|
and <code><phrase role="identifier">other</phrase></code> represent
|
||
|
the same continuation, <code><phrase role="keyword">false</phrase></code>
|
||
|
otherwise.
|
||
|
</para>
|
||
|
</listitem>
|
||
|
</varlistentry>
|
||
|
<varlistentry>
|
||
|
<term>Throws:</term>
|
||
|
<listitem>
|
||
|
<para>
|
||
|
Nothing.
|
||
|
</para>
|
||
|
</listitem>
|
||
|
</varlistentry>
|
||
|
</variablelist>
|
||
|
<para>
|
||
|
<bridgehead renderas="sect4" id="cc_operator_notequal_bridgehead">
|
||
|
<phrase id="cc_operator_notequal"/>
|
||
|
<link linkend="cc_operator_notequal">Member
|
||
|
function <code>operator!=</code>()</link>
|
||
|
</bridgehead>
|
||
|
</para>
|
||
|
<programlisting><phrase role="keyword">bool</phrase> <phrase role="keyword">operator</phrase><phrase role="special">!=(</phrase><phrase role="identifier">continuation</phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
|
||
|
</programlisting>
|
||
|
<variablelist>
|
||
|
<title></title>
|
||
|
<varlistentry>
|
||
|
<term>Returns:</term>
|
||
|
<listitem>
|
||
|
<para>
|
||
|
<code>! (other == * this)</code>
|
||
|
</para>
|
||
|
</listitem>
|
||
|
</varlistentry>
|
||
|
<varlistentry>
|
||
|
<term>Throws:</term>
|
||
|
<listitem>
|
||
|
<para>
|
||
|
Nothing.
|
||
|
</para>
|
||
|
</listitem>
|
||
|
</varlistentry>
|
||
|
</variablelist>
|
||
|
<para>
|
||
|
<bridgehead renderas="sect4" id="cc_operator_less_bridgehead">
|
||
|
<phrase id="cc_operator_less"/>
|
||
|
<link linkend="cc_operator_less">Member function
|
||
|
<code>operator<</code>()</link>
|
||
|
</bridgehead>
|
||
|
</para>
|
||
|
<programlisting><phrase role="keyword">bool</phrase> <phrase role="keyword">operator</phrase><phrase role="special"><(</phrase><phrase role="identifier">continuation</phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
|
||
|
</programlisting>
|
||
|
<variablelist>
|
||
|
<title></title>
|
||
|
<varlistentry>
|
||
|
<term>Returns:</term>
|
||
|
<listitem>
|
||
|
<para>
|
||
|
<code><phrase role="keyword">true</phrase></code> if <code><phrase
|
||
|
role="special">*</phrase><phrase role="keyword">this</phrase> <phrase
|
||
|
role="special">!=</phrase> <phrase role="identifier">other</phrase></code>
|
||
|
is true and the implementation-defined total order of <code><phrase
|
||
|
role="identifier">continuation</phrase></code> values places <code><phrase
|
||
|
role="special">*</phrase><phrase role="keyword">this</phrase></code>
|
||
|
before <code><phrase role="identifier">other</phrase></code>, false
|
||
|
otherwise.
|
||
|
</para>
|
||
|
</listitem>
|
||
|
</varlistentry>
|
||
|
<varlistentry>
|
||
|
<term>Throws:</term>
|
||
|
<listitem>
|
||
|
<para>
|
||
|
Nothing.
|
||
|
</para>
|
||
|
</listitem>
|
||
|
</varlistentry>
|
||
|
</variablelist>
|
||
|
<para>
|
||
|
<bridgehead renderas="sect4" id="cc_operator_greater_bridgehead">
|
||
|
<phrase id="cc_operator_greater"/>
|
||
|
<link linkend="cc_operator_greater">Member
|
||
|
function <code>operator></code>()</link>
|
||
|
</bridgehead>
|
||
|
</para>
|
||
|
<programlisting><phrase role="keyword">bool</phrase> <phrase role="keyword">operator</phrase><phrase role="special">>(</phrase><phrase role="identifier">continuation</phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
|
||
|
</programlisting>
|
||
|
<variablelist>
|
||
|
<title></title>
|
||
|
<varlistentry>
|
||
|
<term>Returns:</term>
|
||
|
<listitem>
|
||
|
<para>
|
||
|
<code><phrase role="identifier">other</phrase> <phrase role="special"><</phrase>
|
||
|
<phrase role="special">*</phrase> <phrase role="keyword">this</phrase></code>
|
||
|
</para>
|
||
|
</listitem>
|
||
|
</varlistentry>
|
||
|
<varlistentry>
|
||
|
<term>Throws:</term>
|
||
|
<listitem>
|
||
|
<para>
|
||
|
Nothing.
|
||
|
</para>
|
||
|
</listitem>
|
||
|
</varlistentry>
|
||
|
</variablelist>
|
||
|
<para>
|
||
|
<bridgehead renderas="sect4" id="cc_operator_lesseq_bridgehead">
|
||
|
<phrase id="cc_operator_lesseq"/>
|
||
|
<link linkend="cc_operator_lesseq">Member function
|
||
|
<code>operator<=</code>()</link>
|
||
|
</bridgehead>
|
||
|
</para>
|
||
|
<programlisting><phrase role="keyword">bool</phrase> <phrase role="keyword">operator</phrase><phrase role="special"><=(</phrase><phrase role="identifier">continuation</phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
|
||
|
</programlisting>
|
||
|
<variablelist>
|
||
|
<title></title>
|
||
|
<varlistentry>
|
||
|
<term>Returns:</term>
|
||
|
<listitem>
|
||
|
<para>
|
||
|
<code><phrase role="special">!</phrase> <phrase role="special">(</phrase><phrase
|
||
|
role="identifier">other</phrase> <phrase role="special"><</phrase>
|
||
|
<phrase role="special">*</phrase> <phrase role="keyword">this</phrase><phrase
|
||
|
role="special">)</phrase></code>
|
||
|
</para>
|
||
|
</listitem>
|
||
|
</varlistentry>
|
||
|
<varlistentry>
|
||
|
<term>Throws:</term>
|
||
|
<listitem>
|
||
|
<para>
|
||
|
Nothing.
|
||
|
</para>
|
||
|
</listitem>
|
||
|
</varlistentry>
|
||
|
</variablelist>
|
||
|
<para>
|
||
|
<bridgehead renderas="sect4" id="cc_operator_greatereq_bridgehead">
|
||
|
<phrase id="cc_operator_greatereq"/>
|
||
|
<link linkend="cc_operator_greatereq">Member
|
||
|
function <code>operator>=</code>()</link>
|
||
|
</bridgehead>
|
||
|
</para>
|
||
|
<programlisting><phrase role="keyword">bool</phrase> <phrase role="keyword">operator</phrase><phrase role="special">>=(</phrase><phrase role="identifier">continuation</phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
|
||
|
</programlisting>
|
||
|
<variablelist>
|
||
|
<title></title>
|
||
|
<varlistentry>
|
||
|
<term>Returns:</term>
|
||
|
<listitem>
|
||
|
<para>
|
||
|
<code><phrase role="special">!</phrase> <phrase role="special">(*</phrase>
|
||
|
<phrase role="keyword">this</phrase> <phrase role="special"><</phrase>
|
||
|
<phrase role="identifier">other</phrase><phrase role="special">)</phrase></code>
|
||
|
</para>
|
||
|
</listitem>
|
||
|
</varlistentry>
|
||
|
<varlistentry>
|
||
|
<term>Throws:</term>
|
||
|
<listitem>
|
||
|
<para>
|
||
|
Nothing.
|
||
|
</para>
|
||
|
</listitem>
|
||
|
</varlistentry>
|
||
|
</variablelist>
|
||
|
<para>
|
||
|
<bridgehead renderas="sect4" id="cc__bridgehead">
|
||
|
<phrase id="cc_"/>
|
||
|
<link linkend="cc_">Non-member function <code>operator<<()</code></link>
|
||
|
</bridgehead>
|
||
|
</para>
|
||
|
<programlisting><phrase role="keyword">template</phrase><phrase role="special"><</phrase><phrase role="keyword">typename</phrase> <phrase role="identifier">charT</phrase><phrase role="special">,</phrase><phrase role="keyword">class</phrase> <phrase role="identifier">traitsT</phrase><phrase role="special">></phrase>
|
||
|
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">basic_ostream</phrase><phrase role="special"><</phrase><phrase role="identifier">charT</phrase><phrase role="special">,</phrase><phrase role="identifier">traitsT</phrase><phrase role="special">></phrase> <phrase role="special">&</phrase>
|
||
|
<phrase role="keyword">operator</phrase><phrase role="special"><<(</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">basic_ostream</phrase><phrase role="special"><</phrase><phrase role="identifier">charT</phrase><phrase role="special">,</phrase><phrase role="identifier">traitsT</phrase><phrase role="special">></phrase> <phrase role="special">&</phrase> <phrase role="identifier">os</phrase><phrase role="special">,</phrase><phrase role="identifier">continuation</phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">other</phrase><phrase role="special">);</phrase>
|
||
|
</programlisting>
|
||
|
<variablelist>
|
||
|
<title></title>
|
||
|
<varlistentry>
|
||
|
<term>Effects:</term>
|
||
|
<listitem>
|
||
|
<para>
|
||
|
Writes the representation of <code><phrase role="identifier">other</phrase></code>
|
||
|
to stream <code><phrase role="identifier">os</phrase></code>.
|
||
|
</para>
|
||
|
</listitem>
|
||
|
</varlistentry>
|
||
|
<varlistentry>
|
||
|
<term>Returns:</term>
|
||
|
<listitem>
|
||
|
<para>
|
||
|
<code><phrase role="identifier">os</phrase></code>
|
||
|
</para>
|
||
|
</listitem>
|
||
|
</varlistentry>
|
||
|
</variablelist>
|
||
|
<bridgehead renderas="sect4" id="context.cc.class__continuation_.h0">
|
||
|
<phrase id="context.cc.class__continuation_.call_with_current_continuation"/><link
|
||
|
linkend="context.cc.class__continuation_.call_with_current_continuation">Call
|
||
|
with current continuation</link>
|
||
|
</bridgehead>
|
||
|
<programlisting><phrase role="preprocessor">#include</phrase> <phrase role="special"><</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">context</phrase><phrase role="special">/</phrase><phrase role="identifier">continuation</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">></phrase>
|
||
|
|
||
|
<phrase role="keyword">template</phrase><phrase role="special"><</phrase><phrase role="keyword">typename</phrase> <phrase role="identifier">Fn</phrase><phrase role="special">></phrase>
|
||
|
<phrase role="identifier">continuation</phrase> <phrase role="identifier">callcc</phrase><phrase role="special">(</phrase><phrase role="identifier">Fn</phrase> <phrase role="special">&&</phrase> <phrase role="identifier">fn</phrase><phrase role="special">);</phrase>
|
||
|
|
||
|
<phrase role="keyword">template</phrase><phrase role="special"><</phrase><phrase role="keyword">typename</phrase> <phrase role="identifier">StackAlloc</phrase><phrase role="special">,</phrase><phrase role="keyword">typename</phrase> <phrase role="identifier">Fn</phrase><phrase role="special">></phrase>
|
||
|
<phrase role="identifier">continuation</phrase> <phrase role="identifier">callcc</phrase><phrase role="special">(</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">allocator_arg_t</phrase><phrase role="special">,</phrase><phrase role="identifier">StackAlloc</phrase> <phrase role="identifier">salloc</phrase><phrase role="special">,</phrase><phrase role="identifier">Fn</phrase> <phrase role="special">&&</phrase> <phrase role="identifier">fn</phrase><phrase role="special">);</phrase>
|
||
|
|
||
|
<phrase role="keyword">template</phrase><phrase role="special"><</phrase><phrase role="keyword">typename</phrase> <phrase role="identifier">StackAlloc</phrase><phrase role="special">,</phrase><phrase role="keyword">typename</phrase> <phrase role="identifier">Fn</phrase><phrase role="special">></phrase>
|
||
|
<phrase role="identifier">continuation</phrase> <phrase role="identifier">callcc</phrase><phrase role="special">(</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">allocator_arg_t</phrase><phrase role="special">,</phrase><phrase role="identifier">preallocated</phrase> <phrase role="identifier">palloc</phrase><phrase role="special">,</phrase><phrase role="identifier">StackAlloc</phrase> <phrase role="identifier">salloc</phrase><phrase role="special">,</phrase><phrase role="identifier">Fn</phrase> <phrase role="special">&&</phrase> <phrase role="identifier">fn</phrase><phrase role="special">);</phrase>
|
||
|
</programlisting>
|
||
|
<variablelist>
|
||
|
<title></title>
|
||
|
<varlistentry>
|
||
|
<term>Effects:</term>
|
||
|
<listitem>
|
||
|
<para>
|
||
|
Captures current continuation and creates a new continuation prepared
|
||
|
to execute <code><phrase role="identifier">fn</phrase></code>. <code><phrase
|
||
|
role="identifier">fixedsize_stack</phrase></code> is used as default
|
||
|
stack allocator (stack size == fixedsize_stack::traits::default_size()).
|
||
|
The function with argument type <code><phrase role="identifier">preallocated</phrase></code>,
|
||
|
is used to create a user defined data <link linkend="cc_prealloc">(for
|
||
|
instance additional control structures)</link> on top of the stack.
|
||
|
</para>
|
||
|
</listitem>
|
||
|
</varlistentry>
|
||
|
<varlistentry>
|
||
|
<term>Returns:</term>
|
||
|
<listitem>
|
||
|
<para>
|
||
|
The continuation representing the contexcontinuation that has been
|
||
|
suspended.
|
||
|
</para>
|
||
|
</listitem>
|
||
|
</varlistentry>
|
||
|
<varlistentry>
|
||
|
<term>Note:</term>
|
||
|
<listitem>
|
||
|
<para>
|
||
|
The returned continuation indicates if the suspended continuation has
|
||
|
terminated (return from context-function) via <code><phrase role="keyword">bool</phrase>
|
||
|
<phrase role="keyword">operator</phrase><phrase role="special">()</phrase></code>.
|
||
|
</para>
|
||
|
</listitem>
|
||
|
</varlistentry>
|
||
|
</variablelist>
|
||
|
</section>
|
||
|
</section>
|
||
|
<section id="context.stack">
|
||
|
<title><anchor id="stack"/><link linkend="context.stack">Stack allocation</link></title>
|
||
|
<para>
|
||
|
The memory used by the stack is allocated/deallocated via a <emphasis>StackAllocator</emphasis>
|
||
|
which is required to model a <emphasis>stack-allocator concept</emphasis>.
|
||
|
</para>
|
||
|
<bridgehead renderas="sect3" id="context.stack.h0">
|
||
|
<phrase id="context.stack._emphasis_stack_allocator_concept__emphasis_"/><link
|
||
|
linkend="context.stack._emphasis_stack_allocator_concept__emphasis_"><emphasis>stack-allocator
|
||
|
concept</emphasis></link>
|
||
|
</bridgehead>
|
||
|
<para>
|
||
|
A <emphasis>StackAllocator</emphasis> must satisfy the <emphasis>stack-allocator
|
||
|
concept</emphasis> requirements shown in the following table, in which <code><phrase
|
||
|
role="identifier">a</phrase></code> is an object of a <emphasis>StackAllocator</emphasis>
|
||
|
type, <code><phrase role="identifier">sctx</phrase></code> is a <code><phrase
|
||
|
role="identifier">stack_context</phrase></code>, and <code><phrase role="identifier">size</phrase></code>
|
||
|
is a <code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase
|
||
|
role="identifier">size_t</phrase></code>:
|
||
|
</para>
|
||
|
<informaltable frame="all">
|
||
|
<tgroup cols="3">
|
||
|
<thead>
|
||
|
<row>
|
||
|
<entry>
|
||
|
<para>
|
||
|
expression
|
||
|
</para>
|
||
|
</entry>
|
||
|
<entry>
|
||
|
<para>
|
||
|
return type
|
||
|
</para>
|
||
|
</entry>
|
||
|
<entry>
|
||
|
<para>
|
||
|
notes
|
||
|
</para>
|
||
|
</entry>
|
||
|
</row>
|
||
|
</thead>
|
||
|
<tbody>
|
||
|
<row>
|
||
|
<entry>
|
||
|
<para>
|
||
|
<code><phrase role="identifier">a</phrase><phrase role="special">(</phrase><phrase
|
||
|
role="identifier">size</phrase><phrase role="special">)</phrase></code>
|
||
|
</para>
|
||
|
</entry>
|
||
|
<entry>
|
||
|
</entry>
|
||
|
<entry>
|
||
|
<para>
|
||
|
creates a stack allocator
|
||
|
</para>
|
||
|
</entry>
|
||
|
</row>
|
||
|
<row>
|
||
|
<entry>
|
||
|
<para>
|
||
|
<code><phrase role="identifier">a</phrase><phrase role="special">.</phrase><phrase
|
||
|
role="identifier">allocate</phrase><phrase role="special">()</phrase></code>
|
||
|
</para>
|
||
|
</entry>
|
||
|
<entry>
|
||
|
<para>
|
||
|
<code><phrase role="identifier">stack_context</phrase></code>
|
||
|
</para>
|
||
|
</entry>
|
||
|
<entry>
|
||
|
<para>
|
||
|
creates a stack
|
||
|
</para>
|
||
|
</entry>
|
||
|
</row>
|
||
|
<row>
|
||
|
<entry>
|
||
|
<para>
|
||
|
<code><phrase role="identifier">a</phrase><phrase role="special">.</phrase><phrase
|
||
|
role="identifier">deallocate</phrase><phrase role="special">(</phrase>
|
||
|
<phrase role="identifier">sctx</phrase><phrase role="special">)</phrase></code>
|
||
|
</para>
|
||
|
</entry>
|
||
|
<entry>
|
||
|
<para>
|
||
|
<code><phrase role="keyword">void</phrase></code>
|
||
|
</para>
|
||
|
</entry>
|
||
|
<entry>
|
||
|
<para>
|
||
|
deallocates the stack created by <code><phrase role="identifier">a</phrase><phrase
|
||
|
role="special">.</phrase><phrase role="identifier">allocate</phrase><phrase
|
||
|
role="special">()</phrase></code>
|
||
|
</para>
|
||
|
</entry>
|
||
|
</row>
|
||
|
</tbody>
|
||
|
</tgroup>
|
||
|
</informaltable>
|
||
|
<important>
|
||
|
<para>
|
||
|
The implementation of <code><phrase role="identifier">allocate</phrase><phrase
|
||
|
role="special">()</phrase></code> might include logic to protect against
|
||
|
exceeding the context's available stack size rather than leaving it as undefined
|
||
|
behaviour.
|
||
|
</para>
|
||
|
</important>
|
||
|
<important>
|
||
|
<para>
|
||
|
Calling <code><phrase role="identifier">deallocate</phrase><phrase role="special">()</phrase></code>
|
||
|
with a <code><phrase role="identifier">stack_context</phrase></code> not
|
||
|
set by <code><phrase role="identifier">allocate</phrase><phrase role="special">()</phrase></code>
|
||
|
results in undefined behaviour.
|
||
|
</para>
|
||
|
</important>
|
||
|
<note>
|
||
|
<para>
|
||
|
Depending on the architecture <code><phrase role="identifier">allocate</phrase><phrase
|
||
|
role="special">()</phrase></code> stores an address from the top of the stack
|
||
|
(growing downwards) or the bottom of the stack (growing upwards).
|
||
|
</para>
|
||
|
</note>
|
||
|
<section id="context.stack.protected_fixedsize">
|
||
|
<title><link linkend="context.stack.protected_fixedsize">Class <emphasis>protected_fixedsize</emphasis></link></title>
|
||
|
<para>
|
||
|
<emphasis role="bold">Boost.Context</emphasis> provides the class <emphasis>protected_fixedsize_stack</emphasis>
|
||
|
which models the <emphasis>stack-allocator concept</emphasis>. It appends
|
||
|
a guard page at the end of each stack to protect against exceeding the stack.
|
||
|
If the guard page is accessed (read or write operation) a segmentation fault/access
|
||
|
violation is generated by the operating system.
|
||
|
</para>
|
||
|
<important>
|
||
|
<para>
|
||
|
Using <emphasis>protected_fixedsize_stack</emphasis> is expensive. That
|
||
|
is, launching a new coroutine with a new stack is expensive; the allocated
|
||
|
stack is just as efficient to use as any other stack.
|
||
|
</para>
|
||
|
</important>
|
||
|
<note>
|
||
|
<para>
|
||
|
The appended <code><phrase role="identifier">guard</phrase> <phrase role="identifier">page</phrase></code>
|
||
|
is <emphasis role="bold">not</emphasis> mapped to physical memory, only
|
||
|
virtual addresses are used.
|
||
|
</para>
|
||
|
</note>
|
||
|
<programlisting><phrase role="preprocessor">#include</phrase> <phrase role="special"><</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">context</phrase><phrase role="special">/</phrase><phrase role="identifier">protected_fixedsize</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">></phrase>
|
||
|
|
||
|
<phrase role="keyword">template</phrase><phrase role="special"><</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">traitsT</phrase> <phrase role="special">></phrase>
|
||
|
<phrase role="keyword">struct</phrase> <phrase role="identifier">basic_protected_fixedsize</phrase> <phrase role="special">{</phrase>
|
||
|
<phrase role="keyword">typedef</phrase> <phrase role="identifier">traitT</phrase> <phrase role="identifier">traits_type</phrase><phrase role="special">;</phrase>
|
||
|
|
||
|
<phrase role="identifier">basic_protected_fixesize</phrase><phrase role="special">(</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">size</phrase> <phrase role="special">=</phrase> <phrase role="identifier">traits_type</phrase><phrase role="special">::</phrase><phrase role="identifier">default_size</phrase><phrase role="special">());</phrase>
|
||
|
|
||
|
<phrase role="identifier">stack_context</phrase> <phrase role="identifier">allocate</phrase><phrase role="special">();</phrase>
|
||
|
|
||
|
<phrase role="keyword">void</phrase> <phrase role="identifier">deallocate</phrase><phrase role="special">(</phrase> <phrase role="identifier">stack_context</phrase> <phrase role="special">&);</phrase>
|
||
|
<phrase role="special">}</phrase>
|
||
|
|
||
|
<phrase role="keyword">typedef</phrase> <phrase role="identifier">basic_protected_fixedsize</phrase><phrase role="special"><</phrase> <phrase role="identifier">stack_traits</phrase> <phrase role="special">></phrase> <phrase role="identifier">protected_fixedsize</phrase>
|
||
|
</programlisting>
|
||
|
<bridgehead renderas="sect4" id="context.stack.protected_fixedsize.h0">
|
||
|
<phrase id="context.stack.protected_fixedsize._code__phrase_role__identifier__stack_context__phrase___phrase_role__identifier__allocate__phrase__phrase_role__special______phrase___code_"/><link
|
||
|
linkend="context.stack.protected_fixedsize._code__phrase_role__identifier__stack_context__phrase___phrase_role__identifier__allocate__phrase__phrase_role__special______phrase___code_"><code><phrase
|
||
|
role="identifier">stack_context</phrase> <phrase role="identifier">allocate</phrase><phrase
|
||
|
role="special">()</phrase></code></link>
|
||
|
</bridgehead>
|
||
|
<variablelist>
|
||
|
<title></title>
|
||
|
<varlistentry>
|
||
|
<term>Preconditions:</term>
|
||
|
<listitem>
|
||
|
<para>
|
||
|
<code><phrase role="identifier">traits_type</phrase><phrase role="special">::</phrase><phrase
|
||
|
role="identifier">minimum</phrase><phrase role="special">:</phrase><phrase
|
||
|
role="identifier">size</phrase><phrase role="special">()</phrase>
|
||
|
<phrase role="special"><=</phrase> <phrase role="identifier">size</phrase></code>
|
||
|
and <code><phrase role="special">!</phrase> <phrase role="identifier">traits_type</phrase><phrase
|
||
|
role="special">::</phrase><phrase role="identifier">is_unbounded</phrase><phrase
|
||
|
role="special">()</phrase> <phrase role="special">&&</phrase>
|
||
|
<phrase role="special">(</phrase> <phrase role="identifier">traits_type</phrase><phrase
|
||
|
role="special">::</phrase><phrase role="identifier">maximum</phrase><phrase
|
||
|
role="special">:</phrase><phrase role="identifier">size</phrase><phrase
|
||
|
role="special">()</phrase> <phrase role="special">>=</phrase> <phrase
|
||
|
role="identifier">size</phrase><phrase role="special">)</phrase></code>.
|
||
|
</para>
|
||
|
</listitem>
|
||
|
</varlistentry>
|
||
|
<varlistentry>
|
||
|
<term>Effects:</term>
|
||
|
<listitem>
|
||
|
<para>
|
||
|
Allocates memory of at least <code><phrase role="identifier">size</phrase></code>
|
||
|
Bytes and stores a pointer to the stack and its actual size in <code><phrase
|
||
|
role="identifier">sctx</phrase></code>. Depending on the architecture
|
||
|
(the stack grows downwards/upwards) the stored address is the highest/lowest
|
||
|
address of the stack.
|
||
|
</para>
|
||
|
</listitem>
|
||
|
</varlistentry>
|
||
|
</variablelist>
|
||
|
<bridgehead renderas="sect4" id="context.stack.protected_fixedsize.h1">
|
||
|
<phrase id="context.stack.protected_fixedsize._code__phrase_role__keyword__void__phrase___phrase_role__identifier__deallocate__phrase__phrase_role__special_____phrase___phrase_role__identifier__stack_context__phrase___phrase_role__special___amp___phrase___phrase_role__identifier__sctx__phrase__phrase_role__special_____phrase___code_"/><link
|
||
|
linkend="context.stack.protected_fixedsize._code__phrase_role__keyword__void__phrase___phrase_role__identifier__deallocate__phrase__phrase_role__special_____phrase___phrase_role__identifier__stack_context__phrase___phrase_role__special___amp___phrase___phrase_role__identifier__sctx__phrase__phrase_role__special_____phrase___code_"><code><phrase
|
||
|
role="keyword">void</phrase> <phrase role="identifier">deallocate</phrase><phrase
|
||
|
role="special">(</phrase> <phrase role="identifier">stack_context</phrase>
|
||
|
<phrase role="special">&</phrase> <phrase role="identifier">sctx</phrase><phrase
|
||
|
role="special">)</phrase></code></link>
|
||
|
</bridgehead>
|
||
|
<variablelist>
|
||
|
<title></title>
|
||
|
<varlistentry>
|
||
|
<term>Preconditions:</term>
|
||
|
<listitem>
|
||
|
<para>
|
||
|
<code><phrase role="identifier">sctx</phrase><phrase role="special">.</phrase><phrase
|
||
|
role="identifier">sp</phrase></code> is valid, <code><phrase role="identifier">traits_type</phrase><phrase
|
||
|
role="special">::</phrase><phrase role="identifier">minimum</phrase><phrase
|
||
|
role="special">:</phrase><phrase role="identifier">size</phrase><phrase
|
||
|
role="special">()</phrase> <phrase role="special"><=</phrase> <phrase
|
||
|
role="identifier">sctx</phrase><phrase role="special">.</phrase><phrase
|
||
|
role="identifier">size</phrase></code> and <code><phrase role="special">!</phrase>
|
||
|
<phrase role="identifier">traits_type</phrase><phrase role="special">::</phrase><phrase
|
||
|
role="identifier">is_unbounded</phrase><phrase role="special">()</phrase>
|
||
|
<phrase role="special">&&</phrase> <phrase role="special">(</phrase>
|
||
|
<phrase role="identifier">traits_type</phrase><phrase role="special">::</phrase><phrase
|
||
|
role="identifier">maximum</phrase><phrase role="special">:</phrase><phrase
|
||
|
role="identifier">size</phrase><phrase role="special">()</phrase>
|
||
|
<phrase role="special">>=</phrase> <phrase role="identifier">sctx</phrase><phrase
|
||
|
role="special">.</phrase><phrase role="identifier">size</phrase><phrase
|
||
|
role="special">)</phrase></code>.
|
||
|
</para>
|
||
|
</listitem>
|
||
|
</varlistentry>
|
||
|
<varlistentry>
|
||
|
<term>Effects:</term>
|
||
|
<listitem>
|
||
|
<para>
|
||
|
Deallocates the stack space.
|
||
|
</para>
|
||
|
</listitem>
|
||
|
</varlistentry>
|
||
|
</variablelist>
|
||
|
</section>
|
||
|
<section id="context.stack.pooled_fixedsize">
|
||
|
<title><link linkend="context.stack.pooled_fixedsize">Class <emphasis>pooled_fixedsize_stack</emphasis></link></title>
|
||
|
<para>
|
||
|
<emphasis role="bold">Boost.Context</emphasis> provides the class <emphasis>pooled_fixedsize_stack</emphasis>
|
||
|
which models the <emphasis>stack-allocator concept</emphasis>. In contrast
|
||
|
to <emphasis>protected_fixedsize_stack</emphasis> it does not append a guard
|
||
|
page at the end of each stack. The memory is managed internally by <ulink
|
||
|
url="http://www.boost.org/doc/libs/release/libs/pool/doc/html/boost/pool.html"><code><phrase
|
||
|
role="identifier">boost</phrase><phrase role="special">::</phrase><phrase
|
||
|
role="identifier">pool</phrase><phrase role="special"><></phrase></code></ulink>.
|
||
|
</para>
|
||
|
<programlisting><phrase role="preprocessor">#include</phrase> <phrase role="special"><</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">context</phrase><phrase role="special">/</phrase><phrase role="identifier">pooled_fixedsize_stack</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">></phrase>
|
||
|
|
||
|
<phrase role="keyword">template</phrase><phrase role="special"><</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">traitsT</phrase> <phrase role="special">></phrase>
|
||
|
<phrase role="keyword">struct</phrase> <phrase role="identifier">basic_pooled_fixedsize_stack</phrase> <phrase role="special">{</phrase>
|
||
|
<phrase role="keyword">typedef</phrase> <phrase role="identifier">traitT</phrase> <phrase role="identifier">traits_type</phrase><phrase role="special">;</phrase>
|
||
|
|
||
|
<phrase role="identifier">basic_pooled_fixedsize_stack</phrase><phrase role="special">(</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">stack_size</phrase> <phrase role="special">=</phrase> <phrase role="identifier">traits_type</phrase><phrase role="special">::</phrase><phrase role="identifier">default_size</phrase><phrase role="special">(),</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">next_size</phrase> <phrase role="special">=</phrase> <phrase role="number">32</phrase><phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">max_size</phrase> <phrase role="special">=</phrase> <phrase role="number">0</phrase><phrase role="special">);</phrase>
|
||
|
|
||
|
<phrase role="identifier">stack_context</phrase> <phrase role="identifier">allocate</phrase><phrase role="special">();</phrase>
|
||
|
|
||
|
<phrase role="keyword">void</phrase> <phrase role="identifier">deallocate</phrase><phrase role="special">(</phrase> <phrase role="identifier">stack_context</phrase> <phrase role="special">&);</phrase>
|
||
|
<phrase role="special">}</phrase>
|
||
|
|
||
|
<phrase role="keyword">typedef</phrase> <phrase role="identifier">basic_pooled_fixedsize_stack</phrase><phrase role="special"><</phrase> <phrase role="identifier">stack_traits</phrase> <phrase role="special">></phrase> <phrase role="identifier">pooled_fixedsize_stack</phrase><phrase role="special">;</phrase>
|
||
|
</programlisting>
|
||
|
<bridgehead renderas="sect4" id="context.stack.pooled_fixedsize.h0">
|
||
|
<phrase id="context.stack.pooled_fixedsize._code__phrase_role__identifier__basic_pooled_fixedsize_stack__phrase__phrase_role__special_____phrase__phrase_role__identifier__std__phrase__phrase_role__special______phrase__phrase_role__identifier__size_t__phrase___phrase_role__identifier__stack_size__phrase__phrase_role__special_____phrase___phrase_role__identifier__std__phrase__phrase_role__special______phrase__phrase_role__identifier__size_t__phrase___phrase_role__identifier__next_size__phrase__phrase_role__special_____phrase___phrase_role__identifier__std__phrase__phrase_role__special______phrase__phrase_role__identifier__size_t__phrase___phrase_role__identifier__max_size__phrase__phrase_role__special_____phrase___code_"/><link
|
||
|
linkend="context.stack.pooled_fixedsize._code__phrase_role__identifier__basic_pooled_fixedsize_stack__phrase__phrase_role__special_____phrase__phrase_role__identifier__std__phrase__phrase_role__special______phrase__phrase_role__identifier__size_t__phrase___phrase_role__identifier__stack_size__phrase__phrase_role__special_____phrase___phrase_role__identifier__std__phrase__phrase_role__special______phrase__phrase_role__identifier__size_t__phrase___phrase_role__identifier__next_size__phrase__phrase_role__special_____phrase___phrase_role__identifier__std__phrase__phrase_role__special______phrase__phrase_role__identifier__size_t__phrase___phrase_role__identifier__max_size__phrase__phrase_role__special_____phrase___code_"><code><phrase
|
||
|
role="identifier">basic_pooled_fixedsize_stack</phrase><phrase role="special">(</phrase><phrase
|
||
|
role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase>
|
||
|
<phrase role="identifier">stack_size</phrase><phrase role="special">,</phrase>
|
||
|
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase
|
||
|
role="identifier">size_t</phrase> <phrase role="identifier">next_size</phrase><phrase
|
||
|
role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase
|
||
|
role="identifier">size_t</phrase> <phrase role="identifier">max_size</phrase><phrase
|
||
|
role="special">)</phrase></code></link>
|
||
|
</bridgehead>
|
||
|
<variablelist>
|
||
|
<title></title>
|
||
|
<varlistentry>
|
||
|
<term>Preconditions:</term>
|
||
|
<listitem>
|
||
|
<para>
|
||
|
<code><phrase role="special">!</phrase> <phrase role="identifier">traits_type</phrase><phrase
|
||
|
role="special">::</phrase><phrase role="identifier">is_unbounded</phrase><phrase
|
||
|
role="special">()</phrase> <phrase role="special">&&</phrase>
|
||
|
<phrase role="special">(</phrase> <phrase role="identifier">traits_type</phrase><phrase
|
||
|
role="special">::</phrase><phrase role="identifier">maximum</phrase><phrase
|
||
|
role="special">:</phrase><phrase role="identifier">size</phrase><phrase
|
||
|
role="special">()</phrase> <phrase role="special">>=</phrase> <phrase
|
||
|
role="identifier">stack_size</phrase><phrase role="special">)</phrase></code>
|
||
|
and <code><phrase role="number">0</phrase> <phrase role="special"><</phrase>
|
||
|
<phrase role="identifier">nest_size</phrase></code>.
|
||
|
</para>
|
||
|
</listitem>
|
||
|
</varlistentry>
|
||
|
<varlistentry>
|
||
|
<term>Effects:</term>
|
||
|
<listitem>
|
||
|
<para>
|
||
|
Allocates memory of at least <code><phrase role="identifier">stack_size</phrase></code>
|
||
|
Bytes and stores a pointer to the stack and its actual size in <code><phrase
|
||
|
role="identifier">sctx</phrase></code>. Depending on the architecture
|
||
|
(the stack grows downwards/upwards) the stored address is the highest/lowest
|
||
|
address of the stack. Argument <code><phrase role="identifier">next_size</phrase></code>
|
||
|
determines the number of stacks to request from the system the first
|
||
|
time that <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>
|
||
|
needs to allocate system memory. The third argument <code><phrase role="identifier">max_size</phrase></code>
|
||
|
controls how many memory might be allocated for stacks - a value of
|
||
|
zero means no uper limit.
|
||
|
</para>
|
||
|
</listitem>
|
||
|
</varlistentry>
|
||
|
</variablelist>
|
||
|
<bridgehead renderas="sect4" id="context.stack.pooled_fixedsize.h1">
|
||
|
<phrase id="context.stack.pooled_fixedsize._code__phrase_role__identifier__stack_context__phrase___phrase_role__identifier__allocate__phrase__phrase_role__special______phrase___code_"/><link
|
||
|
linkend="context.stack.pooled_fixedsize._code__phrase_role__identifier__stack_context__phrase___phrase_role__identifier__allocate__phrase__phrase_role__special______phrase___code_"><code><phrase
|
||
|
role="identifier">stack_context</phrase> <phrase role="identifier">allocate</phrase><phrase
|
||
|
role="special">()</phrase></code></link>
|
||
|
</bridgehead>
|
||
|
<variablelist>
|
||
|
<title></title>
|
||
|
<varlistentry>
|
||
|
<term>Preconditions:</term>
|
||
|
<listitem>
|
||
|
<para>
|
||
|
<code><phrase role="special">!</phrase> <phrase role="identifier">traits_type</phrase><phrase
|
||
|
role="special">::</phrase><phrase role="identifier">is_unbounded</phrase><phrase
|
||
|
role="special">()</phrase> <phrase role="special">&&</phrase>
|
||
|
<phrase role="special">(</phrase> <phrase role="identifier">traits_type</phrase><phrase
|
||
|
role="special">::</phrase><phrase role="identifier">maximum</phrase><phrase
|
||
|
role="special">:</phrase><phrase role="identifier">size</phrase><phrase
|
||
|
role="special">()</phrase> <phrase role="special">>=</phrase> <phrase
|
||
|
role="identifier">stack_size</phrase><phrase role="special">)</phrase></code>.
|
||
|
</para>
|
||
|
</listitem>
|
||
|
</varlistentry>
|
||
|
<varlistentry>
|
||
|
<term>Effects:</term>
|
||
|
<listitem>
|
||
|
<para>
|
||
|
Allocates memory of at least <code><phrase role="identifier">stack_size</phrase></code>
|
||
|
Bytes and stores a pointer to the stack and its actual size in <code><phrase
|
||
|
role="identifier">sctx</phrase></code>. Depending on the architecture
|
||
|
(the stack grows downwards/upwards) the stored address is the highest/lowest
|
||
|
address of the stack.
|
||
|
</para>
|
||
|
</listitem>
|
||
|
</varlistentry>
|
||
|
</variablelist>
|
||
|
<bridgehead renderas="sect4" id="context.stack.pooled_fixedsize.h2">
|
||
|
<phrase id="context.stack.pooled_fixedsize._code__phrase_role__keyword__void__phrase___phrase_role__identifier__deallocate__phrase__phrase_role__special_____phrase___phrase_role__identifier__stack_context__phrase___phrase_role__special___amp___phrase___phrase_role__identifier__sctx__phrase__phrase_role__special_____phrase___code_"/><link
|
||
|
linkend="context.stack.pooled_fixedsize._code__phrase_role__keyword__void__phrase___phrase_role__identifier__deallocate__phrase__phrase_role__special_____phrase___phrase_role__identifier__stack_context__phrase___phrase_role__special___amp___phrase___phrase_role__identifier__sctx__phrase__phrase_role__special_____phrase___code_"><code><phrase
|
||
|
role="keyword">void</phrase> <phrase role="identifier">deallocate</phrase><phrase
|
||
|
role="special">(</phrase> <phrase role="identifier">stack_context</phrase>
|
||
|
<phrase role="special">&</phrase> <phrase role="identifier">sctx</phrase><phrase
|
||
|
role="special">)</phrase></code></link>
|
||
|
</bridgehead>
|
||
|
<variablelist>
|
||
|
<title></title>
|
||
|
<varlistentry>
|
||
|
<term>Preconditions:</term>
|
||
|
<listitem>
|
||
|
<para>
|
||
|
<code><phrase role="identifier">sctx</phrase><phrase role="special">.</phrase><phrase
|
||
|
role="identifier">sp</phrase></code> is valid, <code><phrase role="special">!</phrase>
|
||
|
<phrase role="identifier">traits_type</phrase><phrase role="special">::</phrase><phrase
|
||
|
role="identifier">is_unbounded</phrase><phrase role="special">()</phrase>
|
||
|
<phrase role="special">&&</phrase> <phrase role="special">(</phrase>
|
||
|
<phrase role="identifier">traits_type</phrase><phrase role="special">::</phrase><phrase
|
||
|
role="identifier">maximum</phrase><phrase role="special">:</phrase><phrase
|
||
|
role="identifier">size</phrase><phrase role="special">()</phrase>
|
||
|
<phrase role="special">>=</phrase> <phrase role="identifier">sctx</phrase><phrase
|
||
|
role="special">.</phrase><phrase role="identifier">size</phrase><phrase
|
||
|
role="special">)</phrase></code>.
|
||
|
</para>
|
||
|
</listitem>
|
||
|
</varlistentry>
|
||
|
<varlistentry>
|
||
|
<term>Effects:</term>
|
||
|
<listitem>
|
||
|
<para>
|
||
|
Deallocates the stack space.
|
||
|
</para>
|
||
|
</listitem>
|
||
|
</varlistentry>
|
||
|
</variablelist>
|
||
|
</section>
|
||
|
<section id="context.stack.fixedsize">
|
||
|
<title><link linkend="context.stack.fixedsize">Class <emphasis>fixedsize_stack</emphasis></link></title>
|
||
|
<para>
|
||
|
<emphasis role="bold">Boost.Context</emphasis> provides the class <emphasis>fixedsize_stack</emphasis>
|
||
|
which models the <emphasis>stack-allocator concept</emphasis>. In contrast
|
||
|
to <emphasis>protected_fixedsize_stack</emphasis> it does not append a guard
|
||
|
page at the end of each stack. The memory is simply managed by <code><phrase
|
||
|
role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">malloc</phrase><phrase
|
||
|
role="special">()</phrase></code> and <code><phrase role="identifier">std</phrase><phrase
|
||
|
role="special">::</phrase><phrase role="identifier">free</phrase><phrase
|
||
|
role="special">()</phrase></code>.
|
||
|
</para>
|
||
|
<programlisting><phrase role="preprocessor">#include</phrase> <phrase role="special"><</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">context</phrase><phrase role="special">/</phrase><phrase role="identifier">fixedsize_stack</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">></phrase>
|
||
|
|
||
|
<phrase role="keyword">template</phrase><phrase role="special"><</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">traitsT</phrase> <phrase role="special">></phrase>
|
||
|
<phrase role="keyword">struct</phrase> <phrase role="identifier">basic_fixedsize_stack</phrase> <phrase role="special">{</phrase>
|
||
|
<phrase role="keyword">typedef</phrase> <phrase role="identifier">traitT</phrase> <phrase role="identifier">traits_type</phrase><phrase role="special">;</phrase>
|
||
|
|
||
|
<phrase role="identifier">basic_fixesize_stack</phrase><phrase role="special">(</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">size</phrase> <phrase role="special">=</phrase> <phrase role="identifier">traits_type</phrase><phrase role="special">::</phrase><phrase role="identifier">default_size</phrase><phrase role="special">());</phrase>
|
||
|
|
||
|
<phrase role="identifier">stack_context</phrase> <phrase role="identifier">allocate</phrase><phrase role="special">();</phrase>
|
||
|
|
||
|
<phrase role="keyword">void</phrase> <phrase role="identifier">deallocate</phrase><phrase role="special">(</phrase> <phrase role="identifier">stack_context</phrase> <phrase role="special">&);</phrase>
|
||
|
<phrase role="special">}</phrase>
|
||
|
|
||
|
<phrase role="keyword">typedef</phrase> <phrase role="identifier">basic_fixedsize_stack</phrase><phrase role="special"><</phrase> <phrase role="identifier">stack_traits</phrase> <phrase role="special">></phrase> <phrase role="identifier">fixedsize_stack</phrase><phrase role="special">;</phrase>
|
||
|
</programlisting>
|
||
|
<bridgehead renderas="sect4" id="context.stack.fixedsize.h0">
|
||
|
<phrase id="context.stack.fixedsize._code__phrase_role__identifier__stack_context__phrase___phrase_role__identifier__allocate__phrase__phrase_role__special______phrase___code_"/><link
|
||
|
linkend="context.stack.fixedsize._code__phrase_role__identifier__stack_context__phrase___phrase_role__identifier__allocate__phrase__phrase_role__special______phrase___code_"><code><phrase
|
||
|
role="identifier">stack_context</phrase> <phrase role="identifier">allocate</phrase><phrase
|
||
|
role="special">()</phrase></code></link>
|
||
|
</bridgehead>
|
||
|
<variablelist>
|
||
|
<title></title>
|
||
|
<varlistentry>
|
||
|
<term>Preconditions:</term>
|
||
|
<listitem>
|
||
|
<para>
|
||
|
<code><phrase role="identifier">traits_type</phrase><phrase role="special">::</phrase><phrase
|
||
|
role="identifier">minimum</phrase><phrase role="special">:</phrase><phrase
|
||
|
role="identifier">size</phrase><phrase role="special">()</phrase>
|
||
|
<phrase role="special"><=</phrase> <phrase role="identifier">size</phrase></code>
|
||
|
and <code><phrase role="special">!</phrase> <phrase role="identifier">traits_type</phrase><phrase
|
||
|
role="special">::</phrase><phrase role="identifier">is_unbounded</phrase><phrase
|
||
|
role="special">()</phrase> <phrase role="special">&&</phrase>
|
||
|
<phrase role="special">(</phrase> <phrase role="identifier">traits_type</phrase><phrase
|
||
|
role="special">::</phrase><phrase role="identifier">maximum</phrase><phrase
|
||
|
role="special">:</phrase><phrase role="identifier">size</phrase><phrase
|
||
|
role="special">()</phrase> <phrase role="special">>=</phrase> <phrase
|
||
|
role="identifier">size</phrase><phrase role="special">)</phrase></code>.
|
||
|
</para>
|
||
|
</listitem>
|
||
|
</varlistentry>
|
||
|
<varlistentry>
|
||
|
<term>Effects:</term>
|
||
|
<listitem>
|
||
|
<para>
|
||
|
Allocates memory of at least <code><phrase role="identifier">size</phrase></code>
|
||
|
Bytes and stores a pointer to the stack and its actual size in <code><phrase
|
||
|
role="identifier">sctx</phrase></code>. Depending on the architecture
|
||
|
(the stack grows downwards/upwards) the stored address is the highest/lowest
|
||
|
address of the stack.
|
||
|
</para>
|
||
|
</listitem>
|
||
|
</varlistentry>
|
||
|
</variablelist>
|
||
|
<bridgehead renderas="sect4" id="context.stack.fixedsize.h1">
|
||
|
<phrase id="context.stack.fixedsize._code__phrase_role__keyword__void__phrase___phrase_role__identifier__deallocate__phrase__phrase_role__special_____phrase___phrase_role__identifier__stack_context__phrase___phrase_role__special___amp___phrase___phrase_role__identifier__sctx__phrase__phrase_role__special_____phrase___code_"/><link
|
||
|
linkend="context.stack.fixedsize._code__phrase_role__keyword__void__phrase___phrase_role__identifier__deallocate__phrase__phrase_role__special_____phrase___phrase_role__identifier__stack_context__phrase___phrase_role__special___amp___phrase___phrase_role__identifier__sctx__phrase__phrase_role__special_____phrase___code_"><code><phrase
|
||
|
role="keyword">void</phrase> <phrase role="identifier">deallocate</phrase><phrase
|
||
|
role="special">(</phrase> <phrase role="identifier">stack_context</phrase>
|
||
|
<phrase role="special">&</phrase> <phrase role="identifier">sctx</phrase><phrase
|
||
|
role="special">)</phrase></code></link>
|
||
|
</bridgehead>
|
||
|
<variablelist>
|
||
|
<title></title>
|
||
|
<varlistentry>
|
||
|
<term>Preconditions:</term>
|
||
|
<listitem>
|
||
|
<para>
|
||
|
<code><phrase role="identifier">sctx</phrase><phrase role="special">.</phrase><phrase
|
||
|
role="identifier">sp</phrase></code> is valid, <code><phrase role="identifier">traits_type</phrase><phrase
|
||
|
role="special">::</phrase><phrase role="identifier">minimum</phrase><phrase
|
||
|
role="special">:</phrase><phrase role="identifier">size</phrase><phrase
|
||
|
role="special">()</phrase> <phrase role="special"><=</phrase> <phrase
|
||
|
role="identifier">sctx</phrase><phrase role="special">.</phrase><phrase
|
||
|
role="identifier">size</phrase></code> and <code><phrase role="special">!</phrase>
|
||
|
<phrase role="identifier">traits_type</phrase><phrase role="special">::</phrase><phrase
|
||
|
role="identifier">is_unbounded</phrase><phrase role="special">()</phrase>
|
||
|
<phrase role="special">&&</phrase> <phrase role="special">(</phrase>
|
||
|
<phrase role="identifier">traits_type</phrase><phrase role="special">::</phrase><phrase
|
||
|
role="identifier">maximum</phrase><phrase role="special">:</phrase><phrase
|
||
|
role="identifier">size</phrase><phrase role="special">()</phrase>
|
||
|
<phrase role="special">>=</phrase> <phrase role="identifier">sctx</phrase><phrase
|
||
|
role="special">.</phrase><phrase role="identifier">size</phrase><phrase
|
||
|
role="special">)</phrase></code>.
|
||
|
</para>
|
||
|
</listitem>
|
||
|
</varlistentry>
|
||
|
<varlistentry>
|
||
|
<term>Effects:</term>
|
||
|
<listitem>
|
||
|
<para>
|
||
|
Deallocates the stack space.
|
||
|
</para>
|
||
|
</listitem>
|
||
|
</varlistentry>
|
||
|
</variablelist>
|
||
|
</section>
|
||
|
<section id="context.stack.segmented">
|
||
|
<title><anchor id="segmented"/><link linkend="context.stack.segmented">Class
|
||
|
<emphasis>segmented_stack</emphasis></link></title>
|
||
|
<para>
|
||
|
<emphasis role="bold">Boost.Context</emphasis> supports usage of a <link
|
||
|
linkend="segmented"><emphasis>segmented_stack</emphasis></link>, e. g. the
|
||
|
size of the stack grows on demand. The coroutine is created with a minimal
|
||
|
stack size and will be increased as required. Class <link linkend="segmented"><emphasis>segmented_stack</emphasis></link>
|
||
|
models the <emphasis>stack-allocator concept</emphasis>. In contrast to
|
||
|
<emphasis>protected_fixedsize_stack</emphasis> and <emphasis>fixedsize_stack</emphasis>
|
||
|
it creates a stack which grows on demand.
|
||
|
</para>
|
||
|
<note>
|
||
|
<para>
|
||
|
Segmented stacks are currently only supported by <emphasis role="bold">gcc</emphasis>
|
||
|
from version <emphasis role="bold">4.7</emphasis> <emphasis role="bold">clang</emphasis>
|
||
|
from version <emphasis role="bold">3.4</emphasis> onwards. In order to
|
||
|
use a <emphasis>segmented_stack</emphasis> <emphasis role="bold">Boost.Context</emphasis>
|
||
|
must be built with property <code><phrase role="identifier">segmented</phrase><phrase
|
||
|
role="special">-</phrase><phrase role="identifier">stacks</phrase></code>,
|
||
|
e.g. <emphasis role="bold">toolset=gcc segmented-stacks=on</emphasis> and
|
||
|
applying <code><phrase role="identifier">BOOST_USE_SEGMENTED_STACKS</phrase></code>
|
||
|
at b2/bjam command line.
|
||
|
</para>
|
||
|
</note>
|
||
|
<note>
|
||
|
<para>
|
||
|
Segmented stacks can only be used with <link linkend="cc"><emphasis>callcc()</emphasis></link>
|
||
|
(using <link linkend="implementation"><emphasis>ucontext_t</emphasis></link>)
|
||
|
</para>
|
||
|
</note>
|
||
|
<para>
|
||
|
.
|
||
|
</para>
|
||
|
<programlisting><phrase role="preprocessor">#include</phrase> <phrase role="special"><</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">context</phrase><phrase role="special">/</phrase><phrase role="identifier">segmented_stack</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">></phrase>
|
||
|
|
||
|
<phrase role="keyword">template</phrase><phrase role="special"><</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">traitsT</phrase> <phrase role="special">></phrase>
|
||
|
<phrase role="keyword">struct</phrase> <phrase role="identifier">basic_segmented_stack</phrase> <phrase role="special">{</phrase>
|
||
|
<phrase role="keyword">typedef</phrase> <phrase role="identifier">traitT</phrase> <phrase role="identifier">traits_type</phrase><phrase role="special">;</phrase>
|
||
|
|
||
|
<phrase role="identifier">basic_segmented_stack</phrase><phrase role="special">(</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">size</phrase> <phrase role="special">=</phrase> <phrase role="identifier">traits_type</phrase><phrase role="special">::</phrase><phrase role="identifier">default_size</phrase><phrase role="special">());</phrase>
|
||
|
|
||
|
<phrase role="identifier">stack_context</phrase> <phrase role="identifier">allocate</phrase><phrase role="special">();</phrase>
|
||
|
|
||
|
<phrase role="keyword">void</phrase> <phrase role="identifier">deallocate</phrase><phrase role="special">(</phrase> <phrase role="identifier">stack_context</phrase> <phrase role="special">&);</phrase>
|
||
|
<phrase role="special">}</phrase>
|
||
|
|
||
|
<phrase role="keyword">typedef</phrase> <phrase role="identifier">basic_segmented_stack</phrase><phrase role="special"><</phrase> <phrase role="identifier">stack_traits</phrase> <phrase role="special">></phrase> <phrase role="identifier">segmented_stack</phrase><phrase role="special">;</phrase>
|
||
|
</programlisting>
|
||
|
<bridgehead renderas="sect4" id="context.stack.segmented.h0">
|
||
|
<phrase id="context.stack.segmented._code__phrase_role__identifier__stack_context__phrase___phrase_role__identifier__allocate__phrase__phrase_role__special______phrase___code_"/><link
|
||
|
linkend="context.stack.segmented._code__phrase_role__identifier__stack_context__phrase___phrase_role__identifier__allocate__phrase__phrase_role__special______phrase___code_"><code><phrase
|
||
|
role="identifier">stack_context</phrase> <phrase role="identifier">allocate</phrase><phrase
|
||
|
role="special">()</phrase></code></link>
|
||
|
</bridgehead>
|
||
|
<variablelist>
|
||
|
<title></title>
|
||
|
<varlistentry>
|
||
|
<term>Preconditions:</term>
|
||
|
<listitem>
|
||
|
<para>
|
||
|
<code><phrase role="identifier">traits_type</phrase><phrase role="special">::</phrase><phrase
|
||
|
role="identifier">minimum</phrase><phrase role="special">:</phrase><phrase
|
||
|
role="identifier">size</phrase><phrase role="special">()</phrase>
|
||
|
<phrase role="special"><=</phrase> <phrase role="identifier">size</phrase></code>
|
||
|
and <code><phrase role="special">!</phrase> <phrase role="identifier">traits_type</phrase><phrase
|
||
|
role="special">::</phrase><phrase role="identifier">is_unbounded</phrase><phrase
|
||
|
role="special">()</phrase> <phrase role="special">&&</phrase>
|
||
|
<phrase role="special">(</phrase> <phrase role="identifier">traits_type</phrase><phrase
|
||
|
role="special">::</phrase><phrase role="identifier">maximum</phrase><phrase
|
||
|
role="special">:</phrase><phrase role="identifier">size</phrase><phrase
|
||
|
role="special">()</phrase> <phrase role="special">>=</phrase> <phrase
|
||
|
role="identifier">size</phrase><phrase role="special">)</phrase></code>.
|
||
|
</para>
|
||
|
</listitem>
|
||
|
</varlistentry>
|
||
|
<varlistentry>
|
||
|
<term>Effects:</term>
|
||
|
<listitem>
|
||
|
<para>
|
||
|
Allocates memory of at least <code><phrase role="identifier">size</phrase></code>
|
||
|
Bytes and stores a pointer to the stack and its actual size in <code><phrase
|
||
|
role="identifier">sctx</phrase></code>. Depending on the architecture
|
||
|
(the stack grows downwards/upwards) the stored address is the highest/lowest
|
||
|
address of the stack.
|
||
|
</para>
|
||
|
</listitem>
|
||
|
</varlistentry>
|
||
|
</variablelist>
|
||
|
<bridgehead renderas="sect4" id="context.stack.segmented.h1">
|
||
|
<phrase id="context.stack.segmented._code__phrase_role__keyword__void__phrase___phrase_role__identifier__deallocate__phrase__phrase_role__special_____phrase___phrase_role__identifier__stack_context__phrase___phrase_role__special___amp___phrase___phrase_role__identifier__sctx__phrase__phrase_role__special_____phrase___code_"/><link
|
||
|
linkend="context.stack.segmented._code__phrase_role__keyword__void__phrase___phrase_role__identifier__deallocate__phrase__phrase_role__special_____phrase___phrase_role__identifier__stack_context__phrase___phrase_role__special___amp___phrase___phrase_role__identifier__sctx__phrase__phrase_role__special_____phrase___code_"><code><phrase
|
||
|
role="keyword">void</phrase> <phrase role="identifier">deallocate</phrase><phrase
|
||
|
role="special">(</phrase> <phrase role="identifier">stack_context</phrase>
|
||
|
<phrase role="special">&</phrase> <phrase role="identifier">sctx</phrase><phrase
|
||
|
role="special">)</phrase></code></link>
|
||
|
</bridgehead>
|
||
|
<variablelist>
|
||
|
<title></title>
|
||
|
<varlistentry>
|
||
|
<term>Preconditions:</term>
|
||
|
<listitem>
|
||
|
<para>
|
||
|
<code><phrase role="identifier">sctx</phrase><phrase role="special">.</phrase><phrase
|
||
|
role="identifier">sp</phrase></code> is valid, <code><phrase role="identifier">traits_type</phrase><phrase
|
||
|
role="special">::</phrase><phrase role="identifier">minimum</phrase><phrase
|
||
|
role="special">:</phrase><phrase role="identifier">size</phrase><phrase
|
||
|
role="special">()</phrase> <phrase role="special"><=</phrase> <phrase
|
||
|
role="identifier">sctx</phrase><phrase role="special">.</phrase><phrase
|
||
|
role="identifier">size</phrase></code> and <code><phrase role="special">!</phrase>
|
||
|
<phrase role="identifier">traits_type</phrase><phrase role="special">::</phrase><phrase
|
||
|
role="identifier">is_unbounded</phrase><phrase role="special">()</phrase>
|
||
|
<phrase role="special">&&</phrase> <phrase role="special">(</phrase>
|
||
|
<phrase role="identifier">traits_type</phrase><phrase role="special">::</phrase><phrase
|
||
|
role="identifier">maximum</phrase><phrase role="special">:</phrase><phrase
|
||
|
role="identifier">size</phrase><phrase role="special">()</phrase>
|
||
|
<phrase role="special">>=</phrase> <phrase role="identifier">sctx</phrase><phrase
|
||
|
role="special">.</phrase><phrase role="identifier">size</phrase><phrase
|
||
|
role="special">)</phrase></code>.
|
||
|
</para>
|
||
|
</listitem>
|
||
|
</varlistentry>
|
||
|
<varlistentry>
|
||
|
<term>Effects:</term>
|
||
|
<listitem>
|
||
|
<para>
|
||
|
Deallocates the stack space.
|
||
|
</para>
|
||
|
</listitem>
|
||
|
</varlistentry>
|
||
|
</variablelist>
|
||
|
<note>
|
||
|
<para>
|
||
|
If the library is compiled for segmented stacks, <emphasis>segmented_stack</emphasis>
|
||
|
is the only available stack allocator.
|
||
|
</para>
|
||
|
</note>
|
||
|
</section>
|
||
|
<section id="context.stack.stack_traits">
|
||
|
<title><link linkend="context.stack.stack_traits">Class <emphasis>stack_traits</emphasis></link></title>
|
||
|
<para>
|
||
|
<emphasis>stack_traits</emphasis> models a <emphasis>stack-traits</emphasis>
|
||
|
providing a way to access certain properites defined by the enironment. Stack
|
||
|
allocators use <emphasis>stack-traits</emphasis> to allocate stacks.
|
||
|
</para>
|
||
|
<programlisting><phrase role="preprocessor">#include</phrase> <phrase role="special"><</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">context</phrase><phrase role="special">/</phrase><phrase role="identifier">stack_traits</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">></phrase>
|
||
|
|
||
|
<phrase role="keyword">struct</phrase> <phrase role="identifier">stack_traits</phrase> <phrase role="special">{</phrase>
|
||
|
<phrase role="keyword">static</phrase> <phrase role="keyword">bool</phrase> <phrase role="identifier">is_unbounded</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
|
||
|
|
||
|
<phrase role="keyword">static</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">page_size</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
|
||
|
|
||
|
<phrase role="keyword">static</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">default_size</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
|
||
|
|
||
|
<phrase role="keyword">static</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">minimum_size</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
|
||
|
|
||
|
<phrase role="keyword">static</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">maximum_size</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
|
||
|
<phrase role="special">}</phrase>
|
||
|
</programlisting>
|
||
|
<bridgehead renderas="sect4" id="context.stack.stack_traits.h0">
|
||
|
<phrase id="context.stack.stack_traits._code__phrase_role__keyword__static__phrase___phrase_role__keyword__bool__phrase___phrase_role__identifier__is_unbounded__phrase__phrase_role__special______phrase___code_"/><link
|
||
|
linkend="context.stack.stack_traits._code__phrase_role__keyword__static__phrase___phrase_role__keyword__bool__phrase___phrase_role__identifier__is_unbounded__phrase__phrase_role__special______phrase___code_"><code><phrase
|
||
|
role="keyword">static</phrase> <phrase role="keyword">bool</phrase> <phrase
|
||
|
role="identifier">is_unbounded</phrase><phrase role="special">()</phrase></code></link>
|
||
|
</bridgehead>
|
||
|
<variablelist>
|
||
|
<title></title>
|
||
|
<varlistentry>
|
||
|
<term>Returns:</term>
|
||
|
<listitem>
|
||
|
<para>
|
||
|
Returns <code><phrase role="keyword">true</phrase></code> if the environment
|
||
|
defines no limit for the size of a stack.
|
||
|
</para>
|
||
|
</listitem>
|
||
|
</varlistentry>
|
||
|
<varlistentry>
|
||
|
<term>Throws:</term>
|
||
|
<listitem>
|
||
|
<para>
|
||
|
Nothing.
|
||
|
</para>
|
||
|
</listitem>
|
||
|
</varlistentry>
|
||
|
</variablelist>
|
||
|
<bridgehead renderas="sect4" id="context.stack.stack_traits.h1">
|
||
|
<phrase id="context.stack.stack_traits._code__phrase_role__keyword__static__phrase___phrase_role__identifier__std__phrase__phrase_role__special______phrase__phrase_role__identifier__size_t__phrase___phrase_role__identifier__page_size__phrase__phrase_role__special______phrase___code_"/><link
|
||
|
linkend="context.stack.stack_traits._code__phrase_role__keyword__static__phrase___phrase_role__identifier__std__phrase__phrase_role__special______phrase__phrase_role__identifier__size_t__phrase___phrase_role__identifier__page_size__phrase__phrase_role__special______phrase___code_"><code><phrase
|
||
|
role="keyword">static</phrase> <phrase role="identifier">std</phrase><phrase
|
||
|
role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase
|
||
|
role="identifier">page_size</phrase><phrase role="special">()</phrase></code></link>
|
||
|
</bridgehead>
|
||
|
<variablelist>
|
||
|
<title></title>
|
||
|
<varlistentry>
|
||
|
<term>Returns:</term>
|
||
|
<listitem>
|
||
|
<para>
|
||
|
Returns the page size in bytes.
|
||
|
</para>
|
||
|
</listitem>
|
||
|
</varlistentry>
|
||
|
<varlistentry>
|
||
|
<term>Throws:</term>
|
||
|
<listitem>
|
||
|
<para>
|
||
|
Nothing.
|
||
|
</para>
|
||
|
</listitem>
|
||
|
</varlistentry>
|
||
|
</variablelist>
|
||
|
<bridgehead renderas="sect4" id="context.stack.stack_traits.h2">
|
||
|
<phrase id="context.stack.stack_traits._code__phrase_role__keyword__static__phrase___phrase_role__identifier__std__phrase__phrase_role__special______phrase__phrase_role__identifier__size_t__phrase___phrase_role__identifier__default_size__phrase__phrase_role__special______phrase___code_"/><link
|
||
|
linkend="context.stack.stack_traits._code__phrase_role__keyword__static__phrase___phrase_role__identifier__std__phrase__phrase_role__special______phrase__phrase_role__identifier__size_t__phrase___phrase_role__identifier__default_size__phrase__phrase_role__special______phrase___code_"><code><phrase
|
||
|
role="keyword">static</phrase> <phrase role="identifier">std</phrase><phrase
|
||
|
role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase
|
||
|
role="identifier">default_size</phrase><phrase role="special">()</phrase></code></link>
|
||
|
</bridgehead>
|
||
|
<variablelist>
|
||
|
<title></title>
|
||
|
<varlistentry>
|
||
|
<term>Returns:</term>
|
||
|
<listitem>
|
||
|
<para>
|
||
|
Returns a default stack size, which may be platform specific. If the
|
||
|
stack is unbounded then the present implementation returns the maximum
|
||
|
of <code><phrase role="number">64</phrase> <phrase role="identifier">kB</phrase></code>
|
||
|
and <code><phrase role="identifier">minimum_size</phrase><phrase role="special">()</phrase></code>.
|
||
|
</para>
|
||
|
</listitem>
|
||
|
</varlistentry>
|
||
|
<varlistentry>
|
||
|
<term>Throws:</term>
|
||
|
<listitem>
|
||
|
<para>
|
||
|
Nothing.
|
||
|
</para>
|
||
|
</listitem>
|
||
|
</varlistentry>
|
||
|
</variablelist>
|
||
|
<bridgehead renderas="sect4" id="context.stack.stack_traits.h3">
|
||
|
<phrase id="context.stack.stack_traits._code__phrase_role__keyword__static__phrase___phrase_role__identifier__std__phrase__phrase_role__special______phrase__phrase_role__identifier__size_t__phrase___phrase_role__identifier__minimum_size__phrase__phrase_role__special______phrase___code_"/><link
|
||
|
linkend="context.stack.stack_traits._code__phrase_role__keyword__static__phrase___phrase_role__identifier__std__phrase__phrase_role__special______phrase__phrase_role__identifier__size_t__phrase___phrase_role__identifier__minimum_size__phrase__phrase_role__special______phrase___code_"><code><phrase
|
||
|
role="keyword">static</phrase> <phrase role="identifier">std</phrase><phrase
|
||
|
role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase
|
||
|
role="identifier">minimum_size</phrase><phrase role="special">()</phrase></code></link>
|
||
|
</bridgehead>
|
||
|
<variablelist>
|
||
|
<title></title>
|
||
|
<varlistentry>
|
||
|
<term>Returns:</term>
|
||
|
<listitem>
|
||
|
<para>
|
||
|
Returns the minimum size in bytes of stack defined by the environment
|
||
|
(Win32 4kB/Win64 8kB, defined by rlimit on POSIX).
|
||
|
</para>
|
||
|
</listitem>
|
||
|
</varlistentry>
|
||
|
<varlistentry>
|
||
|
<term>Throws:</term>
|
||
|
<listitem>
|
||
|
<para>
|
||
|
Nothing.
|
||
|
</para>
|
||
|
</listitem>
|
||
|
</varlistentry>
|
||
|
</variablelist>
|
||
|
<bridgehead renderas="sect4" id="context.stack.stack_traits.h4">
|
||
|
<phrase id="context.stack.stack_traits._code__phrase_role__keyword__static__phrase___phrase_role__identifier__std__phrase__phrase_role__special______phrase__phrase_role__identifier__size_t__phrase___phrase_role__identifier__maximum_size__phrase__phrase_role__special______phrase___code_"/><link
|
||
|
linkend="context.stack.stack_traits._code__phrase_role__keyword__static__phrase___phrase_role__identifier__std__phrase__phrase_role__special______phrase__phrase_role__identifier__size_t__phrase___phrase_role__identifier__maximum_size__phrase__phrase_role__special______phrase___code_"><code><phrase
|
||
|
role="keyword">static</phrase> <phrase role="identifier">std</phrase><phrase
|
||
|
role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase
|
||
|
role="identifier">maximum_size</phrase><phrase role="special">()</phrase></code></link>
|
||
|
</bridgehead>
|
||
|
<variablelist>
|
||
|
<title></title>
|
||
|
<varlistentry>
|
||
|
<term>Preconditions:</term>
|
||
|
<listitem>
|
||
|
<para>
|
||
|
<code><phrase role="identifier">is_unbounded</phrase><phrase role="special">()</phrase></code>
|
||
|
returns <code><phrase role="keyword">false</phrase></code>.
|
||
|
</para>
|
||
|
</listitem>
|
||
|
</varlistentry>
|
||
|
<varlistentry>
|
||
|
<term>Returns:</term>
|
||
|
<listitem>
|
||
|
<para>
|
||
|
Returns the maximum size in bytes of stack defined by the environment.
|
||
|
</para>
|
||
|
</listitem>
|
||
|
</varlistentry>
|
||
|
<varlistentry>
|
||
|
<term>Throws:</term>
|
||
|
<listitem>
|
||
|
<para>
|
||
|
Nothing.
|
||
|
</para>
|
||
|
</listitem>
|
||
|
</varlistentry>
|
||
|
</variablelist>
|
||
|
</section>
|
||
|
<section id="context.stack.stack_context">
|
||
|
<title><link linkend="context.stack.stack_context">Class <emphasis>stack_context</emphasis></link></title>
|
||
|
<para>
|
||
|
<emphasis role="bold">Boost.Context</emphasis> provides the class <emphasis>stack_context</emphasis>
|
||
|
which will contain the stack pointer and the size of the stack. In case of
|
||
|
a <link linkend="segmented"><emphasis>segmented_stack</emphasis></link>,
|
||
|
<emphasis>stack_context</emphasis> contains some extra control structures.
|
||
|
</para>
|
||
|
<programlisting><phrase role="keyword">struct</phrase> <phrase role="identifier">stack_context</phrase> <phrase role="special">{</phrase>
|
||
|
<phrase role="keyword">void</phrase> <phrase role="special">*</phrase> <phrase role="identifier">sp</phrase><phrase role="special">;</phrase>
|
||
|
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">size</phrase><phrase role="special">;</phrase>
|
||
|
|
||
|
<phrase role="comment">// might contain additional control structures</phrase>
|
||
|
<phrase role="comment">// for segmented stacks</phrase>
|
||
|
<phrase role="special">}</phrase>
|
||
|
</programlisting>
|
||
|
<bridgehead renderas="sect4" id="context.stack.stack_context.h0">
|
||
|
<phrase id="context.stack.stack_context._code__phrase_role__keyword__void__phrase___phrase_role__special_____phrase___phrase_role__identifier__sp__phrase___code_"/><link
|
||
|
linkend="context.stack.stack_context._code__phrase_role__keyword__void__phrase___phrase_role__special_____phrase___phrase_role__identifier__sp__phrase___code_"><code><phrase
|
||
|
role="keyword">void</phrase> <phrase role="special">*</phrase> <phrase role="identifier">sp</phrase></code></link>
|
||
|
</bridgehead>
|
||
|
<variablelist>
|
||
|
<title></title>
|
||
|
<varlistentry>
|
||
|
<term>Value:</term>
|
||
|
<listitem>
|
||
|
<para>
|
||
|
Pointer to the beginning of the stack.
|
||
|
</para>
|
||
|
</listitem>
|
||
|
</varlistentry>
|
||
|
</variablelist>
|
||
|
<bridgehead renderas="sect4" id="context.stack.stack_context.h1">
|
||
|
<phrase id="context.stack.stack_context._code__phrase_role__identifier__std__phrase__phrase_role__special______phrase__phrase_role__identifier__size_t__phrase___phrase_role__identifier__size__phrase___code_"/><link
|
||
|
linkend="context.stack.stack_context._code__phrase_role__identifier__std__phrase__phrase_role__special______phrase__phrase_role__identifier__size_t__phrase___phrase_role__identifier__size__phrase___code_"><code><phrase
|
||
|
role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase>
|
||
|
<phrase role="identifier">size</phrase></code></link>
|
||
|
</bridgehead>
|
||
|
<variablelist>
|
||
|
<title></title>
|
||
|
<varlistentry>
|
||
|
<term>Value:</term>
|
||
|
<listitem>
|
||
|
<para>
|
||
|
Actual size of the stack.
|
||
|
</para>
|
||
|
</listitem>
|
||
|
</varlistentry>
|
||
|
</variablelist>
|
||
|
</section>
|
||
|
<section id="context.stack.valgrind">
|
||
|
<title><link linkend="context.stack.valgrind">Support for valgrind</link></title>
|
||
|
<para>
|
||
|
Running programs that switch stacks under valgrind causes problems. Property
|
||
|
(b2 command-line) <code><phrase role="identifier">valgrind</phrase><phrase
|
||
|
role="special">=</phrase><phrase role="identifier">on</phrase></code> let
|
||
|
valgrind treat the memory regions as stack space which suppresses the errors.
|
||
|
Users must define <code><phrase role="identifier">BOOST_USE_VALGRIND</phrase></code>
|
||
|
before including any Boost.Context headers when linking against Boost binaries
|
||
|
compiled with <code><phrase role="identifier">valgrind</phrase><phrase role="special">=</phrase><phrase
|
||
|
role="identifier">on</phrase></code>.
|
||
|
</para>
|
||
|
</section>
|
||
|
<section id="context.stack.sanitizers">
|
||
|
<title><link linkend="context.stack.sanitizers">Support for sanitizers</link></title>
|
||
|
<para>
|
||
|
Sanitizers (GCC/Clang) are confused by the stack switches. The library is
|
||
|
required to be compiled with property (b2 command-line) <code><phrase role="identifier">context</phrase><phrase
|
||
|
role="special">-</phrase><phrase role="identifier">impl</phrase><phrase role="special">=</phrase><phrase
|
||
|
role="identifier">ucontext</phrase></code> and compilers santizer options.
|
||
|
Users must define <code><phrase role="identifier">BOOST_USE_ASAN</phrase></code>
|
||
|
before including any Boost.Context headers when linking against Boost binaries.
|
||
|
</para>
|
||
|
</section>
|
||
|
</section>
|
||
|
<section id="context.struct__preallocated_">
|
||
|
<title><link linkend="context.struct__preallocated_">Struct <code><phrase role="identifier">preallocated</phrase></code></link></title>
|
||
|
<programlisting><phrase role="keyword">struct</phrase> <phrase role="identifier">preallocated</phrase> <phrase role="special">{</phrase>
|
||
|
<phrase role="keyword">void</phrase> <phrase role="special">*</phrase> <phrase role="identifier">sp</phrase><phrase role="special">;</phrase>
|
||
|
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">size</phrase><phrase role="special">;</phrase>
|
||
|
<phrase role="identifier">stack_context</phrase> <phrase role="identifier">sctx</phrase><phrase role="special">;</phrase>
|
||
|
|
||
|
<phrase role="identifier">preallocated</phrase><phrase role="special">(</phrase> <phrase role="keyword">void</phrase> <phrase role="special">*</phrase> <phrase role="identifier">sp</phrase><phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">:</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">size</phrase><phrase role="special">,</phrase> <phrase role="identifier">stack_allocator</phrase> <phrase role="identifier">sctx</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
|
||
|
<phrase role="special">};</phrase>
|
||
|
</programlisting>
|
||
|
<bridgehead renderas="sect3" id="context.struct__preallocated_.h0">
|
||
|
<phrase id="context.struct__preallocated_.constructor"/><link linkend="context.struct__preallocated_.constructor">Constructor</link>
|
||
|
</bridgehead>
|
||
|
<programlisting><phrase role="identifier">preallocated</phrase><phrase role="special">(</phrase> <phrase role="keyword">void</phrase> <phrase role="special">*</phrase> <phrase role="identifier">sp</phrase><phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">:</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">size</phrase><phrase role="special">,</phrase> <phrase role="identifier">stack_allocator</phrase> <phrase role="identifier">sctx</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
|
||
|
</programlisting>
|
||
|
<variablelist>
|
||
|
<title></title>
|
||
|
<varlistentry>
|
||
|
<term>Effects:</term>
|
||
|
<listitem>
|
||
|
<para>
|
||
|
Creates an object of preallocated.
|
||
|
</para>
|
||
|
</listitem>
|
||
|
</varlistentry>
|
||
|
</variablelist>
|
||
|
</section>
|
||
|
<section id="context.performance">
|
||
|
<title><anchor id="performance"/><link linkend="context.performance">Performance</link></title>
|
||
|
<para>
|
||
|
Performance measurements were taken using <code><phrase role="identifier">std</phrase><phrase
|
||
|
role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase
|
||
|
role="special">::</phrase><phrase role="identifier">highresolution_clock</phrase></code>,
|
||
|
with overhead corrections. The code was compiled with gcc-6.3.1, using build
|
||
|
options: variant = release, optimization = speed. Tests were executed on dual
|
||
|
Intel XEON E5 2620v4 2.2GHz, 16C/32T, 64GB RAM, running Linux (x86_64).
|
||
|
</para>
|
||
|
<table frame="all" id="context.performance.performance_of_context_switch">
|
||
|
<title>Performance of context switch</title>
|
||
|
<tgroup cols="3">
|
||
|
<thead>
|
||
|
<row>
|
||
|
<entry>
|
||
|
<para>
|
||
|
callcc()/continuation (fcontext_t)
|
||
|
</para>
|
||
|
</entry>
|
||
|
<entry>
|
||
|
<para>
|
||
|
callcc()/continuation (ucontext_t)
|
||
|
</para>
|
||
|
</entry>
|
||
|
<entry>
|
||
|
<para>
|
||
|
callcc()/continuation (Windows-Fiber)
|
||
|
</para>
|
||
|
</entry>
|
||
|
</row>
|
||
|
</thead>
|
||
|
<tbody>
|
||
|
<row>
|
||
|
<entry>
|
||
|
<para>
|
||
|
9 ns / 19 CPU cycles
|
||
|
</para>
|
||
|
</entry>
|
||
|
<entry>
|
||
|
<para>
|
||
|
547 ns / 1130 CPU cycles
|
||
|
</para>
|
||
|
</entry>
|
||
|
<entry>
|
||
|
<para>
|
||
|
49 ns / 98 CPU cycles
|
||
|
</para>
|
||
|
</entry>
|
||
|
</row>
|
||
|
</tbody>
|
||
|
</tgroup>
|
||
|
</table>
|
||
|
</section>
|
||
|
<section id="context.architectures">
|
||
|
<title><link linkend="context.architectures">Architectures</link></title>
|
||
|
<para>
|
||
|
<emphasis role="bold">Boost.Context</emphasis>, using <link linkend="implementation"><emphasis>fcontext_t</emphasis></link>,
|
||
|
supports following architectures:
|
||
|
</para>
|
||
|
<table frame="all" id="context.architectures.supported_architectures___abi_binary_format__">
|
||
|
<title>Supported architectures (<ABI|binary format>)</title>
|
||
|
<tgroup cols="5">
|
||
|
<thead>
|
||
|
<row>
|
||
|
<entry>
|
||
|
<para>
|
||
|
Architecture
|
||
|
</para>
|
||
|
</entry>
|
||
|
<entry>
|
||
|
<para>
|
||
|
LINUX (UNIX)
|
||
|
</para>
|
||
|
</entry>
|
||
|
<entry>
|
||
|
<para>
|
||
|
Windows
|
||
|
</para>
|
||
|
</entry>
|
||
|
<entry>
|
||
|
<para>
|
||
|
MacOS X
|
||
|
</para>
|
||
|
</entry>
|
||
|
<entry>
|
||
|
<para>
|
||
|
iOS
|
||
|
</para>
|
||
|
</entry>
|
||
|
</row>
|
||
|
</thead>
|
||
|
<tbody>
|
||
|
<row>
|
||
|
<entry>
|
||
|
<para>
|
||
|
arm (aarch32)
|
||
|
</para>
|
||
|
</entry>
|
||
|
<entry>
|
||
|
<para>
|
||
|
AAPCS|ELF
|
||
|
</para>
|
||
|
</entry>
|
||
|
<entry>
|
||
|
<para>
|
||
|
AAPCS|PE
|
||
|
</para>
|
||
|
</entry>
|
||
|
<entry>
|
||
|
<para>
|
||
|
-
|
||
|
</para>
|
||
|
</entry>
|
||
|
<entry>
|
||
|
<para>
|
||
|
AAPCS|MACH-O
|
||
|
</para>
|
||
|
</entry>
|
||
|
</row>
|
||
|
<row>
|
||
|
<entry>
|
||
|
<para>
|
||
|
arm (aarch64)
|
||
|
</para>
|
||
|
</entry>
|
||
|
<entry>
|
||
|
<para>
|
||
|
AAPCS|ELF
|
||
|
</para>
|
||
|
</entry>
|
||
|
<entry>
|
||
|
<para>
|
||
|
-
|
||
|
</para>
|
||
|
</entry>
|
||
|
<entry>
|
||
|
<para>
|
||
|
-
|
||
|
</para>
|
||
|
</entry>
|
||
|
<entry>
|
||
|
<para>
|
||
|
AAPCS|MACH-O
|
||
|
</para>
|
||
|
</entry>
|
||
|
</row>
|
||
|
<row>
|
||
|
<entry>
|
||
|
<para>
|
||
|
i386
|
||
|
</para>
|
||
|
</entry>
|
||
|
<entry>
|
||
|
<para>
|
||
|
SYSV|ELF
|
||
|
</para>
|
||
|
</entry>
|
||
|
<entry>
|
||
|
<para>
|
||
|
MS|PE
|
||
|
</para>
|
||
|
</entry>
|
||
|
<entry>
|
||
|
<para>
|
||
|
SYSV|MACH-O
|
||
|
</para>
|
||
|
</entry>
|
||
|
<entry>
|
||
|
<para>
|
||
|
-
|
||
|
</para>
|
||
|
</entry>
|
||
|
</row>
|
||
|
<row>
|
||
|
<entry>
|
||
|
<para>
|
||
|
loongarch64
|
||
|
</para>
|
||
|
</entry>
|
||
|
<entry>
|
||
|
<para>
|
||
|
SYSV|ELF
|
||
|
</para>
|
||
|
</entry>
|
||
|
<entry>
|
||
|
<para>
|
||
|
-
|
||
|
</para>
|
||
|
</entry>
|
||
|
<entry>
|
||
|
<para>
|
||
|
-
|
||
|
</para>
|
||
|
</entry>
|
||
|
<entry>
|
||
|
<para>
|
||
|
-
|
||
|
</para>
|
||
|
</entry>
|
||
|
</row>
|
||
|
<row>
|
||
|
<entry>
|
||
|
<para>
|
||
|
mips
|
||
|
</para>
|
||
|
</entry>
|
||
|
<entry>
|
||
|
<para>
|
||
|
O32,N64|ELF
|
||
|
</para>
|
||
|
</entry>
|
||
|
<entry>
|
||
|
<para>
|
||
|
-
|
||
|
</para>
|
||
|
</entry>
|
||
|
<entry>
|
||
|
<para>
|
||
|
-
|
||
|
</para>
|
||
|
</entry>
|
||
|
<entry>
|
||
|
<para>
|
||
|
-
|
||
|
</para>
|
||
|
</entry>
|
||
|
</row>
|
||
|
<row>
|
||
|
<entry>
|
||
|
<para>
|
||
|
ppc32
|
||
|
</para>
|
||
|
</entry>
|
||
|
<entry>
|
||
|
<para>
|
||
|
SYSV|ELF,XCOFF
|
||
|
</para>
|
||
|
</entry>
|
||
|
<entry>
|
||
|
<para>
|
||
|
-
|
||
|
</para>
|
||
|
</entry>
|
||
|
<entry>
|
||
|
<para>
|
||
|
SYSV|MACH-O
|
||
|
</para>
|
||
|
</entry>
|
||
|
<entry>
|
||
|
<para>
|
||
|
-
|
||
|
</para>
|
||
|
</entry>
|
||
|
</row>
|
||
|
<row>
|
||
|
<entry>
|
||
|
<para>
|
||
|
ppc64
|
||
|
</para>
|
||
|
</entry>
|
||
|
<entry>
|
||
|
<para>
|
||
|
SYSV|ELF,XCOFF
|
||
|
</para>
|
||
|
</entry>
|
||
|
<entry>
|
||
|
<para>
|
||
|
-
|
||
|
</para>
|
||
|
</entry>
|
||
|
<entry>
|
||
|
<para>
|
||
|
SYSV|MACH-O
|
||
|
</para>
|
||
|
</entry>
|
||
|
<entry>
|
||
|
<para>
|
||
|
-
|
||
|
</para>
|
||
|
</entry>
|
||
|
</row>
|
||
|
<row>
|
||
|
<entry>
|
||
|
<para>
|
||
|
riscv64
|
||
|
</para>
|
||
|
</entry>
|
||
|
<entry>
|
||
|
<para>
|
||
|
SYSV|ELF
|
||
|
</para>
|
||
|
</entry>
|
||
|
<entry>
|
||
|
<para>
|
||
|
-
|
||
|
</para>
|
||
|
</entry>
|
||
|
<entry>
|
||
|
<para>
|
||
|
SYSV
|
||
|
</para>
|
||
|
</entry>
|
||
|
<entry>
|
||
|
<para>
|
||
|
-
|
||
|
</para>
|
||
|
</entry>
|
||
|
</row>
|
||
|
<row>
|
||
|
<entry>
|
||
|
<para>
|
||
|
s390x
|
||
|
</para>
|
||
|
</entry>
|
||
|
<entry>
|
||
|
<para>
|
||
|
SYSV|ELF
|
||
|
</para>
|
||
|
</entry>
|
||
|
<entry>
|
||
|
<para>
|
||
|
-
|
||
|
</para>
|
||
|
</entry>
|
||
|
<entry>
|
||
|
<para>
|
||
|
-
|
||
|
</para>
|
||
|
</entry>
|
||
|
<entry>
|
||
|
<para>
|
||
|
-
|
||
|
</para>
|
||
|
</entry>
|
||
|
</row>
|
||
|
<row>
|
||
|
<entry>
|
||
|
<para>
|
||
|
sparc
|
||
|
</para>
|
||
|
</entry>
|
||
|
<entry>
|
||
|
<para>
|
||
|
-
|
||
|
</para>
|
||
|
</entry>
|
||
|
<entry>
|
||
|
<para>
|
||
|
-
|
||
|
</para>
|
||
|
</entry>
|
||
|
<entry>
|
||
|
<para>
|
||
|
-
|
||
|
</para>
|
||
|
</entry>
|
||
|
<entry>
|
||
|
<para>
|
||
|
-
|
||
|
</para>
|
||
|
</entry>
|
||
|
</row>
|
||
|
<row>
|
||
|
<entry>
|
||
|
<para>
|
||
|
x86_64
|
||
|
</para>
|
||
|
</entry>
|
||
|
<entry>
|
||
|
<para>
|
||
|
SYSV,X32|ELF
|
||
|
</para>
|
||
|
</entry>
|
||
|
<entry>
|
||
|
<para>
|
||
|
MS|PE
|
||
|
</para>
|
||
|
</entry>
|
||
|
<entry>
|
||
|
<para>
|
||
|
SYSV|MACH-O
|
||
|
</para>
|
||
|
</entry>
|
||
|
<entry>
|
||
|
<para>
|
||
|
-
|
||
|
</para>
|
||
|
</entry>
|
||
|
</row>
|
||
|
</tbody>
|
||
|
</tgroup>
|
||
|
</table>
|
||
|
<note>
|
||
|
<para>
|
||
|
If the architecture is not supported but the platform provides <link linkend="implementation"><emphasis>ucontext_t</emphasis></link>,
|
||
|
<emphasis role="bold">Boost.Context</emphasis> should be compiled with <code><phrase
|
||
|
role="identifier">BOOST_USE_UCONTEXT</phrase></code> and b2 property <code><phrase
|
||
|
role="identifier">context</phrase><phrase role="special">-</phrase><phrase
|
||
|
role="identifier">impl</phrase><phrase role="special">=</phrase><phrase role="identifier">ucontext</phrase></code>.
|
||
|
</para>
|
||
|
</note>
|
||
|
<section id="context.architectures.crosscompiling">
|
||
|
<title><link linkend="context.architectures.crosscompiling">Cross compiling</link></title>
|
||
|
<para>
|
||
|
Cross compiling the library requires to specify the build properties <architecture>,
|
||
|
<address-model>, <binary-format> and <abi> at b2 command
|
||
|
line.
|
||
|
</para>
|
||
|
</section>
|
||
|
</section>
|
||
|
<section id="context.rationale">
|
||
|
<title><link linkend="context.rationale">Rationale</link></title>
|
||
|
<bridgehead renderas="sect3" id="context.rationale.h0">
|
||
|
<phrase id="context.rationale.no_inline_assembler"/><link linkend="context.rationale.no_inline_assembler">No
|
||
|
inline-assembler</link>
|
||
|
</bridgehead>
|
||
|
<para>
|
||
|
Some newer compiler (for instance MSVC 10 for x86_64 and itanium) do not support
|
||
|
inline assembler. <footnote id="context.rationale.f0">
|
||
|
<para>
|
||
|
<ulink url="http://msdn.microsoft.com/en-us/library/4ks26t93.aspx">MSDN article
|
||
|
'Inline Assembler'</ulink>
|
||
|
</para>
|
||
|
</footnote>. Inlined assembler generates code bloating which is not welcome
|
||
|
on embedded systems.
|
||
|
</para>
|
||
|
<bridgehead renderas="sect3" id="context.rationale.h1">
|
||
|
<phrase id="context.rationale.fcontext_t"/><link linkend="context.rationale.fcontext_t">fcontext_t</link>
|
||
|
</bridgehead>
|
||
|
<para>
|
||
|
<emphasis role="bold">Boost.Context</emphasis> provides the low level API fcontext_t
|
||
|
which is implemented in assembler to provide context swapping operations. fcontext_t
|
||
|
is the part to port to new platforms.
|
||
|
</para>
|
||
|
<note>
|
||
|
<para>
|
||
|
Context switches do not preserve the signal mask on UNIX systems.
|
||
|
</para>
|
||
|
</note>
|
||
|
<para>
|
||
|
<emphasis>fcontext_t</emphasis> is an opaque pointer.
|
||
|
</para>
|
||
|
<section id="context.rationale.other_apis_">
|
||
|
<title><link linkend="context.rationale.other_apis_">Other APIs </link></title>
|
||
|
<bridgehead renderas="sect4" id="context.rationale.other_apis_.h0">
|
||
|
<phrase id="context.rationale.other_apis_.setjmp___longjmp__"/><link linkend="context.rationale.other_apis_.setjmp___longjmp__">setjmp()/longjmp()</link>
|
||
|
</bridgehead>
|
||
|
<para>
|
||
|
C99 defines <code><phrase role="identifier">setjmp</phrase><phrase role="special">()</phrase></code>/<code><phrase
|
||
|
role="identifier">longjmp</phrase><phrase role="special">()</phrase></code>
|
||
|
to provide non-local jumps but it does not require that <emphasis>longjmp()</emphasis>
|
||
|
preserves the current stack frame. Therefore, jumping into a function which
|
||
|
was exited via a call to <emphasis>longjmp()</emphasis> is undefined <footnote
|
||
|
id="context.rationale.other_apis_.f0">
|
||
|
<para>
|
||
|
ISO/IEC 9899:1999, 2005, 7.13.2.1:2
|
||
|
</para>
|
||
|
</footnote>.
|
||
|
</para>
|
||
|
<anchor id="ucontext"/>
|
||
|
<bridgehead renderas="sect4" id="context.rationale.other_apis_.h1">
|
||
|
<phrase id="context.rationale.other_apis_.ucontext_t"/><link linkend="context.rationale.other_apis_.ucontext_t">ucontext_t</link>
|
||
|
</bridgehead>
|
||
|
<para>
|
||
|
Since POSIX.1-2004 <code><phrase role="identifier">ucontext_t</phrase></code>
|
||
|
is deprecated and was removed in POSIX.1-2008! The function signature of
|
||
|
<code><phrase role="identifier">makecontext</phrase><phrase role="special">()</phrase></code>
|
||
|
is:
|
||
|
</para>
|
||
|
<programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">makecontext</phrase><phrase role="special">(</phrase><phrase role="identifier">ucontext_t</phrase> <phrase role="special">*</phrase><phrase role="identifier">ucp</phrase><phrase role="special">,</phrase> <phrase role="keyword">void</phrase> <phrase role="special">(*</phrase><phrase role="identifier">func</phrase><phrase role="special">)(),</phrase> <phrase role="keyword">int</phrase> <phrase role="identifier">argc</phrase><phrase role="special">,</phrase> <phrase role="special">...);</phrase>
|
||
|
</programlisting>
|
||
|
<para>
|
||
|
The third argument of <code><phrase role="identifier">makecontext</phrase><phrase
|
||
|
role="special">()</phrase></code> specifies the number of integer arguments
|
||
|
that follow which will require function pointer cast if <code><phrase role="identifier">func</phrase></code>
|
||
|
will accept those arguments which is undefined in C99 <footnote id="context.rationale.other_apis_.f1">
|
||
|
<para>
|
||
|
ISO/IEC 9899:1999, 2005, J.2
|
||
|
</para>
|
||
|
</footnote>.
|
||
|
</para>
|
||
|
<para>
|
||
|
The arguments in the var-arg list are required to be integers, passing pointers
|
||
|
in var-arg list is not guaranteed to work, especially it will fail for architectures
|
||
|
where pointers are larger than integers.
|
||
|
</para>
|
||
|
<para>
|
||
|
<code><phrase role="identifier">ucontext_t</phrase></code> preserves signal
|
||
|
mask between context switches which involves system calls consuming a lot
|
||
|
of CPU cycles (ucontext_t is slower; a context switch takes <link linkend="performance"><emphasis>two
|
||
|
magnitutes of order more CPU cycles</emphasis></link> more than <emphasis>fcontext_t</emphasis>).
|
||
|
</para>
|
||
|
<bridgehead renderas="sect4" id="context.rationale.other_apis_.h2">
|
||
|
<phrase id="context.rationale.other_apis_.windows_fibers"/><link linkend="context.rationale.other_apis_.windows_fibers">Windows
|
||
|
fibers</link>
|
||
|
</bridgehead>
|
||
|
<para>
|
||
|
A drawback of Windows Fiber API is that <code><phrase role="identifier">CreateFiber</phrase><phrase
|
||
|
role="special">()</phrase></code> does not accept a pointer to user allocated
|
||
|
stack space preventing the reuse of stacks for other context instances. Because
|
||
|
the Windows Fiber API requires to call <code><phrase role="identifier">ConvertThreadToFiber</phrase><phrase
|
||
|
role="special">()</phrase></code> if <code><phrase role="identifier">SwitchFiber</phrase><phrase
|
||
|
role="special">()</phrase></code> is called for a thread which has not been
|
||
|
converted to a fiber. For the same reason <code><phrase role="identifier">ConvertFiberToThread</phrase><phrase
|
||
|
role="special">()</phrase></code> must be called after return from <code><phrase
|
||
|
role="identifier">SwitchFiber</phrase><phrase role="special">()</phrase></code>
|
||
|
if the thread was forced to be converted to a fiber before (which is inefficient).
|
||
|
</para>
|
||
|
<programlisting><phrase role="keyword">if</phrase> <phrase role="special">(</phrase> <phrase role="special">!</phrase> <phrase role="identifier">is_a_fiber</phrase><phrase role="special">()</phrase> <phrase role="special">)</phrase>
|
||
|
<phrase role="special">{</phrase>
|
||
|
<phrase role="identifier">ConvertThreadToFiber</phrase><phrase role="special">(</phrase> <phrase role="number">0</phrase><phrase role="special">);</phrase>
|
||
|
<phrase role="identifier">SwitchToFiber</phrase><phrase role="special">(</phrase> <phrase role="identifier">ctx</phrase><phrase role="special">);</phrase>
|
||
|
<phrase role="identifier">ConvertFiberToThread</phrase><phrase role="special">();</phrase>
|
||
|
<phrase role="special">}</phrase>
|
||
|
</programlisting>
|
||
|
<para>
|
||
|
If the condition <code><phrase role="identifier">_WIN32_WINNT</phrase> <phrase
|
||
|
role="special">>=</phrase> <phrase role="identifier">_WIN32_WINNT_VISTA</phrase></code>
|
||
|
is met function <code><phrase role="identifier">IsThreadAFiber</phrase><phrase
|
||
|
role="special">()</phrase></code> is provided in order to detect if the current
|
||
|
thread was already converted. Unfortunately Windows XP + SP 2/3 defines
|
||
|
<code><phrase role="identifier">_WIN32_WINNT</phrase> <phrase role="special">>=</phrase>
|
||
|
<phrase role="identifier">_WIN32_WINNT_VISTA</phrase></code> without providing
|
||
|
<code><phrase role="identifier">IsThreadAFiber</phrase><phrase role="special">()</phrase></code>.
|
||
|
</para>
|
||
|
</section>
|
||
|
<section id="context.rationale.x86_and_floating_point_env">
|
||
|
<title><link linkend="context.rationale.x86_and_floating_point_env">x86 and
|
||
|
floating-point env</link></title>
|
||
|
<bridgehead renderas="sect4" id="context.rationale.x86_and_floating_point_env.h0">
|
||
|
<phrase id="context.rationale.x86_and_floating_point_env.i386"/><link linkend="context.rationale.x86_and_floating_point_env.i386">i386</link>
|
||
|
</bridgehead>
|
||
|
<para>
|
||
|
"The FpCsr and the MxCsr register must be saved and restored before
|
||
|
any call or return by any procedure that needs to modify them ..."
|
||
|
<footnote id="context.rationale.x86_and_floating_point_env.f0">
|
||
|
<para>
|
||
|
'Calling Conventions', Agner Fog
|
||
|
</para>
|
||
|
</footnote>.
|
||
|
</para>
|
||
|
<bridgehead renderas="sect4" id="context.rationale.x86_and_floating_point_env.h1">
|
||
|
<phrase id="context.rationale.x86_and_floating_point_env.x86_64"/><link linkend="context.rationale.x86_and_floating_point_env.x86_64">x86_64</link>
|
||
|
</bridgehead>
|
||
|
<bridgehead renderas="sect4" id="context.rationale.x86_and_floating_point_env.h2">
|
||
|
<phrase id="context.rationale.x86_and_floating_point_env.windows"/><link
|
||
|
linkend="context.rationale.x86_and_floating_point_env.windows">Windows</link>
|
||
|
</bridgehead>
|
||
|
<para>
|
||
|
MxCsr - "A callee that modifies any of the non-volatile fields within
|
||
|
MxCsr must restore them before returning to its caller. Furthermore, a caller
|
||
|
that has modified any of these fields must restore them to their standard
|
||
|
values before invoking a callee ..." <footnote id="context.rationale.x86_and_floating_point_env.f1">
|
||
|
<para>
|
||
|
<ulink url="http://http://msdn.microsoft.com/en-us/library/yxty7t75.aspx">MSDN
|
||
|
article 'MxCsr'</ulink>
|
||
|
</para>
|
||
|
</footnote>.
|
||
|
</para>
|
||
|
<para>
|
||
|
FpCsr - "A callee that modifies any of the fields within FpCsr must
|
||
|
restore them before returning to its caller. Furthermore, a caller that has
|
||
|
modified any of these fields must restore them to their standard values before
|
||
|
invoking a callee ..." <footnote id="context.rationale.x86_and_floating_point_env.f2">
|
||
|
<para>
|
||
|
<ulink url="http://http://msdn.microsoft.com/en-us/library/ms235300.aspx">MSDN
|
||
|
article 'FpCsr'</ulink>
|
||
|
</para>
|
||
|
</footnote>.
|
||
|
</para>
|
||
|
<para>
|
||
|
"The MMX and floating-point stack registers (MM0-MM7/ST0-ST7) are preserved
|
||
|
across context switches. There is no explicit calling convention for these
|
||
|
registers." <footnote id="context.rationale.x86_and_floating_point_env.f3">
|
||
|
<para>
|
||
|
<ulink url="http://msdn.microsoft.com/en-us/library/a32tsf7t%28VS.80%29.aspx">MSDN
|
||
|
article 'Legacy Floating-Point Support'</ulink>
|
||
|
</para>
|
||
|
</footnote>.
|
||
|
</para>
|
||
|
<para>
|
||
|
"The 64-bit Microsoft compiler does not use ST(0)-ST(7)/MM0-MM7".
|
||
|
<footnote id="context.rationale.x86_and_floating_point_env.f4">
|
||
|
<para>
|
||
|
'Calling Conventions', Agner Fog
|
||
|
</para>
|
||
|
</footnote>.
|
||
|
</para>
|
||
|
<para>
|
||
|
"XMM6-XMM15 must be preserved" <footnote id="context.rationale.x86_and_floating_point_env.f5">
|
||
|
<para>
|
||
|
<ulink url="http://msdn.microsoft.com/en-us/library/9z1stfyw%28v=vs.100%29.aspx">MSDN
|
||
|
article 'Register Usage'</ulink>
|
||
|
</para>
|
||
|
</footnote>
|
||
|
</para>
|
||
|
<bridgehead renderas="sect4" id="context.rationale.x86_and_floating_point_env.h3">
|
||
|
<phrase id="context.rationale.x86_and_floating_point_env.sysv"/><link linkend="context.rationale.x86_and_floating_point_env.sysv">SysV</link>
|
||
|
</bridgehead>
|
||
|
<para>
|
||
|
"The control bits of the MxCsr register are callee-saved (preserved
|
||
|
across calls), while the status bits are caller-saved (not preserved). The
|
||
|
x87 status word register is caller-saved, whereas the x87 control word (FpCsr)
|
||
|
is callee-saved." <footnote id="context.rationale.x86_and_floating_point_env.f6">
|
||
|
<para>
|
||
|
SysV ABI AMD64 Architecture Processor Supplement Draft Version 0.99.4,
|
||
|
3.2.1
|
||
|
</para>
|
||
|
</footnote>.
|
||
|
</para>
|
||
|
</section>
|
||
|
</section>
|
||
|
<section id="context.reference">
|
||
|
<title><link linkend="context.reference">Reference</link></title>
|
||
|
<bridgehead renderas="sect3" id="context.reference.h0">
|
||
|
<phrase id="context.reference.arm"/><link linkend="context.reference.arm">ARM</link>
|
||
|
</bridgehead>
|
||
|
<itemizedlist>
|
||
|
<listitem>
|
||
|
<simpara>
|
||
|
AAPCS ABI: Procedure Call Standard for the ARM Architecture
|
||
|
</simpara>
|
||
|
</listitem>
|
||
|
<listitem>
|
||
|
<simpara>
|
||
|
AAPCS/LINUX: ARM GNU/Linux Application Binary Interface Supplement
|
||
|
</simpara>
|
||
|
</listitem>
|
||
|
</itemizedlist>
|
||
|
<bridgehead renderas="sect3" id="context.reference.h1">
|
||
|
<phrase id="context.reference.mips"/><link linkend="context.reference.mips">MIPS</link>
|
||
|
</bridgehead>
|
||
|
<itemizedlist>
|
||
|
<listitem>
|
||
|
<simpara>
|
||
|
O32 ABI: SYSTEM V APPLICATION BINARY INTERFACE, MIPS RISC Processor Supplement
|
||
|
</simpara>
|
||
|
</listitem>
|
||
|
</itemizedlist>
|
||
|
<bridgehead renderas="sect3" id="context.reference.h2">
|
||
|
<phrase id="context.reference.powerpc32"/><link linkend="context.reference.powerpc32">PowerPC32</link>
|
||
|
</bridgehead>
|
||
|
<itemizedlist>
|
||
|
<listitem>
|
||
|
<simpara>
|
||
|
SYSV ABI: SYSTEM V APPLICATION BINARY INTERFACE PowerPC Processor Supplement
|
||
|
</simpara>
|
||
|
</listitem>
|
||
|
</itemizedlist>
|
||
|
<bridgehead renderas="sect3" id="context.reference.h3">
|
||
|
<phrase id="context.reference.powerpc64"/><link linkend="context.reference.powerpc64">PowerPC64</link>
|
||
|
</bridgehead>
|
||
|
<itemizedlist>
|
||
|
<listitem>
|
||
|
<simpara>
|
||
|
SYSV ABI: PowerPC User Instruction Set Architecture, Book I
|
||
|
</simpara>
|
||
|
</listitem>
|
||
|
</itemizedlist>
|
||
|
<bridgehead renderas="sect3" id="context.reference.h4">
|
||
|
<phrase id="context.reference.x86_32"/><link linkend="context.reference.x86_32">X86-32</link>
|
||
|
</bridgehead>
|
||
|
<itemizedlist>
|
||
|
<listitem>
|
||
|
<simpara>
|
||
|
SYSV ABI: SYSTEM V APPLICATION BINARY INTERFACE, Intel386TM Architecture
|
||
|
Processor Supplement
|
||
|
</simpara>
|
||
|
</listitem>
|
||
|
<listitem>
|
||
|
<simpara>
|
||
|
MS PE: <ulink url="http://msdn.microsoft.com/en-us/library/k2b2ssfy.aspx">Calling
|
||
|
Conventions</ulink>
|
||
|
</simpara>
|
||
|
</listitem>
|
||
|
</itemizedlist>
|
||
|
<bridgehead renderas="sect3" id="context.reference.h5">
|
||
|
<phrase id="context.reference.x86_64"/><link linkend="context.reference.x86_64">X86-64</link>
|
||
|
</bridgehead>
|
||
|
<itemizedlist>
|
||
|
<listitem>
|
||
|
<simpara>
|
||
|
SYSV ABI: System V Application Binary Interface, AMD64 Architecture Processor
|
||
|
Supplement
|
||
|
</simpara>
|
||
|
</listitem>
|
||
|
<listitem>
|
||
|
<simpara>
|
||
|
MS PE: <ulink url="http://msdn.microsoft.com/en-us/library/7kcdt6fy%28VS.80%29.aspx">x64
|
||
|
Software Conventions</ulink>
|
||
|
</simpara>
|
||
|
</listitem>
|
||
|
</itemizedlist>
|
||
|
</section>
|
||
|
<section id="context.acknowledgements">
|
||
|
<title><link linkend="context.acknowledgements">Acknowledgments</link></title>
|
||
|
<para>
|
||
|
I'd like to thank Adreas Fett, Artyom Beilis, Daniel Larimer, David Deakins,
|
||
|
Evgeny Shapovalov, Fernando Pelliccioni, Giovanni Piero Deretta, Gordon Woodhull,
|
||
|
Helge Bahmann, Holger Grund, Jeffrey Lee Hellrung (Jr.), Keith Jeffery, Martin
|
||
|
Husemann, Phil Endecott, Robert Stewart, Sergey Cheban, Steven Watanabe, Vicente
|
||
|
J. Botet Escriba, Wayne Piekarski.
|
||
|
</para>
|
||
|
</section>
|
||
|
</library>
|