mirror of
https://github.com/boostorg/context.git
synced 2026-01-27 18:52:16 +00:00
3474 lines
284 KiB
XML
3474 lines
284 KiB
XML
<?xml version="1.0" encoding="UTF-8"?>
|
|
<!DOCTYPE article PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
|
|
<article id="context" last-revision="$Date: 2012/02/01 18:25:59 $" xmlns:xi="http://www.w3.org/2001/XInclude">
|
|
<title>Context</title>
|
|
<articleinfo>
|
|
<authorgroup>
|
|
<author>
|
|
<firstname>Oliver</firstname> <surname>Kowalke</surname>
|
|
</author>
|
|
</authorgroup>
|
|
<copyright>
|
|
<year>2009</year> <holder>Oliver Kowalke</holder>
|
|
</copyright>
|
|
<legalnotice>
|
|
<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>
|
|
<articlepurpose>
|
|
C++ Library for swiching different user contexts
|
|
</articlepurpose>
|
|
<articlecategory name="category:text"></articlecategory>
|
|
</articleinfo>
|
|
<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 <link linkend="context.context.context"><emphasis>context</emphasis></link>
|
|
instance 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 aquivalent
|
|
to <ulink url="http://msdn.microsoft.com/en-us/library/9k7k7cf0%28v=vs.80%29.aspx">C#
|
|
keyword <emphasis>yield</emphasis></ulink> in C++ ( <link linkend="context.examples.enumerator">see
|
|
enumerator example</link>).
|
|
</para>
|
|
<para>
|
|
A <link linkend="context.context.context"><emphasis>context</emphasis></link>
|
|
provides the means to suspend the current execution path and to transfer execution
|
|
control, thereby permitting another <link linkend="context.context.context"><emphasis>context</emphasis></link>
|
|
to run on the current thread. This stateful transfer mechanism enables a <link
|
|
linkend="context.context.context"><emphasis>context</emphasis></link> 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="context.context.context"><emphasis>context</emphasis></link>
|
|
only runs on a single thread, it can be migrated to another thread at any given
|
|
time.
|
|
</para>
|
|
<para>
|
|
A context switch between threads requires system calls (involving the OS kernel),
|
|
which can cost thousands of CPU cycles on x86 CPUs. By contrast, transferring
|
|
control among them requires only a few hundred CPU cycles because it does not
|
|
involve system calls as it is done within a single thread.
|
|
</para>
|
|
<para>
|
|
In order to use the classes and functions described here, you can either include
|
|
the specific headers specified by the descriptions of each class or function,
|
|
or include the master library header:
|
|
</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">all</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">></phrase>
|
|
</programlisting>
|
|
<para>
|
|
which includes all the other headers in turn.
|
|
</para>
|
|
<para>
|
|
All functions and classes are contained in the namespace <emphasis>boost::contexts</emphasis>.
|
|
</para>
|
|
<para>
|
|
<emphasis role="bold">Boost.Context</emphasis> depends on <emphasis role="bold">Boost.Move</emphasis>.
|
|
</para>
|
|
</section>
|
|
<section id="context.installtion">
|
|
<title><link linkend="context.installtion">How to build and install</link></title>
|
|
<para>
|
|
<emphasis role="bold">Boost.Context</emphasis> must be built for the particular
|
|
compiler(s) and CPU architecture(s)s being targeted. <emphasis role="bold">Boost.Context</emphasis>
|
|
includes assembly code and, therefore, requires GNU AS for supported POSIX
|
|
systems, and MASM for Windows systems.
|
|
</para>
|
|
<note>
|
|
<para>
|
|
The architecture, instruction set, and address model are optional <emphasis
|
|
role="bold">Boost.Build</emphasis> properties that must be given on the bjam
|
|
command line, as shown in the table below.
|
|
</para>
|
|
</note>
|
|
<informaltable frame="all">
|
|
<tgroup cols="2">
|
|
<thead>
|
|
<row>
|
|
<entry>
|
|
</entry>
|
|
<entry>
|
|
</entry>
|
|
</row>
|
|
</thead>
|
|
<tbody>
|
|
<row>
|
|
<entry>
|
|
<para>
|
|
ARM, UNIX, aapcs, elf
|
|
</para>
|
|
</entry>
|
|
<entry>
|
|
<para>
|
|
bjam toolset = gcc architecture = arm
|
|
</para>
|
|
</entry>
|
|
</row>
|
|
<row>
|
|
<entry>
|
|
<para>
|
|
MIPS (32bit), UNIX, o32, elf
|
|
</para>
|
|
</entry>
|
|
<entry>
|
|
<para>
|
|
bjam toolset = gcc architecture = mips1 <footnote>
|
|
<para>
|
|
Because of a bug in shared_ptr you have to apply a patch 'patches/llsc-mips.patch'
|
|
to shared_ptr or provide cxxflags="-mips2" at bjam command-line.
|
|
</para>
|
|
</footnote>
|
|
</para>
|
|
</entry>
|
|
</row>
|
|
<row>
|
|
<entry>
|
|
<para>
|
|
I386, UNIX, sysv, elf
|
|
</para>
|
|
</entry>
|
|
<entry>
|
|
<para>
|
|
bjam toolset = gcc architecture = x86 instruction-set = i686 address-model
|
|
= 32
|
|
</para>
|
|
</entry>
|
|
</row>
|
|
<row>
|
|
<entry>
|
|
<para>
|
|
I386, UNIX, sysv, elf
|
|
</para>
|
|
</entry>
|
|
<entry>
|
|
<para>
|
|
bjam toolset = intel architecture = x86 instruction-set = i686 address-model
|
|
= 32
|
|
</para>
|
|
</entry>
|
|
</row>
|
|
<row>
|
|
<entry>
|
|
<para>
|
|
I386, Windows, ms, pe
|
|
</para>
|
|
</entry>
|
|
<entry>
|
|
<para>
|
|
bjam toolset = msvc-9.0 architecture = x86 instruction-set = i686
|
|
address-model = 32
|
|
</para>
|
|
</entry>
|
|
</row>
|
|
<row>
|
|
<entry>
|
|
<para>
|
|
PowerPc (32bit), UNIX, sysv, elf
|
|
</para>
|
|
</entry>
|
|
<entry>
|
|
<para>
|
|
bjam toolset = gcc architecture = power address-model = 32
|
|
</para>
|
|
</entry>
|
|
</row>
|
|
<row>
|
|
<entry>
|
|
<para>
|
|
PowerPc (64bit), UNIX, sysv, elf
|
|
</para>
|
|
</entry>
|
|
<entry>
|
|
<para>
|
|
bjam toolset = gcc architecture = power address-model = 64
|
|
</para>
|
|
</entry>
|
|
</row>
|
|
<row>
|
|
<entry>
|
|
<para>
|
|
X86_64, UNIX, sysv, elf
|
|
</para>
|
|
</entry>
|
|
<entry>
|
|
<para>
|
|
bjam toolset = gcc architecture = x86 instruction-set = yorksfield
|
|
address-model = 64
|
|
</para>
|
|
</entry>
|
|
</row>
|
|
<row>
|
|
<entry>
|
|
<para>
|
|
X86_64, UNIX, sysv, elf
|
|
</para>
|
|
</entry>
|
|
<entry>
|
|
<para>
|
|
bjam toolset = intel architecture = x86 instruction-set = yorksfield
|
|
address-model = 64
|
|
</para>
|
|
</entry>
|
|
</row>
|
|
<row>
|
|
<entry>
|
|
<para>
|
|
X86_64, Windows, ms, pe
|
|
</para>
|
|
</entry>
|
|
<entry>
|
|
<para>
|
|
bjam toolset = msvc-10.0 architecture = x86 instruction-set = yorksfield
|
|
address-model = 64
|
|
</para>
|
|
</entry>
|
|
</row>
|
|
</tbody>
|
|
</tgroup>
|
|
</informaltable>
|
|
</section>
|
|
<section id="context.context">
|
|
<title><link linkend="context.context">Context</link></title>
|
|
<para>
|
|
Each instance of <link linkend="context.context.context"><emphasis>context</emphasis></link>
|
|
represents a context (CPU registers and stack space) of execution or <emphasis>not-a-context</emphasis>.
|
|
Objects of type <link linkend="context.context.context"><emphasis>context</emphasis></link>
|
|
are moveable but not copyable and can be returned by a function.
|
|
</para>
|
|
|
|
<programlisting><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">contexts</phrase><phrase role="special">::</phrase><phrase role="identifier">context</phrase> <phrase role="identifier">make_context</phrase><phrase role="special">();</phrase>
|
|
|
|
<phrase role="keyword">void</phrase> <phrase role="identifier">f</phrase><phrase role="special">()</phrase>
|
|
<phrase role="special">{</phrase>
|
|
<phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">contexts</phrase><phrase role="special">::</phrase><phrase role="identifier">context</phrase> <phrase role="identifier">ctx</phrase><phrase role="special">(</phrase> <phrase role="identifier">make_context</phrase><phrase role="special">()</phrase> <phrase role="special">);</phrase>
|
|
<phrase role="identifier">ctx</phrase><phrase role="special">.</phrase><phrase role="identifier">resume</phrase><phrase role="special">();</phrase>
|
|
<phrase role="special">}</phrase>
|
|
</programlisting>
|
|
<note>
|
|
<para>
|
|
<emphasis role="bold">Boost.Move</emphasis> is used to emulate rvalue references.
|
|
</para>
|
|
</note>
|
|
<warning>
|
|
<para>
|
|
If contexts are used in a multithreaded application, they can migrated between
|
|
threads, but must not reference <emphasis>thread-local storage</emphasis>.
|
|
</para>
|
|
</warning>
|
|
<note>
|
|
<para>
|
|
If <emphasis>fiber-local storage</emphasis> is used on Windows, the user
|
|
is responsible for calling <emphasis>::FlsAlloc()</emphasis>, <emphasis>::FlsFree()</emphasis>.
|
|
</para>
|
|
</note>
|
|
<anchor id="context.context.executing_a_context"/>
|
|
<bridgehead renderas="sect3">
|
|
<link linkend="context.context.executing_a_context">Executing a context</link>
|
|
</bridgehead>
|
|
<para>
|
|
A new context is created from a callable object (known as the <emphasis>context-function</emphasis>).
|
|
The stack size, stack unwinding behavior, and context termination behavior
|
|
are determined by additional arguments.
|
|
</para>
|
|
<para>
|
|
The <link linkend="context.context.context"><emphasis>context</emphasis></link>
|
|
constructor uses a <emphasis>StackAllocator concept</emphasis> to allocate
|
|
an associated stack, and the destructor uses the same <emphasis>StackAllocator
|
|
concept</emphasis> to deallocate the stack. The default <emphasis>StackAllocator
|
|
concept</emphasis> is <emphasis>StackAllocator</emphasis>, but a custom stack-allocator
|
|
can be passed to the constructor.
|
|
</para>
|
|
<para>
|
|
Additional arguments needed by a <emphasis>context-function</emphasis> are
|
|
supplied as additional arguments to the context constructor.
|
|
</para>
|
|
|
|
<programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">f</phrase><phrase role="special">(</phrase> <phrase role="keyword">int</phrase> <phrase role="identifier">i</phrase><phrase role="special">);</phrase>
|
|
|
|
<phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">contexts</phrase><phrase role="special">::</phrase><phrase role="identifier">context</phrase> <phrase role="identifier">ctx</phrase><phrase role="special">(</phrase> <phrase role="identifier">f</phrase><phrase role="special">,</phrase> <phrase role="number">42</phrase><phrase role="special">,</phrase>
|
|
<phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">contexts</phrase><phrase role="special">::</phrase><phrase role="identifier">default_stacksize</phrase><phrase role="special">(),</phrase>
|
|
<phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">contexts</phrase><phrase role="special">::</phrase><phrase role="identifier">no_stack_unwind</phrase><phrase role="special">,</phrase>
|
|
<phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">contexts</phrase><phrase role="special">::</phrase><phrase role="identifier">return_to_caller</phrase><phrase role="special">);</phrase>
|
|
</programlisting>
|
|
<para>
|
|
The <emphasis>context-function</emphasis>, as well as its arguments, if any,
|
|
are copied into the context's state. If a reference is required, use boost::ref.
|
|
</para>
|
|
<para>
|
|
The maximum number of arguments of <emphasis>context-function</emphasis> is
|
|
defined by BOOST_CONTEXT_ARITY (default is 10 and might be increased).
|
|
</para>
|
|
<para>
|
|
Calling <emphasis>context::start()</emphasis> invokes the <emphasis>context-function</emphasis>
|
|
in a newly created context complete with registers, flags, stack and instruction
|
|
pointers. When control should be returned to the original calling context,
|
|
call <emphasis>context::suspend()</emphasis>. The current context information
|
|
(registers, flags, and stack and instruction pointers) is saved and the original
|
|
context information is restored. Calling <emphasis>context::resume()</emphasis>
|
|
resumes execution in the second context after saving the new state of the original
|
|
context. Note that <emphasis>context::start()</emphasis> must be called first
|
|
and only once.
|
|
</para>
|
|
|
|
<programlisting><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">contexts</phrase><phrase role="special">::</phrase><phrase role="identifier">context</phrase> <phrase role="identifier">ctx</phrase><phrase role="special">;</phrase>
|
|
|
|
<phrase role="keyword">void</phrase> <phrase role="identifier">fn</phrase><phrase role="special">(</phrase> <phrase role="keyword">int</phrase> <phrase role="identifier">j</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">i</phrase> <phrase role="special">=</phrase> <phrase role="number">0</phrase><phrase role="special">;</phrase> <phrase role="identifier">i</phrase> <phrase role="special"><</phrase> <phrase role="identifier">j</phrase><phrase role="special">;</phrase> <phrase role="special">++</phrase><phrase role="identifier">i</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">"fn(): local variable i == "</phrase> <phrase role="special"><<</phrase> <phrase role="identifier">i</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="comment">// save current context
|
|
</phrase> <phrase role="comment">// value of local variable is preserved
|
|
</phrase> <phrase role="comment">// transfer execution control back to main()
|
|
</phrase> <phrase role="identifier">ctx</phrase><phrase role="special">.</phrase><phrase role="identifier">suspend</phrase><phrase role="special">();</phrase>
|
|
|
|
<phrase role="comment">// ctx.resume() was called
|
|
</phrase> <phrase role="comment">// execution control transfered back from main()
|
|
</phrase> <phrase role="special">}</phrase>
|
|
<phrase role="special">}</phrase>
|
|
|
|
<phrase role="keyword">int</phrase> <phrase role="identifier">main</phrase><phrase role="special">(</phrase> <phrase role="keyword">int</phrase> <phrase role="identifier">argc</phrase><phrase role="special">,</phrase> <phrase role="keyword">char</phrase> <phrase role="special">*</phrase> <phrase role="identifier">argv</phrase><phrase role="special">[])</phrase>
|
|
<phrase role="special">{</phrase>
|
|
<phrase role="identifier">ctx</phrase> <phrase role="special">=</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">contexts</phrase><phrase role="special">::</phrase><phrase role="identifier">context</phrase><phrase role="special">(</phrase> <phrase role="identifier">fn</phrase><phrase role="special">,</phrase> <phrase role="number">7</phrase><phrase role="special">,</phrase>
|
|
<phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">contexts</phrase><phrase role="special">::</phrase><phrase role="identifier">default_stacksize</phrase><phrase role="special">(),</phrase>
|
|
<phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">contexts</phrase><phrase role="special">::</phrase><phrase role="identifier">no_stack_unwind</phrase><phrase role="special">,</phrase>
|
|
<phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">contexts</phrase><phrase role="special">::</phrase><phrase role="identifier">return_to_caller</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">"main() starts context ctx"</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="comment">// start the context ctx for the first time; enter fn()
|
|
</phrase> <phrase role="identifier">ctx</phrase><phrase role="special">.</phrase><phrase role="identifier">start</phrase><phrase role="special">();</phrase>
|
|
|
|
<phrase role="comment">// ctx.suspend() was called so we returned from start()
|
|
</phrase> <phrase role="keyword">while</phrase> <phrase role="special">(</phrase> <phrase role="special">!</phrase> <phrase role="identifier">ctx</phrase><phrase role="special">.</phrase><phrase role="identifier">is_complete</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">cout</phrase> <phrase role="special"><<</phrase> <phrase role="string">"main() calls context ctx"</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="comment">// resume inside fn()
|
|
</phrase> <phrase role="comment">// execution control is transfered to ctx
|
|
</phrase> <phrase role="identifier">ctx</phrase><phrase role="special">.</phrase><phrase role="identifier">resume</phrase><phrase role="special">();</phrase>
|
|
|
|
<phrase role="comment">// ctx.suspend() was called within fn()
|
|
</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">"Done"</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">EXIT_SUCCESS</phrase><phrase role="special">;</phrase>
|
|
<phrase role="special">}</phrase>
|
|
|
|
<phrase role="identifier">output</phrase><phrase role="special">:</phrase>
|
|
<phrase role="identifier">main</phrase><phrase role="special">()</phrase> <phrase role="identifier">starts</phrase> <phrase role="identifier">context</phrase> <phrase role="identifier">ctx</phrase>
|
|
<phrase role="identifier">fn</phrase><phrase role="special">():</phrase> <phrase role="identifier">local</phrase> <phrase role="identifier">variable</phrase> <phrase role="identifier">i</phrase> <phrase role="special">==</phrase> <phrase role="number">0</phrase>
|
|
<phrase role="identifier">main</phrase><phrase role="special">()</phrase> <phrase role="identifier">calls</phrase> <phrase role="identifier">context</phrase> <phrase role="identifier">ctx</phrase>
|
|
<phrase role="identifier">fn</phrase><phrase role="special">():</phrase> <phrase role="identifier">local</phrase> <phrase role="identifier">variable</phrase> <phrase role="identifier">i</phrase> <phrase role="special">==</phrase> <phrase role="number">1</phrase>
|
|
<phrase role="identifier">main</phrase><phrase role="special">()</phrase> <phrase role="identifier">calls</phrase> <phrase role="identifier">context</phrase> <phrase role="identifier">ctx</phrase>
|
|
<phrase role="identifier">fn</phrase><phrase role="special">():</phrase> <phrase role="identifier">local</phrase> <phrase role="identifier">variable</phrase> <phrase role="identifier">i</phrase> <phrase role="special">==</phrase> <phrase role="number">2</phrase>
|
|
<phrase role="identifier">main</phrase><phrase role="special">()</phrase> <phrase role="identifier">calls</phrase> <phrase role="identifier">context</phrase> <phrase role="identifier">ctx</phrase>
|
|
<phrase role="identifier">fn</phrase><phrase role="special">():</phrase> <phrase role="identifier">local</phrase> <phrase role="identifier">variable</phrase> <phrase role="identifier">i</phrase> <phrase role="special">==</phrase> <phrase role="number">3</phrase>
|
|
<phrase role="identifier">main</phrase><phrase role="special">()</phrase> <phrase role="identifier">calls</phrase> <phrase role="identifier">context</phrase> <phrase role="identifier">ctx</phrase>
|
|
<phrase role="identifier">fn</phrase><phrase role="special">():</phrase> <phrase role="identifier">local</phrase> <phrase role="identifier">variable</phrase> <phrase role="identifier">i</phrase> <phrase role="special">==</phrase> <phrase role="number">4</phrase>
|
|
<phrase role="identifier">main</phrase><phrase role="special">()</phrase> <phrase role="identifier">calls</phrase> <phrase role="identifier">context</phrase> <phrase role="identifier">ctx</phrase>
|
|
<phrase role="identifier">fn</phrase><phrase role="special">():</phrase> <phrase role="identifier">local</phrase> <phrase role="identifier">variable</phrase> <phrase role="identifier">i</phrase> <phrase role="special">==</phrase> <phrase role="number">5</phrase>
|
|
<phrase role="identifier">main</phrase><phrase role="special">()</phrase> <phrase role="identifier">calls</phrase> <phrase role="identifier">context</phrase> <phrase role="identifier">ctx</phrase>
|
|
<phrase role="identifier">fn</phrase><phrase role="special">():</phrase> <phrase role="identifier">local</phrase> <phrase role="identifier">variable</phrase> <phrase role="identifier">i</phrase> <phrase role="special">==</phrase> <phrase role="number">6</phrase>
|
|
<phrase role="identifier">main</phrase><phrase role="special">()</phrase> <phrase role="identifier">calls</phrase> <phrase role="identifier">context</phrase> <phrase role="identifier">ctx</phrase>
|
|
<phrase role="identifier">Done</phrase>
|
|
</programlisting>
|
|
<warning>
|
|
<para>
|
|
Calling <emphasis>context::resume()</emphasis> from inside the same context
|
|
results in undefined behaviour.
|
|
</para>
|
|
</warning>
|
|
<note>
|
|
<para>
|
|
In contrast to threads, which are preemtive, <link linkend="context.context.context"><emphasis>context</emphasis></link>
|
|
switches are cooperative (programmer controls when switch will happen). The
|
|
kernel is not involved in the context switches.
|
|
</para>
|
|
</note>
|
|
<anchor id="context.context.transfer_of_data"/>
|
|
<bridgehead renderas="sect3">
|
|
<link linkend="context.context.transfer_of_data">Transfer of data</link>
|
|
</bridgehead>
|
|
<para>
|
|
The argument passed to <emphasis>context::resume()</emphasis>, in one context,
|
|
is returned by <emphasis>context::suspend()</emphasis> in the other context.
|
|
The intptr_t passed to <emphasis>context::suspend()</emphasis>, in one context,
|
|
is returned by <emphasis>context::resume()</emphasis> (or <emphasis>context::start()</emphasis>,
|
|
depending upon which function was called previously) in the other context.
|
|
<emphasis>context::start()</emphasis> has no argument because it enters the
|
|
start of the function, and there is no previous call to <emphasis>context::suspend()</emphasis>
|
|
to return a value.
|
|
</para>
|
|
|
|
<programlisting><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">contexts</phrase><phrase role="special">::</phrase><phrase role="identifier">context</phrase> <phrase role="identifier">ctx</phrase><phrase role="special">;</phrase>
|
|
|
|
<phrase role="keyword">void</phrase> <phrase role="identifier">fn</phrase><phrase role="special">()</phrase>
|
|
<phrase role="special">{</phrase>
|
|
<phrase role="keyword">int</phrase> <phrase role="identifier">i</phrase> <phrase role="special">=</phrase> <phrase role="number">7</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">"fn(): local variable i == "</phrase> <phrase role="special"><<</phrase> <phrase role="identifier">i</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="comment">// save current context
|
|
</phrase> <phrase role="comment">// transfer execution control back to caller
|
|
</phrase> <phrase role="comment">// pass content of variable back
|
|
</phrase> <phrase role="keyword">int</phrase> <phrase role="identifier">j</phrase> <phrase role="special">=</phrase> <phrase role="identifier">ctx</phrase><phrase role="special">.</phrase><phrase role="identifier">suspend</phrase><phrase role="special">(</phrase> <phrase role="identifier">i</phrase><phrase role="special">);</phrase>
|
|
<phrase role="comment">// j == 10 because x == 10 in main()
|
|
</phrase>
|
|
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cout</phrase> <phrase role="special"><<</phrase> <phrase role="string">"transfered value: "</phrase> <phrase role="special"><<</phrase> <phrase role="identifier">j</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="special">}</phrase>
|
|
|
|
<phrase role="keyword">int</phrase> <phrase role="identifier">main</phrase><phrase role="special">(</phrase> <phrase role="keyword">int</phrase> <phrase role="identifier">argc</phrase><phrase role="special">,</phrase> <phrase role="keyword">char</phrase> <phrase role="special">*</phrase> <phrase role="identifier">argv</phrase><phrase role="special">[])</phrase>
|
|
<phrase role="special">{</phrase>
|
|
<phrase role="identifier">ctx</phrase> <phrase role="special">=</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">contexts</phrase><phrase role="special">::</phrase><phrase role="identifier">context</phrase><phrase role="special">(</phrase> <phrase role="identifier">fn</phrase><phrase role="special">,</phrase>
|
|
<phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">contexts</phrase><phrase role="special">::</phrase><phrase role="identifier">default_stacksize</phrase><phrase role="special">(),</phrase>
|
|
<phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">contexts</phrase><phrase role="special">::</phrase><phrase role="identifier">no_stack_unwind</phrase><phrase role="special">,</phrase>
|
|
<phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">contexts</phrase><phrase role="special">::</phrase><phrase role="identifier">return_to_caller</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">"main() calls context ctx"</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="comment">// start the context ctx for the first time
|
|
</phrase> <phrase role="comment">// enter fn()
|
|
</phrase> <phrase role="keyword">int</phrase> <phrase role="identifier">x</phrase> <phrase role="special">=</phrase> <phrase role="identifier">ctx</phrase><phrase role="special">.</phrase><phrase role="identifier">start</phrase><phrase role="special">();</phrase>
|
|
<phrase role="comment">// x == 7 because i == 7 in fn()
|
|
</phrase>
|
|
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cout</phrase> <phrase role="special"><<</phrase> <phrase role="string">"transfered value: "</phrase> <phrase role="special"><<</phrase> <phrase role="identifier">x</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">x</phrase> <phrase role="special">=</phrase> <phrase role="number">10</phrase><phrase role="special">;</phrase>
|
|
<phrase role="comment">// ctx.suspend() was called so we returned from start()
|
|
</phrase> <phrase role="identifier">ctx</phrase><phrase role="special">.</phrase><phrase role="identifier">resume</phrase><phrase role="special">(</phrase> <phrase role="identifier">x</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">"Done"</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">EXIT_SUCCESS</phrase><phrase role="special">;</phrase>
|
|
<phrase role="special">}</phrase>
|
|
|
|
<phrase role="identifier">output</phrase><phrase role="special">:</phrase>
|
|
<phrase role="identifier">main</phrase><phrase role="special">()</phrase> <phrase role="identifier">calls</phrase> <phrase role="identifier">context</phrase> <phrase role="identifier">ctx</phrase>
|
|
<phrase role="identifier">fn</phrase><phrase role="special">():</phrase> <phrase role="identifier">local</phrase> <phrase role="identifier">variable</phrase> <phrase role="identifier">i</phrase> <phrase role="special">==</phrase> <phrase role="number">7</phrase>
|
|
<phrase role="identifier">transfered</phrase> <phrase role="identifier">value</phrase><phrase role="special">:</phrase> <phrase role="number">7</phrase>
|
|
<phrase role="identifier">transfered</phrase> <phrase role="identifier">value</phrase><phrase role="special">:</phrase> <phrase role="number">10</phrase>
|
|
<phrase role="identifier">Done</phrase>
|
|
</programlisting>
|
|
<anchor id="context.context.exceptions_in__emphasis_context_function__emphasis_"/>
|
|
<bridgehead renderas="sect3">
|
|
<link linkend="context.context.exceptions_in__emphasis_context_function__emphasis_">Exceptions
|
|
in <emphasis>context-function</emphasis></link>
|
|
</bridgehead>
|
|
<para>
|
|
If the <emphasis>context-function</emphasis> emits an exception, std::terminate()
|
|
is called.
|
|
</para>
|
|
<important>
|
|
<para>
|
|
Code executed by context must not prevent the propagation of the <emphasis>forced_unwind</emphasis>
|
|
exception. Absorbing that exception will cause stack unwinding to fail. Thus,
|
|
any code that catches all exceptions must rethrow the pending exception.
|
|
</para>
|
|
</important>
|
|
|
|
<programlisting><phrase role="keyword">try</phrase>
|
|
<phrase role="special">{</phrase>
|
|
<phrase role="comment">// code that might throw
|
|
</phrase><phrase role="special">}</phrase>
|
|
<phrase role="keyword">catch</phrase><phrase role="special">(</phrase> <phrase role="identifier">forced_unwind</phrase><phrase role="special">)</phrase>
|
|
<phrase role="special">{</phrase>
|
|
<phrase role="keyword">throw</phrase><phrase role="special">;</phrase>
|
|
<phrase role="special">}</phrase>
|
|
<phrase role="keyword">catch</phrase><phrase role="special">(...)</phrase>
|
|
<phrase role="special">{</phrase>
|
|
<phrase role="comment">// possibly not rethrow pending exception
|
|
</phrase><phrase role="special">}</phrase>
|
|
</programlisting>
|
|
<anchor id="context.context.handling_execution_context_termination"/>
|
|
<bridgehead renderas="sect3">
|
|
<link linkend="context.context.handling_execution_context_termination">Handling
|
|
execution context termination</link>
|
|
</bridgehead>
|
|
<para>
|
|
The last context constructor argument is an enumerated type which determines
|
|
what should happen when the context is complete (that is, when the <emphasis>context-function</emphasis>
|
|
returns). The available values are <code><phrase role="identifier">return_to_caller</phrase></code>
|
|
and <code><phrase role="identifier">exit_application</phrase></code>.
|
|
</para>
|
|
<para>
|
|
When the last constructor argument is <code><phrase role="identifier">return_to_caller</phrase></code>,
|
|
execution control is transferred back to the last invocation of <emphasis>context::start()</emphasis>
|
|
or <emphasis>context::resume()</emphasis> when the context is complete, as
|
|
shown in this example:
|
|
</para>
|
|
|
|
<programlisting><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">contexts</phrase><phrase role="special">::</phrase><phrase role="identifier">context</phrase> <phrase role="identifier">ctx</phrase><phrase role="special">;</phrase>
|
|
|
|
<phrase role="keyword">void</phrase> <phrase role="identifier">fn</phrase><phrase role="special">(</phrase> <phrase role="keyword">int</phrase> <phrase role="identifier">j</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">i</phrase> <phrase role="special">=</phrase> <phrase role="number">0</phrase><phrase role="special">;</phrase> <phrase role="identifier">i</phrase> <phrase role="special"><</phrase> <phrase role="identifier">j</phrase><phrase role="special">;</phrase> <phrase role="special">++</phrase><phrase role="identifier">i</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">"fn(): local variable i == "</phrase> <phrase role="special"><<</phrase> <phrase role="identifier">i</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">ctx</phrase><phrase role="special">.</phrase><phrase role="identifier">suspend</phrase><phrase role="special">();</phrase>
|
|
<phrase role="special">}</phrase>
|
|
|
|
<phrase role="comment">// fn() returns
|
|
</phrase> <phrase role="comment">// execution control is transfered back to main()
|
|
</phrase><phrase role="special">}</phrase>
|
|
|
|
<phrase role="keyword">int</phrase> <phrase role="identifier">main</phrase><phrase role="special">(</phrase> <phrase role="keyword">int</phrase> <phrase role="identifier">argc</phrase><phrase role="special">,</phrase> <phrase role="keyword">char</phrase> <phrase role="special">*</phrase> <phrase role="identifier">argv</phrase><phrase role="special">[])</phrase>
|
|
<phrase role="special">{</phrase>
|
|
<phrase role="identifier">ctx</phrase> <phrase role="special">=</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">contexts</phrase><phrase role="special">::</phrase><phrase role="identifier">context</phrase><phrase role="special">(</phrase> <phrase role="identifier">fn</phrase><phrase role="special">,</phrase> <phrase role="number">7</phrase><phrase role="special">,</phrase>
|
|
<phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">contexts</phrase><phrase role="special">::</phrase><phrase role="identifier">default_stacksize</phrase><phrase role="special">(),</phrase>
|
|
<phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">contexts</phrase><phrase role="special">::</phrase><phrase role="identifier">no_stack_unwind</phrase><phrase role="special">,</phrase>
|
|
<phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">contexts</phrase><phrase role="special">::</phrase><phrase role="identifier">return_to_caller</phrase><phrase role="special">);</phrase>
|
|
|
|
<phrase role="identifier">ctx</phrase><phrase role="special">.</phrase><phrase role="identifier">start</phrase><phrase role="special">();</phrase>
|
|
<phrase role="keyword">while</phrase> <phrase role="special">(</phrase> <phrase role="special">!</phrase> <phrase role="identifier">ctx</phrase><phrase role="special">.</phrase><phrase role="identifier">is_complete</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">cout</phrase> <phrase role="special"><<</phrase> <phrase role="string">"main() calls context ctx"</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">ctx</phrase><phrase role="special">.</phrase><phrase role="identifier">resume</phrase><phrase role="special">();</phrase>
|
|
<phrase role="special">}</phrase>
|
|
|
|
<phrase role="comment">// fn() returned; the context is complete
|
|
</phrase>
|
|
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cout</phrase> <phrase role="special"><<</phrase> <phrase role="string">"Done"</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">EXIT_SUCCESS</phrase><phrase role="special">;</phrase>
|
|
<phrase role="special">}</phrase>
|
|
|
|
<phrase role="identifier">output</phrase><phrase role="special">:</phrase>
|
|
<phrase role="identifier">fn</phrase><phrase role="special">():</phrase> <phrase role="identifier">local</phrase> <phrase role="identifier">variable</phrase> <phrase role="identifier">i</phrase> <phrase role="special">==</phrase> <phrase role="number">0</phrase>
|
|
<phrase role="identifier">main</phrase><phrase role="special">()</phrase> <phrase role="identifier">calls</phrase> <phrase role="identifier">context</phrase> <phrase role="identifier">ctx</phrase>
|
|
<phrase role="identifier">fn</phrase><phrase role="special">():</phrase> <phrase role="identifier">local</phrase> <phrase role="identifier">variable</phrase> <phrase role="identifier">i</phrase> <phrase role="special">==</phrase> <phrase role="number">1</phrase>
|
|
<phrase role="identifier">main</phrase><phrase role="special">()</phrase> <phrase role="identifier">calls</phrase> <phrase role="identifier">context</phrase> <phrase role="identifier">ctx</phrase>
|
|
<phrase role="identifier">fn</phrase><phrase role="special">():</phrase> <phrase role="identifier">local</phrase> <phrase role="identifier">variable</phrase> <phrase role="identifier">i</phrase> <phrase role="special">==</phrase> <phrase role="number">2</phrase>
|
|
<phrase role="identifier">main</phrase><phrase role="special">()</phrase> <phrase role="identifier">calls</phrase> <phrase role="identifier">context</phrase> <phrase role="identifier">ctx</phrase>
|
|
<phrase role="identifier">fn</phrase><phrase role="special">():</phrase> <phrase role="identifier">local</phrase> <phrase role="identifier">variable</phrase> <phrase role="identifier">i</phrase> <phrase role="special">==</phrase> <phrase role="number">3</phrase>
|
|
<phrase role="identifier">main</phrase><phrase role="special">()</phrase> <phrase role="identifier">calls</phrase> <phrase role="identifier">context</phrase> <phrase role="identifier">ctx</phrase>
|
|
<phrase role="identifier">fn</phrase><phrase role="special">():</phrase> <phrase role="identifier">local</phrase> <phrase role="identifier">variable</phrase> <phrase role="identifier">i</phrase> <phrase role="special">==</phrase> <phrase role="number">4</phrase>
|
|
<phrase role="identifier">main</phrase><phrase role="special">()</phrase> <phrase role="identifier">calls</phrase> <phrase role="identifier">context</phrase> <phrase role="identifier">ctx</phrase>
|
|
<phrase role="identifier">fn</phrase><phrase role="special">():</phrase> <phrase role="identifier">local</phrase> <phrase role="identifier">variable</phrase> <phrase role="identifier">i</phrase> <phrase role="special">==</phrase> <phrase role="number">5</phrase>
|
|
<phrase role="identifier">main</phrase><phrase role="special">()</phrase> <phrase role="identifier">calls</phrase> <phrase role="identifier">context</phrase> <phrase role="identifier">ctx</phrase>
|
|
<phrase role="identifier">fn</phrase><phrase role="special">():</phrase> <phrase role="identifier">local</phrase> <phrase role="identifier">variable</phrase> <phrase role="identifier">i</phrase> <phrase role="special">==</phrase> <phrase role="number">6</phrase>
|
|
<phrase role="identifier">main</phrase><phrase role="special">()</phrase> <phrase role="identifier">calls</phrase> <phrase role="identifier">context</phrase> <phrase role="identifier">ctx</phrase>
|
|
<phrase role="identifier">Done</phrase>
|
|
</programlisting>
|
|
<para>
|
|
When the last constructor argument is <code><phrase role="identifier">exit_application</phrase></code>,
|
|
the application terminates with an exit status of zero when the context is
|
|
complete, as shown in the following example:
|
|
</para>
|
|
|
|
<programlisting><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">contexts</phrase><phrase role="special">::</phrase><phrase role="identifier">context</phrase> <phrase role="identifier">ctx</phrase><phrase role="special">;</phrase>
|
|
|
|
<phrase role="keyword">void</phrase> <phrase role="identifier">fn</phrase><phrase role="special">(</phrase> <phrase role="keyword">int</phrase> <phrase role="identifier">j</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">i</phrase> <phrase role="special">=</phrase> <phrase role="number">0</phrase><phrase role="special">;</phrase> <phrase role="identifier">i</phrase> <phrase role="special"><</phrase> <phrase role="identifier">j</phrase><phrase role="special">;</phrase> <phrase role="special">++</phrase><phrase role="identifier">i</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">"fn(): local variable i == "</phrase> <phrase role="special"><<</phrase> <phrase role="identifier">i</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">ctx</phrase><phrase role="special">.</phrase><phrase role="identifier">suspend</phrase><phrase role="special">();</phrase>
|
|
<phrase role="special">}</phrase>
|
|
|
|
<phrase role="comment">// fn() returns
|
|
</phrase> <phrase role="comment">// application will terminate
|
|
</phrase><phrase role="special">}</phrase>
|
|
|
|
<phrase role="keyword">int</phrase> <phrase role="identifier">main</phrase><phrase role="special">(</phrase> <phrase role="keyword">int</phrase> <phrase role="identifier">argc</phrase><phrase role="special">,</phrase> <phrase role="keyword">char</phrase> <phrase role="special">*</phrase> <phrase role="identifier">argv</phrase><phrase role="special">[])</phrase>
|
|
<phrase role="special">{</phrase>
|
|
<phrase role="identifier">ctx</phrase> <phrase role="special">=</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">contexts</phrase><phrase role="special">::</phrase><phrase role="identifier">context</phrase><phrase role="special">(</phrase> <phrase role="identifier">fn</phrase><phrase role="special">,</phrase> <phrase role="number">7</phrase><phrase role="special">,</phrase>
|
|
<phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">contexts</phrase><phrase role="special">::</phrase><phrase role="identifier">default_stacksize</phrase><phrase role="special">(),</phrase>
|
|
<phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">contexts</phrase><phrase role="special">::</phrase><phrase role="identifier">no_stack_unwind</phrase><phrase role="special">,</phrase>
|
|
<phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">contexts</phrase><phrase role="special">::</phrase><phrase role="identifier">exit_application</phrase><phrase role="special">);</phrase>
|
|
|
|
<phrase role="identifier">ctx</phrase><phrase role="special">.</phrase><phrase role="identifier">start</phrase><phrase role="special">();</phrase>
|
|
<phrase role="keyword">while</phrase> <phrase role="special">(</phrase> <phrase role="special">!</phrase> <phrase role="identifier">ctx</phrase><phrase role="special">.</phrase><phrase role="identifier">is_complete</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">cout</phrase> <phrase role="special"><<</phrase> <phrase role="string">"main() calls context ctx"</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">ctx</phrase><phrase role="special">.</phrase><phrase role="identifier">resume</phrase><phrase role="special">();</phrase>
|
|
<phrase role="special">}</phrase>
|
|
|
|
<phrase role="comment">// never reached
|
|
</phrase> <phrase role="keyword">return</phrase> <phrase role="identifier">EXIT_SUCCESS</phrase><phrase role="special">;</phrase>
|
|
<phrase role="special">}</phrase>
|
|
|
|
<phrase role="identifier">output</phrase><phrase role="special">:</phrase>
|
|
<phrase role="identifier">fn</phrase><phrase role="special">()</phrase> <phrase role="identifier">calls</phrase> <phrase role="identifier">context</phrase> <phrase role="identifier">ctx</phrase>
|
|
<phrase role="identifier">fn</phrase><phrase role="special">():</phrase> <phrase role="identifier">local</phrase> <phrase role="identifier">variable</phrase> <phrase role="identifier">i</phrase> <phrase role="special">==</phrase> <phrase role="number">1</phrase>
|
|
<phrase role="identifier">main</phrase><phrase role="special">()</phrase> <phrase role="identifier">calls</phrase> <phrase role="identifier">context</phrase> <phrase role="identifier">ctx</phrase>
|
|
<phrase role="identifier">fn</phrase><phrase role="special">():</phrase> <phrase role="identifier">local</phrase> <phrase role="identifier">variable</phrase> <phrase role="identifier">i</phrase> <phrase role="special">==</phrase> <phrase role="number">2</phrase>
|
|
<phrase role="identifier">main</phrase><phrase role="special">()</phrase> <phrase role="identifier">calls</phrase> <phrase role="identifier">context</phrase> <phrase role="identifier">ctx</phrase>
|
|
<phrase role="identifier">fn</phrase><phrase role="special">():</phrase> <phrase role="identifier">local</phrase> <phrase role="identifier">variable</phrase> <phrase role="identifier">i</phrase> <phrase role="special">==</phrase> <phrase role="number">3</phrase>
|
|
<phrase role="identifier">main</phrase><phrase role="special">()</phrase> <phrase role="identifier">calls</phrase> <phrase role="identifier">context</phrase> <phrase role="identifier">ctx</phrase>
|
|
<phrase role="identifier">fn</phrase><phrase role="special">():</phrase> <phrase role="identifier">local</phrase> <phrase role="identifier">variable</phrase> <phrase role="identifier">i</phrase> <phrase role="special">==</phrase> <phrase role="number">4</phrase>
|
|
<phrase role="identifier">main</phrase><phrase role="special">()</phrase> <phrase role="identifier">calls</phrase> <phrase role="identifier">context</phrase> <phrase role="identifier">ctx</phrase>
|
|
<phrase role="identifier">fn</phrase><phrase role="special">():</phrase> <phrase role="identifier">local</phrase> <phrase role="identifier">variable</phrase> <phrase role="identifier">i</phrase> <phrase role="special">==</phrase> <phrase role="number">5</phrase>
|
|
<phrase role="identifier">main</phrase><phrase role="special">()</phrase> <phrase role="identifier">calls</phrase> <phrase role="identifier">context</phrase> <phrase role="identifier">ctx</phrase>
|
|
<phrase role="identifier">fn</phrase><phrase role="special">():</phrase> <phrase role="identifier">local</phrase> <phrase role="identifier">variable</phrase> <phrase role="identifier">i</phrase> <phrase role="special">==</phrase> <phrase role="number">6</phrase>
|
|
<phrase role="identifier">main</phrase><phrase role="special">()</phrase> <phrase role="identifier">calls</phrase> <phrase role="identifier">context</phrase> <phrase role="identifier">ctx</phrase>
|
|
</programlisting>
|
|
<anchor id="context.context.chaining_contexts"/>
|
|
<bridgehead renderas="sect3">
|
|
<link linkend="context.context.chaining_contexts">Chaining contexts</link>
|
|
</bridgehead>
|
|
<para>
|
|
<emphasis role="bold">Boost.Context</emphasis> provides the ability to chain
|
|
context instances by passing a reference to another context, other than that
|
|
<emphasis>not-a-context</emphasis>, as the last constructor argument. In this
|
|
way, it is possible to create a chain of contexts. Depending on the <code><phrase
|
|
role="identifier">do_return</phrase></code> argument in the constructor of
|
|
the last context in the chain, the application terminates or execution control
|
|
is transferred back to the last invocation of <emphasis>context::resume()</emphasis>.
|
|
Each call of <emphasis>context::suspend()</emphasis>, for the chained context
|
|
instances, will return to <emphasis>context::resume()</emphasis>.
|
|
</para>
|
|
|
|
<programlisting><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">contexts</phrase><phrase role="special">::</phrase><phrase role="identifier">context</phrase> <phrase role="identifier">ctx2</phrase><phrase role="special">;</phrase>
|
|
|
|
<phrase role="keyword">void</phrase> <phrase role="identifier">fn1</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">"fn1(): when this function returns fn2() will be 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="special">}</phrase>
|
|
|
|
<phrase role="keyword">void</phrase> <phrase role="identifier">fn2</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">"fn2(): first time 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">ctx2</phrase><phrase role="special">.</phrase><phrase role="identifier">suspend</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">"fn2(): second time entered\n"</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">"fn2(): return to main()"</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="special">}</phrase>
|
|
|
|
<phrase role="keyword">int</phrase> <phrase role="identifier">main</phrase><phrase role="special">(</phrase> <phrase role="keyword">int</phrase> <phrase role="identifier">argc</phrase><phrase role="special">,</phrase> <phrase role="keyword">char</phrase> <phrase role="special">*</phrase> <phrase role="identifier">argv</phrase><phrase role="special">[])</phrase>
|
|
<phrase role="special">{</phrase>
|
|
<phrase role="special">{</phrase>
|
|
<phrase role="comment">// ctx2 will return to ctx2.resume()
|
|
</phrase> <phrase role="identifier">ctx2</phrase> <phrase role="special">=</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">contexts</phrase><phrase role="special">::</phrase><phrase role="identifier">context</phrase><phrase role="special">(</phrase>
|
|
<phrase role="identifier">fn2</phrase><phrase role="special">,</phrase>
|
|
<phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">contexts</phrase><phrase role="special">::</phrase><phrase role="identifier">default_stacksize</phrase><phrase role="special">(),</phrase>
|
|
<phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">contexts</phrase><phrase role="special">::</phrase><phrase role="identifier">no_stack_unwind</phrase><phrase role="special">,</phrase>
|
|
<phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">contexts</phrase><phrase role="special">::</phrase><phrase role="identifier">return_to_caller</phrase><phrase role="special">);</phrase>
|
|
|
|
<phrase role="comment">// ctx1 defines ctx2 as its successor
|
|
</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">contexts</phrase><phrase role="special">::</phrase><phrase role="identifier">context</phrase> <phrase role="identifier">ctx1</phrase><phrase role="special">(</phrase>
|
|
<phrase role="identifier">fn1</phrase><phrase role="special">,</phrase>
|
|
<phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">contexts</phrase><phrase role="special">::</phrase><phrase role="identifier">default_stacksize</phrase><phrase role="special">(),</phrase>
|
|
<phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">contexts</phrase><phrase role="special">::</phrase><phrase role="identifier">no_stack_unwind</phrase><phrase role="special">,</phrase>
|
|
<phrase role="identifier">ctx2</phrase><phrase role="special">);</phrase>
|
|
|
|
<phrase role="comment">// transfer execution control to ctx1
|
|
</phrase> <phrase role="comment">// fn1() is entered
|
|
</phrase> <phrase role="identifier">ctx1</phrase><phrase role="special">.</phrase><phrase role="identifier">start</phrase><phrase role="special">();</phrase>
|
|
|
|
<phrase role="comment">// ctx2.suspend() was called
|
|
</phrase> <phrase role="special">}</phrase>
|
|
|
|
<phrase role="comment">// ctx2 was already started by ctx1
|
|
</phrase> <phrase role="identifier">ctx2</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">"Done"</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">EXIT_SUCCESS</phrase><phrase role="special">;</phrase>
|
|
<phrase role="special">}</phrase>
|
|
|
|
<phrase role="identifier">output</phrase><phrase role="special">:</phrase>
|
|
<phrase role="identifier">fn1</phrase><phrase role="special">():</phrase> <phrase role="identifier">when</phrase> <phrase role="keyword">this</phrase> <phrase role="identifier">function</phrase> <phrase role="identifier">returns</phrase> <phrase role="identifier">fn2</phrase><phrase role="special">()</phrase> <phrase role="identifier">will</phrase> <phrase role="identifier">be</phrase> <phrase role="identifier">entered</phrase>
|
|
<phrase role="identifier">fn2</phrase><phrase role="special">():</phrase> <phrase role="identifier">first</phrase> <phrase role="identifier">time</phrase> <phrase role="identifier">entered</phrase>
|
|
<phrase role="identifier">fn2</phrase><phrase role="special">():</phrase> <phrase role="identifier">second</phrase> <phrase role="identifier">time</phrase> <phrase role="identifier">entered</phrase>
|
|
<phrase role="identifier">fnd2</phrase><phrase role="special">():</phrase> <phrase role="keyword">return</phrase> <phrase role="identifier">to</phrase> <phrase role="identifier">main</phrase><phrase role="special">()</phrase>
|
|
<phrase role="identifier">Done</phrase>
|
|
</programlisting>
|
|
<important>
|
|
<para>
|
|
Call <emphasis>context::start()</emphasis> only on the first context in a
|
|
chain.
|
|
</para>
|
|
</important>
|
|
<anchor id="context.context.stack_unwinding"/>
|
|
<bridgehead renderas="sect3">
|
|
<link linkend="context.context.stack_unwinding">Stack unwinding</link>
|
|
</bridgehead>
|
|
<para>
|
|
Sometimes it is necessary to unwind the stack of an unfinished context to destroy
|
|
local stack variables so they can release allocated resources (RAII pattern).
|
|
The next to last argument of the context constructor, <code><phrase role="identifier">do_unwind</phrase></code>,
|
|
indicates whether the destructor should unwind the stack. Stack unwinding can
|
|
also be triggered by calling <emphasis>context::unwind_stack()</emphasis>.
|
|
</para>
|
|
<para>
|
|
Stack unwinding assumes the following preconditions:
|
|
</para>
|
|
<itemizedlist>
|
|
<listitem>
|
|
<simpara>
|
|
The context is not <emphasis>not-a-context</emphasis>
|
|
</simpara>
|
|
</listitem>
|
|
<listitem>
|
|
<simpara>
|
|
The context is not complete
|
|
</simpara>
|
|
</listitem>
|
|
<listitem>
|
|
<simpara>
|
|
The context is not running
|
|
</simpara>
|
|
</listitem>
|
|
<listitem>
|
|
<simpara>
|
|
The context owns a stack
|
|
</simpara>
|
|
</listitem>
|
|
</itemizedlist>
|
|
<para>
|
|
After unwinding, a <link linkend="context.context.context"><emphasis>context</emphasis></link>
|
|
is complete.
|
|
</para>
|
|
|
|
<programlisting><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">contexts</phrase><phrase role="special">::</phrase><phrase role="identifier">context</phrase> <phrase role="identifier">ctx</phrase><phrase role="special">;</phrase>
|
|
|
|
<phrase role="keyword">struct</phrase> <phrase role="identifier">X</phrase>
|
|
<phrase role="special">{</phrase>
|
|
<phrase role="identifier">X</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">"X()"</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="special">}</phrase>
|
|
|
|
<phrase role="special">~</phrase><phrase role="identifier">X</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">"~X()"</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="special">}</phrase>
|
|
<phrase role="special">};</phrase>
|
|
|
|
<phrase role="keyword">void</phrase> <phrase role="identifier">fn</phrase><phrase role="special">()</phrase>
|
|
<phrase role="special">{</phrase>
|
|
<phrase role="identifier">X</phrase> <phrase role="identifier">x</phrase><phrase role="special">;</phrase>
|
|
|
|
<phrase role="keyword">for</phrase><phrase role="special">(</phrase> <phrase role="keyword">int</phrase> <phrase role="identifier">i</phrase> <phrase role="special">=</phrase> <phrase role="number">0</phrase><phrase role="special">;;</phrase> <phrase role="special">++</phrase><phrase role="identifier">i</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">"fn(): "</phrase> <phrase role="special"><<</phrase> <phrase role="identifier">i</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="comment">// transfer execution control back to main()
|
|
</phrase> <phrase role="identifier">ctx</phrase><phrase role="special">.</phrase><phrase role="identifier">suspend</phrase><phrase role="special">();</phrase>
|
|
<phrase role="special">}</phrase>
|
|
<phrase role="special">}</phrase>
|
|
|
|
<phrase role="keyword">int</phrase> <phrase role="identifier">main</phrase><phrase role="special">(</phrase> <phrase role="keyword">int</phrase> <phrase role="identifier">argc</phrase><phrase role="special">,</phrase> <phrase role="keyword">char</phrase> <phrase role="special">*</phrase> <phrase role="identifier">argv</phrase><phrase role="special">[])</phrase>
|
|
<phrase role="special">{</phrase>
|
|
<phrase role="identifier">ctx</phrase> <phrase role="special">=</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">contexts</phrase><phrase role="special">::</phrase><phrase role="identifier">context</phrase><phrase role="special">(</phrase>
|
|
<phrase role="identifier">fn</phrase><phrase role="special">,</phrase>
|
|
<phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">contexts</phrase><phrase role="special">::</phrase><phrase role="identifier">default_stacksize</phrase><phrase role="special">(),</phrase>
|
|
<phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">contexts</phrase><phrase role="special">::</phrase><phrase role="identifier">no_stack_unwind</phrase><phrase role="special">,</phrase>
|
|
<phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">contexts</phrase><phrase role="special">::</phrase><phrase role="identifier">return_to_caller</phrase><phrase role="special">);</phrase>
|
|
<phrase role="identifier">ctx</phrase><phrase role="special">.</phrase><phrase role="identifier">start</phrase><phrase role="special">();</phrase>
|
|
<phrase role="keyword">for</phrase> <phrase role="special">(</phrase> <phrase role="keyword">int</phrase> <phrase role="identifier">i</phrase> <phrase role="special">=</phrase> <phrase role="number">0</phrase><phrase role="special">;</phrase> <phrase role="identifier">i</phrase> <phrase role="special"><</phrase> <phrase role="number">5</phrase><phrase role="special">;</phrase> <phrase role="special">++</phrase><phrase role="identifier">i</phrase><phrase role="special">)</phrase>
|
|
<phrase role="special">{</phrase>
|
|
<phrase role="comment">// transfer execution control to fn()
|
|
</phrase> <phrase role="identifier">ctx</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">cout</phrase> <phrase role="special"><<</phrase> <phrase role="string">"ctx is complete: "</phrase> <phrase role="special"><<</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">boolalpha</phrase> <phrase role="special"><<</phrase> <phrase role="identifier">ctx</phrase><phrase role="special">.</phrase><phrase role="identifier">is_complete</phrase><phrase role="special">()</phrase> <phrase role="special"><<</phrase> <phrase role="string">"\n"</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">"call ctx.unwind_stack()"</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="comment">// unwind the stack
|
|
</phrase> <phrase role="comment">// X::~X() will be called
|
|
</phrase> <phrase role="identifier">ctx</phrase><phrase role="special">.</phrase><phrase role="identifier">unwind_stack</phrase><phrase role="special">();</phrase> <phrase role="comment">// unwind the stack
|
|
</phrase>
|
|
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cout</phrase> <phrase role="special"><<</phrase> <phrase role="string">"ctx is complete: "</phrase> <phrase role="special"><<</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">boolalpha</phrase> <phrase role="special"><<</phrase> <phrase role="identifier">ctx</phrase><phrase role="special">.</phrase><phrase role="identifier">is_complete</phrase><phrase role="special">()</phrase> <phrase role="special"><<</phrase> <phrase role="string">"\n"</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">"Done"</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">EXIT_SUCCESS</phrase><phrase role="special">;</phrase>
|
|
<phrase role="special">}</phrase>
|
|
|
|
<phrase role="identifier">output</phrase><phrase role="special">:</phrase>
|
|
<phrase role="identifier">X</phrase><phrase role="special">()</phrase>
|
|
<phrase role="identifier">fn</phrase><phrase role="special">():</phrase> <phrase role="number">0</phrase>
|
|
<phrase role="identifier">fn</phrase><phrase role="special">():</phrase> <phrase role="number">1</phrase>
|
|
<phrase role="identifier">fn</phrase><phrase role="special">():</phrase> <phrase role="number">2</phrase>
|
|
<phrase role="identifier">fn</phrase><phrase role="special">():</phrase> <phrase role="number">3</phrase>
|
|
<phrase role="identifier">fn</phrase><phrase role="special">():</phrase> <phrase role="number">4</phrase>
|
|
<phrase role="identifier">fn</phrase><phrase role="special">():</phrase> <phrase role="number">5</phrase>
|
|
<phrase role="identifier">ctx</phrase> <phrase role="identifier">is</phrase> <phrase role="identifier">complete</phrase><phrase role="special">:</phrase> <phrase role="keyword">false</phrase>
|
|
<phrase role="identifier">call</phrase> <phrase role="identifier">ctx</phrase><phrase role="special">.</phrase><phrase role="identifier">unwind_stack</phrase><phrase role="special">()</phrase>
|
|
<phrase role="special">~</phrase><phrase role="identifier">X</phrase><phrase role="special">()</phrase>
|
|
<phrase role="identifier">ctx</phrase> <phrase role="identifier">is</phrase> <phrase role="identifier">complete</phrase><phrase role="special">:</phrase> <phrase role="keyword">true</phrase>
|
|
<phrase role="identifier">Done</phrase>
|
|
</programlisting>
|
|
<important>
|
|
<para>
|
|
You must not swallow <emphasis>forced_unwind</emphasis> exceptions!
|
|
</para>
|
|
</important>
|
|
<section id="context.context.context">
|
|
<title><link linkend="context.context.context">Class <code><phrase role="identifier">context</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">context</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">></phrase>
|
|
|
|
<phrase role="keyword">class</phrase> <phrase role="identifier">context</phrase>
|
|
<phrase role="special">{</phrase>
|
|
<phrase role="keyword">public</phrase><phrase role="special">:</phrase>
|
|
<phrase role="identifier">context</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">context</phrase><phrase role="special">(</phrase> <phrase role="identifier">Fn</phrase> <phrase role="identifier">fn</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">flag_unwind_t</phrase> <phrase role="identifier">do_unwind</phrase><phrase role="special">,</phrase> <phrase role="identifier">flag_return_t</phrase> <phrase role="identifier">do_return</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="keyword">typename</phrase> <phrase role="identifier">Allocator</phrase> <phrase role="special">></phrase>
|
|
<phrase role="identifier">context</phrase><phrase role="special">(</phrase> <phrase role="identifier">Fn</phrase> <phrase role="identifier">fn</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">flag_unwind_t</phrase> <phrase role="identifier">do_unwind</phrase><phrase role="special">,</phrase> <phrase role="identifier">flag_return_t</phrase> <phrase role="identifier">do_return</phrase><phrase role="special">,</phrase> <phrase role="identifier">Allocator</phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">alloc</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">context</phrase><phrase role="special">(</phrase> <phrase role="identifier">Fn</phrase> <phrase role="identifier">fn</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">flag_unwind_t</phrase> <phrase role="identifier">do_unwind</phrase><phrase role="special">,</phrase> <phrase role="identifier">context</phrase> <phrase role="special">&</phrase> <phrase role="identifier">nxt</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="keyword">typename</phrase> <phrase role="identifier">Allocator</phrase> <phrase role="special">></phrase>
|
|
<phrase role="identifier">context</phrase><phrase role="special">(</phrase> <phrase role="identifier">Fn</phrase> <phrase role="identifier">fn</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">flag_unwind_t</phrase> <phrase role="identifier">do_unwind</phrase><phrase role="special">,</phrase> <phrase role="identifier">context</phrase> <phrase role="special">&</phrase> <phrase role="identifier">nxt</phrase><phrase role="special">,</phrase> <phrase role="identifier">Allocator</phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">alloc</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="keyword">typename</phrase> <phrase role="identifier">A0</phrase> <phrase role="special">></phrase>
|
|
<phrase role="identifier">context</phrase><phrase role="special">(</phrase> <phrase role="identifier">Fn</phrase> <phrase role="identifier">fn</phrase> <phrase role="identifier">A0</phrase> <phrase role="identifier">a0</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">flag_unwind_t</phrase> <phrase role="identifier">do_unwind</phrase><phrase role="special">,</phrase> <phrase role="identifier">flag_return_t</phrase> <phrase role="identifier">do_return</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="keyword">typename</phrase> <phrase role="identifier">A0</phrase><phrase role="special">,...,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">A9</phrase> <phrase role="special">></phrase>
|
|
<phrase role="identifier">context</phrase><phrase role="special">(</phrase> <phrase role="identifier">Fn</phrase> <phrase role="identifier">fn</phrase> <phrase role="identifier">A0</phrase> <phrase role="identifier">a0</phrase><phrase role="special">,...,</phrase> <phrase role="identifier">A9</phrase><phrase role="special">,</phrase> <phrase role="identifier">a9</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">flag_unwind_t</phrase> <phrase role="identifier">do_unwind</phrase><phrase role="special">,</phrase> <phrase role="identifier">flag_return_t</phrase> <phrase role="identifier">do_return</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="keyword">typename</phrase> <phrase role="identifier">Allocator</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">A0</phrase> <phrase role="special">></phrase>
|
|
<phrase role="identifier">context</phrase><phrase role="special">(</phrase> <phrase role="identifier">Fn</phrase> <phrase role="identifier">fn</phrase> <phrase role="identifier">A0</phrase> <phrase role="identifier">a0</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">flag_unwind_t</phrase> <phrase role="identifier">do_unwind</phrase><phrase role="special">,</phrase> <phrase role="identifier">flag_return_t</phrase> <phrase role="identifier">do_return</phrase><phrase role="special">,</phrase> <phrase role="identifier">Allocator</phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">alloc</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="keyword">typename</phrase> <phrase role="identifier">Allocator</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">A0</phrase><phrase role="special">,...,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">A9</phrase> <phrase role="special">></phrase>
|
|
<phrase role="identifier">context</phrase><phrase role="special">(</phrase> <phrase role="identifier">Fn</phrase> <phrase role="identifier">fn</phrase> <phrase role="identifier">A0</phrase> <phrase role="identifier">a0</phrase><phrase role="special">,...,</phrase> <phrase role="identifier">A9</phrase><phrase role="special">,</phrase> <phrase role="identifier">a9</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">flag_unwind_t</phrase> <phrase role="identifier">do_unwind</phrase><phrase role="special">,</phrase> <phrase role="identifier">flag_return_t</phrase> <phrase role="identifier">do_return</phrase><phrase role="special">,</phrase> <phrase role="identifier">Allocator</phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">alloc</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="keyword">typename</phrase> <phrase role="identifier">A0</phrase> <phrase role="special">></phrase>
|
|
<phrase role="identifier">context</phrase><phrase role="special">(</phrase> <phrase role="identifier">Fn</phrase> <phrase role="identifier">fn</phrase> <phrase role="identifier">A0</phrase> <phrase role="identifier">a0</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">flag_unwind_t</phrase> <phrase role="identifier">do_unwind</phrase><phrase role="special">,</phrase> <phrase role="identifier">context</phrase> <phrase role="special">&</phrase> <phrase role="identifier">nxt</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="keyword">typename</phrase> <phrase role="identifier">A0</phrase><phrase role="special">,...,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">A9</phrase> <phrase role="special">></phrase>
|
|
<phrase role="identifier">context</phrase><phrase role="special">(</phrase> <phrase role="identifier">Fn</phrase> <phrase role="identifier">fn</phrase> <phrase role="identifier">A0</phrase> <phrase role="identifier">a0</phrase><phrase role="special">,...,</phrase> <phrase role="identifier">A9</phrase><phrase role="special">,</phrase> <phrase role="identifier">a9</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">flag_unwind_t</phrase> <phrase role="identifier">do_unwind</phrase><phrase role="special">,</phrase> <phrase role="identifier">context</phrase> <phrase role="special">&</phrase> <phrase role="identifier">nxt</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="keyword">typename</phrase> <phrase role="identifier">Allocator</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">A0</phrase> <phrase role="special">></phrase>
|
|
<phrase role="identifier">context</phrase><phrase role="special">(</phrase> <phrase role="identifier">Fn</phrase> <phrase role="identifier">fn</phrase> <phrase role="identifier">A0</phrase> <phrase role="identifier">a0</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">flag_unwind_t</phrase> <phrase role="identifier">do_unwind</phrase><phrase role="special">,</phrase> <phrase role="identifier">context</phrase> <phrase role="special">&</phrase> <phrase role="identifier">nxt</phrase><phrase role="special">,</phrase> <phrase role="identifier">Allocator</phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">alloc</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="keyword">typename</phrase> <phrase role="identifier">Allocator</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">A0</phrase><phrase role="special">,...,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">A9</phrase> <phrase role="special">></phrase>
|
|
<phrase role="identifier">context</phrase><phrase role="special">(</phrase> <phrase role="identifier">Fn</phrase> <phrase role="identifier">fn</phrase> <phrase role="identifier">A0</phrase> <phrase role="identifier">a0</phrase><phrase role="special">,...,</phrase> <phrase role="identifier">A9</phrase><phrase role="special">,</phrase> <phrase role="identifier">a9</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">flag_unwind_t</phrase> <phrase role="identifier">do_unwind</phrase><phrase role="special">,</phrase> <phrase role="identifier">context</phrase> <phrase role="special">&</phrase> <phrase role="identifier">nxt</phrase><phrase role="special">,</phrase> <phrase role="identifier">Allocator</phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">alloc</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">context</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="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">flag_unwind_t</phrase> <phrase role="identifier">do_unwind</phrase><phrase role="special">,</phrase> <phrase role="identifier">flag_return_t</phrase> <phrase role="identifier">do_return</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="keyword">typename</phrase> <phrase role="identifier">Allocator</phrase> <phrase role="special">></phrase>
|
|
<phrase role="identifier">context</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="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">flag_unwind_t</phrase> <phrase role="identifier">do_unwind</phrase><phrase role="special">,</phrase> <phrase role="identifier">flag_return_t</phrase> <phrase role="identifier">do_return</phrase><phrase role="special">,</phrase> <phrase role="identifier">Allocator</phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">alloc</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">context</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="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">flag_unwind_t</phrase> <phrase role="identifier">do_unwind</phrase><phrase role="special">,</phrase> <phrase role="identifier">context</phrase> <phrase role="special">&</phrase> <phrase role="identifier">nxt</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="keyword">typename</phrase> <phrase role="identifier">Allocator</phrase> <phrase role="special">></phrase>
|
|
<phrase role="identifier">context</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="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">flag_unwind_t</phrase> <phrase role="identifier">do_unwind</phrase><phrase role="special">,</phrase> <phrase role="identifier">context</phrase> <phrase role="special">&</phrase> <phrase role="identifier">nxt</phrase><phrase role="special">,</phrase> <phrase role="identifier">Allocator</phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">alloc</phrase><phrase role="special">);</phrase>
|
|
|
|
<phrase role="special">~</phrase><phrase role="identifier">context</phrase><phrase role="special">();</phrase>
|
|
|
|
<phrase role="identifier">context</phrase><phrase role="special">(</phrase> <phrase role="identifier">context</phrase> <phrase role="special">&&</phrase> <phrase role="identifier">other</phrase><phrase role="special">);</phrase>
|
|
|
|
<phrase role="identifier">context</phrase> <phrase role="special">&</phrase> <phrase role="keyword">operator</phrase><phrase role="special">=(</phrase> <phrase role="identifier">context</phrase> <phrase role="special">&&</phrase> <phrase role="identifier">other</phrase><phrase role="special">);</phrase>
|
|
|
|
<phrase role="keyword">operator</phrase> <phrase role="identifier">unspecified</phrase><phrase role="special">-</phrase><phrase role="keyword">bool</phrase><phrase role="special">-</phrase><phrase role="identifier">type</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</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="special">;</phrase>
|
|
|
|
<phrase role="keyword">void</phrase> <phrase role="identifier">swap</phrase><phrase role="special">(</phrase> <phrase role="identifier">context</phrase> <phrase role="special">&</phrase> <phrase role="identifier">other</phrase><phrase role="special">);</phrase>
|
|
|
|
<phrase role="keyword">bool</phrase> <phrase role="identifier">is_complete</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
|
|
|
|
<phrase role="keyword">bool</phrase> <phrase role="identifier">is_running</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
|
|
|
|
<phrase role="identifier">intptr_t</phrase> <phrase role="identifier">start</phrase><phrase role="special">();</phrase>
|
|
|
|
<phrase role="identifier">intptr_t</phrase> <phrase role="identifier">resume</phrase><phrase role="special">(</phrase> <phrase role="identifier">intptr_t</phrase> <phrase role="identifier">vp</phrase> <phrase role="special">=</phrase> <phrase role="number">0</phrase><phrase role="special">);</phrase>
|
|
|
|
<phrase role="identifier">intptr_t</phrase> <phrase role="identifier">suspend</phrase><phrase role="special">(</phrase> <phrase role="identifier">intptr_t</phrase> <phrase role="identifier">vp</phrase> <phrase role="special">=</phrase> <phrase role="number">0</phrase><phrase role="special">);</phrase>
|
|
|
|
<phrase role="keyword">void</phrase> <phrase role="identifier">unwind_stack</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">context</phrase> <phrase role="special">&</phrase> <phrase role="identifier">l</phrase><phrase role="special">,</phrase> <phrase role="identifier">context</phrase> <phrase role="special">&</phrase> <phrase role="identifier">r</phrase><phrase role="special">);</phrase>
|
|
</programlisting>
|
|
<anchor id="context.context.context._code__phrase_role__identifier__context__phrase__phrase_role__special______phrase___code_"/>
|
|
<bridgehead renderas="sect4">
|
|
<link linkend="context.context.context._code__phrase_role__identifier__context__phrase__phrase_role__special______phrase___code_"><code><phrase
|
|
role="identifier">context</phrase><phrase role="special">()</phrase></code></link>
|
|
</bridgehead>
|
|
<variablelist>
|
|
<title></title>
|
|
<varlistentry>
|
|
<term>Effects:</term>
|
|
<listitem>
|
|
<para>
|
|
Creates a context representing a <emphasis>not-a-context</emphasis>.
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
<varlistentry>
|
|
<term>Throws:</term>
|
|
<listitem>
|
|
<para>
|
|
Nothing.
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
</variablelist>
|
|
<anchor id="context.context.context._code__phrase_role__keyword__template__phrase__phrase_role__special___lt___phrase___phrase_role__keyword__typename__phrase___phrase_role__identifier__fn__phrase___phrase_role__special___gt___phrase___phrase_role__identifier__context__phrase__phrase_role__special_____phrase___phrase_role__identifier__fn__phrase___phrase_role__identifier__fn__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__flag_unwind_t__phrase___phrase_role__identifier__do_unwind__phrase__phrase_role__special_____phrase___phrase_role__identifier__flag_return_t__phrase___phrase_role__identifier__do_return__phrase__phrase_role__special_____phrase___code_"/>
|
|
<bridgehead renderas="sect4">
|
|
<link linkend="context.context.context._code__phrase_role__keyword__template__phrase__phrase_role__special___lt___phrase___phrase_role__keyword__typename__phrase___phrase_role__identifier__fn__phrase___phrase_role__special___gt___phrase___phrase_role__identifier__context__phrase__phrase_role__special_____phrase___phrase_role__identifier__fn__phrase___phrase_role__identifier__fn__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__flag_unwind_t__phrase___phrase_role__identifier__do_unwind__phrase__phrase_role__special_____phrase___phrase_role__identifier__flag_return_t__phrase___phrase_role__identifier__do_return__phrase__phrase_role__special_____phrase___code_"><code><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">context</phrase><phrase
|
|
role="special">(</phrase> <phrase role="identifier">Fn</phrase> <phrase role="identifier">fn</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">flag_unwind_t</phrase>
|
|
<phrase role="identifier">do_unwind</phrase><phrase role="special">,</phrase>
|
|
<phrase role="identifier">flag_return_t</phrase> <phrase role="identifier">do_return</phrase><phrase
|
|
role="special">)</phrase></code></link>
|
|
</bridgehead>
|
|
<variablelist>
|
|
<title></title>
|
|
<varlistentry>
|
|
<term>Preconditions:</term>
|
|
<listitem>
|
|
<para>
|
|
<code><phrase role="identifier">size</phrase></code> > minimum_stacksize(),
|
|
<code><phrase role="identifier">size</phrase></code> < maximum_stacksize()
|
|
when ! is_stack_unbound().
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
<varlistentry>
|
|
<term>Effects:</term>
|
|
<listitem>
|
|
<para>
|
|
Creates a context which will execute <code><phrase role="identifier">fn</phrase></code>.
|
|
If <code><phrase role="identifier">do_unwind</phrase></code> is <code><phrase
|
|
role="identifier">stack_unwind</phrase></code> the destructor of <code><phrase
|
|
role="special">*</phrase><phrase role="keyword">this</phrase></code>
|
|
unwinds the stack before destructing it. If <code><phrase role="identifier">do_return</phrase></code>
|
|
is <code><phrase role="identifier">exit_application</phrase></code>
|
|
the application exits with return code <code><phrase role="number">0</phrase></code>,
|
|
otherwise execution control is transfered back to the invoker (<code><phrase
|
|
role="identifier">resume</phrase><phrase role="special">()</phrase></code>
|
|
returns).
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
<varlistentry>
|
|
<term>Throws:</term>
|
|
<listitem>
|
|
<para>
|
|
<emphasis>std::invalid_argument</emphasis> if a precondition is not
|
|
satisfied.
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
</variablelist>
|
|
<anchor id="context.context.context._code__phrase_role__keyword__template__phrase__phrase_role__special___lt___phrase___phrase_role__keyword__typename__phrase___phrase_role__identifier__fn__phrase__phrase_role__special_____phrase___phrase_role__keyword__typename__phrase___phrase_role__identifier__allocator__phrase___phrase_role__special___gt___phrase___phrase_role__identifier__context__phrase__phrase_role__special_____phrase___phrase_role__identifier__fn__phrase___phrase_role__identifier__fn__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__flag_unwind_t__phrase___phrase_role__identifier__do_unwind__phrase__phrase_role__special_____phrase___phrase_role__identifier__flag_return_t__phrase___phrase_role__identifier__do_return__phrase__phrase_role__special_____phrase___phrase_role__identifier__allocator__phrase___phrase_role__keyword__const__phrase__phrase_role__special___amp___phrase___phrase_role__identifier__alloc__phrase__phrase_role__special_____phrase___code_"/>
|
|
<bridgehead renderas="sect4">
|
|
<link linkend="context.context.context._code__phrase_role__keyword__template__phrase__phrase_role__special___lt___phrase___phrase_role__keyword__typename__phrase___phrase_role__identifier__fn__phrase__phrase_role__special_____phrase___phrase_role__keyword__typename__phrase___phrase_role__identifier__allocator__phrase___phrase_role__special___gt___phrase___phrase_role__identifier__context__phrase__phrase_role__special_____phrase___phrase_role__identifier__fn__phrase___phrase_role__identifier__fn__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__flag_unwind_t__phrase___phrase_role__identifier__do_unwind__phrase__phrase_role__special_____phrase___phrase_role__identifier__flag_return_t__phrase___phrase_role__identifier__do_return__phrase__phrase_role__special_____phrase___phrase_role__identifier__allocator__phrase___phrase_role__keyword__const__phrase__phrase_role__special___amp___phrase___phrase_role__identifier__alloc__phrase__phrase_role__special_____phrase___code_"><code><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="keyword">typename</phrase> <phrase
|
|
role="identifier">Allocator</phrase> <phrase role="special">></phrase>
|
|
<phrase role="identifier">context</phrase><phrase role="special">(</phrase>
|
|
<phrase role="identifier">Fn</phrase> <phrase role="identifier">fn</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">flag_unwind_t</phrase>
|
|
<phrase role="identifier">do_unwind</phrase><phrase role="special">,</phrase>
|
|
<phrase role="identifier">flag_return_t</phrase> <phrase role="identifier">do_return</phrase><phrase
|
|
role="special">,</phrase> <phrase role="identifier">Allocator</phrase> <phrase
|
|
role="keyword">const</phrase><phrase role="special">&</phrase> <phrase
|
|
role="identifier">alloc</phrase><phrase role="special">)</phrase></code></link>
|
|
</bridgehead>
|
|
<variablelist>
|
|
<title></title>
|
|
<varlistentry>
|
|
<term>Effects:</term>
|
|
<listitem>
|
|
<para>
|
|
Creates a context which will execute <code><phrase role="identifier">fn</phrase></code>.
|
|
If <code><phrase role="identifier">do_unwind</phrase></code> is <code><phrase
|
|
role="identifier">stack_unwind</phrase></code> the destructor of <code><phrase
|
|
role="special">*</phrase><phrase role="keyword">this</phrase></code>
|
|
unwinds the stack before destructing it. If <code><phrase role="identifier">do_return</phrase></code>
|
|
is <code><phrase role="identifier">exit_application</phrase></code>
|
|
the application exits with return code <code><phrase role="number">0</phrase></code>,
|
|
otherwise execution control is transfered back to the invoker (<code><phrase
|
|
role="identifier">resume</phrase><phrase role="special">()</phrase></code>
|
|
returns).
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
<varlistentry>
|
|
<term>Throws:</term>
|
|
<listitem>
|
|
<para>
|
|
depends on <code><phrase role="identifier">alloc</phrase></code> if
|
|
a precondition is not satisfied.
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
</variablelist>
|
|
<anchor id="context.context.context._code__phrase_role__keyword__template__phrase__phrase_role__special___lt___phrase___phrase_role__keyword__typename__phrase___phrase_role__identifier__fn__phrase___phrase_role__special___gt___phrase___phrase_role__identifier__context__phrase__phrase_role__special_____phrase___phrase_role__identifier__fn__phrase___phrase_role__identifier__fn__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__flag_unwind_t__phrase___phrase_role__identifier__do_unwind__phrase__phrase_role__special_____phrase___phrase_role__identifier__context__phrase___phrase_role__special___amp___phrase___phrase_role__identifier__nxt__phrase__phrase_role__special_____phrase___code_"/>
|
|
<bridgehead renderas="sect4">
|
|
<link linkend="context.context.context._code__phrase_role__keyword__template__phrase__phrase_role__special___lt___phrase___phrase_role__keyword__typename__phrase___phrase_role__identifier__fn__phrase___phrase_role__special___gt___phrase___phrase_role__identifier__context__phrase__phrase_role__special_____phrase___phrase_role__identifier__fn__phrase___phrase_role__identifier__fn__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__flag_unwind_t__phrase___phrase_role__identifier__do_unwind__phrase__phrase_role__special_____phrase___phrase_role__identifier__context__phrase___phrase_role__special___amp___phrase___phrase_role__identifier__nxt__phrase__phrase_role__special_____phrase___code_"><code><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">context</phrase><phrase
|
|
role="special">(</phrase> <phrase role="identifier">Fn</phrase> <phrase role="identifier">fn</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">flag_unwind_t</phrase>
|
|
<phrase role="identifier">do_unwind</phrase><phrase role="special">,</phrase>
|
|
<phrase role="identifier">context</phrase> <phrase role="special">&</phrase>
|
|
<phrase role="identifier">nxt</phrase><phrase role="special">)</phrase></code></link>
|
|
</bridgehead>
|
|
<variablelist>
|
|
<title></title>
|
|
<varlistentry>
|
|
<term>Preconditions:</term>
|
|
<listitem>
|
|
<para>
|
|
<code><phrase role="identifier">size</phrase></code> > minimum_stacksize(),
|
|
<code><phrase role="identifier">size</phrase></code> < maximum_stacksize()
|
|
when ! is_stack_unbound(), <code><phrase role="identifier">nxt</phrase></code>
|
|
is not a <emphasis>not-a-context</emphasis>.
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
<varlistentry>
|
|
<term>Effects:</term>
|
|
<listitem>
|
|
<para>
|
|
Creates a context which will execute <code><phrase role="identifier">fn</phrase></code>.
|
|
If <code><phrase role="identifier">do_unwind</phrase></code> is <code><phrase
|
|
role="identifier">stack_unwind</phrase></code> the destructor of <code><phrase
|
|
role="special">*</phrase><phrase role="keyword">this</phrase></code>
|
|
unwinds the stack before destructing it. execution control is transfered
|
|
to <code><phrase role="identifier">nxt</phrase></code> if <code><phrase
|
|
role="identifier">fn</phrase></code> returns (<code><phrase role="identifier">nxt</phrase></code>
|
|
is linked).
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
<varlistentry>
|
|
<term>Throws:</term>
|
|
<listitem>
|
|
<para>
|
|
<emphasis>std::invalid_argument</emphasis> if a precondition is not
|
|
satisfied.
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
</variablelist>
|
|
<anchor id="context.context.context._code__phrase_role__keyword__template__phrase__phrase_role__special___lt___phrase___phrase_role__keyword__typename__phrase___phrase_role__identifier__fn__phrase__phrase_role__special_____phrase___phrase_role__keyword__typename__phrase___phrase_role__identifier__allocator__phrase___phrase_role__special___gt___phrase___phrase_role__identifier__context__phrase__phrase_role__special_____phrase___phrase_role__identifier__fn__phrase___phrase_role__identifier__fn__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__flag_unwind_t__phrase___phrase_role__identifier__do_unwind__phrase__phrase_role__special_____phrase___phrase_role__identifier__context__phrase___phrase_role__special___amp___phrase___phrase_role__identifier__nxt__phrase__phrase_role__special_____phrase___phrase_role__identifier__allocatorconst__phrase__phrase_role__special___amp___phrase___phrase_role__identifier__alloc__phrase__phrase_role__special_____phrase___code_"/>
|
|
<bridgehead renderas="sect4">
|
|
<link linkend="context.context.context._code__phrase_role__keyword__template__phrase__phrase_role__special___lt___phrase___phrase_role__keyword__typename__phrase___phrase_role__identifier__fn__phrase__phrase_role__special_____phrase___phrase_role__keyword__typename__phrase___phrase_role__identifier__allocator__phrase___phrase_role__special___gt___phrase___phrase_role__identifier__context__phrase__phrase_role__special_____phrase___phrase_role__identifier__fn__phrase___phrase_role__identifier__fn__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__flag_unwind_t__phrase___phrase_role__identifier__do_unwind__phrase__phrase_role__special_____phrase___phrase_role__identifier__context__phrase___phrase_role__special___amp___phrase___phrase_role__identifier__nxt__phrase__phrase_role__special_____phrase___phrase_role__identifier__allocatorconst__phrase__phrase_role__special___amp___phrase___phrase_role__identifier__alloc__phrase__phrase_role__special_____phrase___code_"><code><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="keyword">typename</phrase> <phrase
|
|
role="identifier">Allocator</phrase> <phrase role="special">></phrase>
|
|
<phrase role="identifier">context</phrase><phrase role="special">(</phrase>
|
|
<phrase role="identifier">Fn</phrase> <phrase role="identifier">fn</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">flag_unwind_t</phrase>
|
|
<phrase role="identifier">do_unwind</phrase><phrase role="special">,</phrase>
|
|
<phrase role="identifier">context</phrase> <phrase role="special">&</phrase>
|
|
<phrase role="identifier">nxt</phrase><phrase role="special">,</phrase>
|
|
<phrase role="identifier">Allocatorconst</phrase><phrase role="special">&</phrase>
|
|
<phrase role="identifier">alloc</phrase><phrase role="special">)</phrase></code></link>
|
|
</bridgehead>
|
|
<variablelist>
|
|
<title></title>
|
|
<varlistentry>
|
|
<term>Preconditions:</term>
|
|
<listitem>
|
|
<para>
|
|
<code><phrase role="identifier">nxt</phrase></code> is not a <emphasis>not-a-context</emphasis>.
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
<varlistentry>
|
|
<term>Effects:</term>
|
|
<listitem>
|
|
<para>
|
|
Creates a context which will execute <code><phrase role="identifier">fn</phrase></code>.
|
|
If <code><phrase role="identifier">do_unwind</phrase></code> is <code><phrase
|
|
role="identifier">stack_unwind</phrase></code> the destructor of <code><phrase
|
|
role="special">*</phrase><phrase role="keyword">this</phrase></code>
|
|
unwinds the stack before destructing it. execution control is transfered
|
|
to <code><phrase role="identifier">nxt</phrase></code> if <code><phrase
|
|
role="identifier">fn</phrase></code> returns (<code><phrase role="identifier">nxt</phrase></code>
|
|
is linked).
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
<varlistentry>
|
|
<term>Throws:</term>
|
|
<listitem>
|
|
<para>
|
|
depends on <code><phrase role="identifier">alloc</phrase></code> if
|
|
a precondition is not satisfied.
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
</variablelist>
|
|
<anchor id="context.context.context._code__phrase_role__keyword__template__phrase__phrase_role__special___lt___phrase___phrase_role__keyword__typename__phrase___phrase_role__identifier__fn__phrase__phrase_role__special_____phrase___phrase_role__keyword__typename__phrase___phrase_role__identifier__a0__phrase__phrase_role__special________phrase___phrase_role__special___gt___phrase___phrase_role__identifier__context__phrase__phrase_role__special_____phrase___phrase_role__identifier__fn__phrase___phrase_role__identifier__fn__phrase__phrase_role__special_____phrase___phrase_role__identifier__a0__phrase___phrase_role__identifier__a0__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__flag_unwind_t__phrase___phrase_role__identifier__do_unwind__phrase__phrase_role__special_____phrase___phrase_role__identifier__flag_return_t__phrase___phrase_role__identifier__do_return__phrase__phrase_role__special_____phrase___code_"/>
|
|
<bridgehead renderas="sect4">
|
|
<link linkend="context.context.context._code__phrase_role__keyword__template__phrase__phrase_role__special___lt___phrase___phrase_role__keyword__typename__phrase___phrase_role__identifier__fn__phrase__phrase_role__special_____phrase___phrase_role__keyword__typename__phrase___phrase_role__identifier__a0__phrase__phrase_role__special________phrase___phrase_role__special___gt___phrase___phrase_role__identifier__context__phrase__phrase_role__special_____phrase___phrase_role__identifier__fn__phrase___phrase_role__identifier__fn__phrase__phrase_role__special_____phrase___phrase_role__identifier__a0__phrase___phrase_role__identifier__a0__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__flag_unwind_t__phrase___phrase_role__identifier__do_unwind__phrase__phrase_role__special_____phrase___phrase_role__identifier__flag_return_t__phrase___phrase_role__identifier__do_return__phrase__phrase_role__special_____phrase___code_"><code><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="keyword">typename</phrase> <phrase
|
|
role="identifier">A0</phrase><phrase role="special">,...</phrase> <phrase
|
|
role="special">></phrase> <phrase role="identifier">context</phrase><phrase
|
|
role="special">(</phrase> <phrase role="identifier">Fn</phrase> <phrase role="identifier">fn</phrase><phrase
|
|
role="special">,</phrase> <phrase role="identifier">A0</phrase> <phrase role="identifier">a0</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">flag_unwind_t</phrase> <phrase role="identifier">do_unwind</phrase><phrase
|
|
role="special">,</phrase> <phrase role="identifier">flag_return_t</phrase>
|
|
<phrase role="identifier">do_return</phrase><phrase role="special">)</phrase></code></link>
|
|
</bridgehead>
|
|
<variablelist>
|
|
<title></title>
|
|
<varlistentry>
|
|
<term>Preconditions:</term>
|
|
<listitem>
|
|
<para>
|
|
<code><phrase role="identifier">size</phrase></code> > minimum_stacksize(),
|
|
<code><phrase role="identifier">size</phrase></code> < maximum_stacksize()
|
|
when ! is_stack_unbound().
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
<varlistentry>
|
|
<term>Effects:</term>
|
|
<listitem>
|
|
<para>
|
|
Creates a context which will execute <code><phrase role="identifier">fn</phrase></code>
|
|
(arguments <code><phrase role="identifier">A0</phrase></code>,... are
|
|
bound to <code><phrase role="identifier">fn</phrase></code>). If <code><phrase
|
|
role="identifier">do_unwind</phrase></code> is <code><phrase role="identifier">stack_unwind</phrase></code>
|
|
the destructor of <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>
|
|
unwinds the stack before destructing it. If <code><phrase role="identifier">do_return</phrase></code>
|
|
is <code><phrase role="identifier">exit_application</phrase></code>
|
|
the application exits with return code <code><phrase role="number">0</phrase></code>,
|
|
otherwise execution control is transfered back to the invoker (<code><phrase
|
|
role="identifier">resume</phrase><phrase role="special">()</phrase></code>
|
|
returns).
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
<varlistentry>
|
|
<term>Throws:</term>
|
|
<listitem>
|
|
<para>
|
|
<emphasis>std::invalid_argument</emphasis> if a precondition is not
|
|
satisfied.
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
</variablelist>
|
|
<anchor id="context.context.context._code__phrase_role__keyword__template__phrase__phrase_role__special___lt___phrase___phrase_role__keyword__typename__phrase___phrase_role__identifier__fn__phrase__phrase_role__special_____phrase___phrase_role__keyword__typename__phrase___phrase_role__identifier__allocator__phrase__phrase_role__special_____phrase___phrase_role__keyword__typename__phrase___phrase_role__identifier__a0__phrase__phrase_role__special________phrase___phrase_role__special___gt___phrase___phrase_role__identifier__context__phrase__phrase_role__special_____phrase___phrase_role__identifier__fn__phrase___phrase_role__identifier__fn__phrase__phrase_role__special_____phrase___phrase_role__identifier__a0__phrase___phrase_role__identifier__a0__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__flag_unwind_t__phrase___phrase_role__identifier__do_unwind__phrase__phrase_role__special_____phrase___phrase_role__identifier__flag_return_t__phrase___phrase_role__identifier__do_return__phrase__phrase_role__special_____phrase___phrase_role__identifier__allocator__phrase___phrase_role__keyword__const__phrase__phrase_role__special___amp___phrase___phrase_role__identifier__alloc__phrase__phrase_role__special_____phrase___code_"/>
|
|
<bridgehead renderas="sect4">
|
|
<link linkend="context.context.context._code__phrase_role__keyword__template__phrase__phrase_role__special___lt___phrase___phrase_role__keyword__typename__phrase___phrase_role__identifier__fn__phrase__phrase_role__special_____phrase___phrase_role__keyword__typename__phrase___phrase_role__identifier__allocator__phrase__phrase_role__special_____phrase___phrase_role__keyword__typename__phrase___phrase_role__identifier__a0__phrase__phrase_role__special________phrase___phrase_role__special___gt___phrase___phrase_role__identifier__context__phrase__phrase_role__special_____phrase___phrase_role__identifier__fn__phrase___phrase_role__identifier__fn__phrase__phrase_role__special_____phrase___phrase_role__identifier__a0__phrase___phrase_role__identifier__a0__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__flag_unwind_t__phrase___phrase_role__identifier__do_unwind__phrase__phrase_role__special_____phrase___phrase_role__identifier__flag_return_t__phrase___phrase_role__identifier__do_return__phrase__phrase_role__special_____phrase___phrase_role__identifier__allocator__phrase___phrase_role__keyword__const__phrase__phrase_role__special___amp___phrase___phrase_role__identifier__alloc__phrase__phrase_role__special_____phrase___code_"><code><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="keyword">typename</phrase> <phrase
|
|
role="identifier">Allocator</phrase><phrase role="special">,</phrase> <phrase
|
|
role="keyword">typename</phrase> <phrase role="identifier">A0</phrase><phrase
|
|
role="special">,...</phrase> <phrase role="special">></phrase> <phrase
|
|
role="identifier">context</phrase><phrase role="special">(</phrase> <phrase
|
|
role="identifier">Fn</phrase> <phrase role="identifier">fn</phrase><phrase
|
|
role="special">,</phrase> <phrase role="identifier">A0</phrase> <phrase role="identifier">a0</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">flag_unwind_t</phrase> <phrase role="identifier">do_unwind</phrase><phrase
|
|
role="special">,</phrase> <phrase role="identifier">flag_return_t</phrase>
|
|
<phrase role="identifier">do_return</phrase><phrase role="special">,</phrase>
|
|
<phrase role="identifier">Allocator</phrase> <phrase role="keyword">const</phrase><phrase
|
|
role="special">&</phrase> <phrase role="identifier">alloc</phrase><phrase
|
|
role="special">)</phrase></code></link>
|
|
</bridgehead>
|
|
<variablelist>
|
|
<title></title>
|
|
<varlistentry>
|
|
<term>Preconditions:</term>
|
|
<listitem>
|
|
<para>
|
|
<code><phrase role="identifier">size</phrase></code> > minimum_stacksize(),
|
|
<code><phrase role="identifier">size</phrase></code> < maximum_stacksize()
|
|
when ! is_stack_unbound().
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
<varlistentry>
|
|
<term>Effects:</term>
|
|
<listitem>
|
|
<para>
|
|
Creates a context which will execute <code><phrase role="identifier">fn</phrase></code>
|
|
(arguments <code><phrase role="identifier">A0</phrase></code>,... are
|
|
bound to <code><phrase role="identifier">fn</phrase></code>). If <code><phrase
|
|
role="identifier">do_unwind</phrase></code> is <code><phrase role="identifier">stack_unwind</phrase></code>
|
|
the destructor of <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>
|
|
unwinds the stack before destructing it. If <code><phrase role="identifier">do_return</phrase></code>
|
|
is <code><phrase role="identifier">exit_application</phrase></code>
|
|
the application exits with return code <code><phrase role="number">0</phrase></code>,
|
|
otherwise execution control is transfered back to the invoker (<code><phrase
|
|
role="identifier">resume</phrase><phrase role="special">()</phrase></code>
|
|
returns).
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
<varlistentry>
|
|
<term>Throws:</term>
|
|
<listitem>
|
|
<para>
|
|
depends on <code><phrase role="identifier">alloc</phrase></code> if
|
|
a precondition is not satisfied.
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
</variablelist>
|
|
<anchor id="context.context.context._code__phrase_role__keyword__template__phrase__phrase_role__special___lt___phrase___phrase_role__keyword__typename__phrase___phrase_role__identifier__fn__phrase__phrase_role__special_____phrase___phrase_role__keyword__typename__phrase___phrase_role__identifier__a0__phrase__phrase_role__special________phrase___phrase_role__special___gt___phrase___phrase_role__identifier__context__phrase__phrase_role__special_____phrase___phrase_role__identifier__fn__phrase___phrase_role__identifier__fn__phrase__phrase_role__special_____phrase___phrase_role__identifier__a0__phrase___phrase_role__identifier__a0__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__flag_unwind_t__phrase___phrase_role__identifier__do_unwind__phrase__phrase_role__special_____phrase___phrase_role__identifier__context__phrase___phrase_role__special___amp___phrase___phrase_role__identifier__nxt__phrase__phrase_role__special_____phrase___code_"/>
|
|
<bridgehead renderas="sect4">
|
|
<link linkend="context.context.context._code__phrase_role__keyword__template__phrase__phrase_role__special___lt___phrase___phrase_role__keyword__typename__phrase___phrase_role__identifier__fn__phrase__phrase_role__special_____phrase___phrase_role__keyword__typename__phrase___phrase_role__identifier__a0__phrase__phrase_role__special________phrase___phrase_role__special___gt___phrase___phrase_role__identifier__context__phrase__phrase_role__special_____phrase___phrase_role__identifier__fn__phrase___phrase_role__identifier__fn__phrase__phrase_role__special_____phrase___phrase_role__identifier__a0__phrase___phrase_role__identifier__a0__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__flag_unwind_t__phrase___phrase_role__identifier__do_unwind__phrase__phrase_role__special_____phrase___phrase_role__identifier__context__phrase___phrase_role__special___amp___phrase___phrase_role__identifier__nxt__phrase__phrase_role__special_____phrase___code_"><code><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="keyword">typename</phrase> <phrase
|
|
role="identifier">A0</phrase><phrase role="special">,...</phrase> <phrase
|
|
role="special">></phrase> <phrase role="identifier">context</phrase><phrase
|
|
role="special">(</phrase> <phrase role="identifier">Fn</phrase> <phrase role="identifier">fn</phrase><phrase
|
|
role="special">,</phrase> <phrase role="identifier">A0</phrase> <phrase role="identifier">a0</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">flag_unwind_t</phrase> <phrase role="identifier">do_unwind</phrase><phrase
|
|
role="special">,</phrase> <phrase role="identifier">context</phrase> <phrase
|
|
role="special">&</phrase> <phrase role="identifier">nxt</phrase><phrase
|
|
role="special">)</phrase></code></link>
|
|
</bridgehead>
|
|
<variablelist>
|
|
<title></title>
|
|
<varlistentry>
|
|
<term>Preconditions:</term>
|
|
<listitem>
|
|
<para>
|
|
<code><phrase role="identifier">size</phrase></code> > minimum_stacksize(),
|
|
<code><phrase role="identifier">size</phrase></code> < maximum_stacksize()
|
|
when ! is_stack_unbound(), <code><phrase role="identifier">nxt</phrase></code>
|
|
is not a <emphasis>not-a-context</emphasis>.
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
<varlistentry>
|
|
<term>Effects:</term>
|
|
<listitem>
|
|
<para>
|
|
Creates a context which will execute <code><phrase role="identifier">fn</phrase></code>
|
|
(arguments<code><phrase role="identifier">A0</phrase></code>,... are
|
|
bound to <code><phrase role="identifier">fn</phrase></code>). If <code><phrase
|
|
role="identifier">do_unwind</phrase></code> is <code><phrase role="identifier">stack_unwind</phrase></code>
|
|
the destructor of <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>
|
|
unwinds the stack before destructing it. execution control is transfered
|
|
to <code><phrase role="identifier">nxt</phrase></code> if <code><phrase
|
|
role="identifier">fn</phrase></code> returns (<code><phrase role="identifier">nxt</phrase></code>
|
|
is linked).
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
<varlistentry>
|
|
<term>Throws:</term>
|
|
<listitem>
|
|
<para>
|
|
<emphasis>std::invalid_argument</emphasis> if a precondition is not
|
|
satisfied.
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
</variablelist>
|
|
<anchor id="context.context.context._code__phrase_role__keyword__template__phrase__phrase_role__special___lt___phrase___phrase_role__keyword__typename__phrase___phrase_role__identifier__fn__phrase__phrase_role__special_____phrase___phrase_role__keyword__typename__phrase___phrase_role__identifier__allocator__phrase__phrase_role__special_____phrase___phrase_role__keyword__typename__phrase___phrase_role__identifier__a0__phrase__phrase_role__special________phrase___phrase_role__special___gt___phrase___phrase_role__identifier__context__phrase__phrase_role__special_____phrase___phrase_role__identifier__fn__phrase___phrase_role__identifier__fn__phrase__phrase_role__special_____phrase___phrase_role__identifier__a0__phrase___phrase_role__identifier__a0__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__flag_unwind_t__phrase___phrase_role__identifier__do_unwind__phrase__phrase_role__special_____phrase___phrase_role__identifier__context__phrase___phrase_role__special___amp___phrase___phrase_role__identifier__nxt__phrase__phrase_role__special_____phrase___phrase_role__identifier__allocator__phrase___phrase_role__keyword__const__phrase__phrase_role__special___amp___phrase___phrase_role__identifier__alloc__phrase__phrase_role__special_____phrase___code_"/>
|
|
<bridgehead renderas="sect4">
|
|
<link linkend="context.context.context._code__phrase_role__keyword__template__phrase__phrase_role__special___lt___phrase___phrase_role__keyword__typename__phrase___phrase_role__identifier__fn__phrase__phrase_role__special_____phrase___phrase_role__keyword__typename__phrase___phrase_role__identifier__allocator__phrase__phrase_role__special_____phrase___phrase_role__keyword__typename__phrase___phrase_role__identifier__a0__phrase__phrase_role__special________phrase___phrase_role__special___gt___phrase___phrase_role__identifier__context__phrase__phrase_role__special_____phrase___phrase_role__identifier__fn__phrase___phrase_role__identifier__fn__phrase__phrase_role__special_____phrase___phrase_role__identifier__a0__phrase___phrase_role__identifier__a0__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__flag_unwind_t__phrase___phrase_role__identifier__do_unwind__phrase__phrase_role__special_____phrase___phrase_role__identifier__context__phrase___phrase_role__special___amp___phrase___phrase_role__identifier__nxt__phrase__phrase_role__special_____phrase___phrase_role__identifier__allocator__phrase___phrase_role__keyword__const__phrase__phrase_role__special___amp___phrase___phrase_role__identifier__alloc__phrase__phrase_role__special_____phrase___code_"><code><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="keyword">typename</phrase> <phrase
|
|
role="identifier">Allocator</phrase><phrase role="special">,</phrase> <phrase
|
|
role="keyword">typename</phrase> <phrase role="identifier">A0</phrase><phrase
|
|
role="special">,...</phrase> <phrase role="special">></phrase> <phrase
|
|
role="identifier">context</phrase><phrase role="special">(</phrase> <phrase
|
|
role="identifier">Fn</phrase> <phrase role="identifier">fn</phrase><phrase
|
|
role="special">,</phrase> <phrase role="identifier">A0</phrase> <phrase role="identifier">a0</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">flag_unwind_t</phrase> <phrase role="identifier">do_unwind</phrase><phrase
|
|
role="special">,</phrase> <phrase role="identifier">context</phrase> <phrase
|
|
role="special">&</phrase> <phrase role="identifier">nxt</phrase><phrase
|
|
role="special">,</phrase> <phrase role="identifier">Allocator</phrase> <phrase
|
|
role="keyword">const</phrase><phrase role="special">&</phrase> <phrase
|
|
role="identifier">alloc</phrase><phrase role="special">)</phrase></code></link>
|
|
</bridgehead>
|
|
<variablelist>
|
|
<title></title>
|
|
<varlistentry>
|
|
<term>Preconditions:</term>
|
|
<listitem>
|
|
<para>
|
|
<code><phrase role="identifier">nxt</phrase></code> is not a <emphasis>not-a-context</emphasis>.
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
<varlistentry>
|
|
<term>Effects:</term>
|
|
<listitem>
|
|
<para>
|
|
Creates a context which will execute <code><phrase role="identifier">fn</phrase></code>
|
|
(arguments<code><phrase role="identifier">A0</phrase></code>,... are
|
|
bound to <code><phrase role="identifier">fn</phrase></code>). If <code><phrase
|
|
role="identifier">do_unwind</phrase></code> is <code><phrase role="identifier">stack_unwind</phrase></code>
|
|
the destructor of <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>
|
|
unwinds the stack before destructing it. execution control is transfered
|
|
to <code><phrase role="identifier">nxt</phrase></code> if <code><phrase
|
|
role="identifier">fn</phrase></code> returns (<code><phrase role="identifier">nxt</phrase></code>
|
|
is linked).
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
<varlistentry>
|
|
<term>Throws:</term>
|
|
<listitem>
|
|
<para>
|
|
depends on <code><phrase role="identifier">alloc</phrase></code> if
|
|
a precondition is not satisfied.
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
</variablelist>
|
|
<anchor id="context.context.context._code__phrase_role__special_____phrase__phrase_role__identifier__context__phrase__phrase_role__special______phrase___code_"/>
|
|
<bridgehead renderas="sect4">
|
|
<link linkend="context.context.context._code__phrase_role__special_____phrase__phrase_role__identifier__context__phrase__phrase_role__special______phrase___code_"><code><phrase
|
|
role="special">~</phrase><phrase role="identifier">context</phrase><phrase
|
|
role="special">()</phrase></code></link>
|
|
</bridgehead>
|
|
<variablelist>
|
|
<title></title>
|
|
<varlistentry>
|
|
<term>Effects:</term>
|
|
<listitem>
|
|
<para>
|
|
Destroys the instance and deallocates the stack. Unwinds the stack
|
|
if it was specified in the constructor of <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>
|
|
<anchor id="context.context.context._code__phrase_role__identifier__context__phrase__phrase_role__special_____phrase___phrase_role__identifier__context__phrase___phrase_role__special___amp__amp___phrase___phrase_role__identifier__other__phrase__phrase_role__special_____phrase___code_"/>
|
|
<bridgehead renderas="sect4">
|
|
<link linkend="context.context.context._code__phrase_role__identifier__context__phrase__phrase_role__special_____phrase___phrase_role__identifier__context__phrase___phrase_role__special___amp__amp___phrase___phrase_role__identifier__other__phrase__phrase_role__special_____phrase___code_"><code><phrase
|
|
role="identifier">context</phrase><phrase role="special">(</phrase> <phrase
|
|
role="identifier">context</phrase> <phrase role="special">&&</phrase>
|
|
<phrase role="identifier">other</phrase><phrase role="special">)</phrase></code></link>
|
|
</bridgehead>
|
|
<variablelist>
|
|
<title></title>
|
|
<varlistentry>
|
|
<term>Effects:</term>
|
|
<listitem>
|
|
<para>
|
|
Moves the internal data of <code><phrase role="identifier">other</phrase></code>
|
|
to <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>.
|
|
<code><phrase role="identifier">other</phrase></code> becomes <emphasis>not-a-context</emphasis>.
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
<varlistentry>
|
|
<term>Throws:</term>
|
|
<listitem>
|
|
<para>
|
|
Nothing.
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
</variablelist>
|
|
<anchor id="context.context.context._code__phrase_role__identifier__context__phrase___phrase_role__special___amp___phrase___phrase_role__keyword__operator__phrase__phrase_role__special______phrase___phrase_role__identifier__context__phrase___phrase_role__special___amp__amp___phrase___phrase_role__identifier__other__phrase__phrase_role__special_____phrase___code_"/>
|
|
<bridgehead renderas="sect4">
|
|
<link linkend="context.context.context._code__phrase_role__identifier__context__phrase___phrase_role__special___amp___phrase___phrase_role__keyword__operator__phrase__phrase_role__special______phrase___phrase_role__identifier__context__phrase___phrase_role__special___amp__amp___phrase___phrase_role__identifier__other__phrase__phrase_role__special_____phrase___code_"><code><phrase
|
|
role="identifier">context</phrase> <phrase role="special">&</phrase>
|
|
<phrase role="keyword">operator</phrase><phrase role="special">=(</phrase>
|
|
<phrase role="identifier">context</phrase> <phrase role="special">&&</phrase>
|
|
<phrase role="identifier">other</phrase><phrase role="special">)</phrase></code></link>
|
|
</bridgehead>
|
|
<variablelist>
|
|
<title></title>
|
|
<varlistentry>
|
|
<term>Effects:</term>
|
|
<listitem>
|
|
<para>
|
|
Destroys the internal data of <code><phrase role="special">*</phrase><phrase
|
|
role="keyword">this</phrase></code> and moves the internal data of
|
|
<code><phrase role="identifier">other</phrase></code> to <code><phrase
|
|
role="special">*</phrase><phrase role="keyword">this</phrase></code>.
|
|
<code><phrase role="identifier">other</phrase></code> becomes <emphasis>not-a-context</emphasis>.
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
<varlistentry>
|
|
<term>Throws:</term>
|
|
<listitem>
|
|
<para>
|
|
Nothing.
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
</variablelist>
|
|
<anchor id="context.context.context._code__phrase_role__keyword__operator__phrase___phrase_role__identifier__unspecified__phrase__phrase_role__special_____phrase__phrase_role__keyword__bool__phrase__phrase_role__special_____phrase__phrase_role__identifier__type__phrase__phrase_role__special______phrase___phrase_role__keyword__const__phrase___code_"/>
|
|
<bridgehead renderas="sect4">
|
|
<link linkend="context.context.context._code__phrase_role__keyword__operator__phrase___phrase_role__identifier__unspecified__phrase__phrase_role__special_____phrase__phrase_role__keyword__bool__phrase__phrase_role__special_____phrase__phrase_role__identifier__type__phrase__phrase_role__special______phrase___phrase_role__keyword__const__phrase___code_"><code><phrase
|
|
role="keyword">operator</phrase> <phrase role="identifier">unspecified</phrase><phrase
|
|
role="special">-</phrase><phrase role="keyword">bool</phrase><phrase role="special">-</phrase><phrase
|
|
role="identifier">type</phrase><phrase role="special">()</phrase> <phrase
|
|
role="keyword">const</phrase></code></link>
|
|
</bridgehead>
|
|
<variablelist>
|
|
<title></title>
|
|
<varlistentry>
|
|
<term>Returns:</term>
|
|
<listitem>
|
|
<para>
|
|
If <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>
|
|
refers to <emphasis>not-a-context</emphasis>, the function returns
|
|
false. Otherwise true.
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
<varlistentry>
|
|
<term>Throws:</term>
|
|
<listitem>
|
|
<para>
|
|
Nothing.
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
</variablelist>
|
|
<anchor id="context.context.context._code__phrase_role__keyword__bool__phrase___phrase_role__keyword__operator__phrase__phrase_role__special_______phrase___phrase_role__keyword__const__phrase___code_"/>
|
|
<bridgehead renderas="sect4">
|
|
<link linkend="context.context.context._code__phrase_role__keyword__bool__phrase___phrase_role__keyword__operator__phrase__phrase_role__special_______phrase___phrase_role__keyword__const__phrase___code_"><code><phrase
|
|
role="keyword">bool</phrase> <phrase role="keyword">operator</phrase><phrase
|
|
role="special">!()</phrase> <phrase role="keyword">const</phrase></code></link>
|
|
</bridgehead>
|
|
<variablelist>
|
|
<title></title>
|
|
<varlistentry>
|
|
<term>Returns:</term>
|
|
<listitem>
|
|
<para>
|
|
If <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>
|
|
refers not to <emphasis>not-a-context</emphasis>, the function returns
|
|
true. Otherwise false.
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
<varlistentry>
|
|
<term>Throws:</term>
|
|
<listitem>
|
|
<para>
|
|
Nothing.
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
</variablelist>
|
|
<anchor id="context.context.context._code__phrase_role__keyword__void__phrase___phrase_role__identifier__swap__phrase__phrase_role__special_____phrase___phrase_role__identifier__context__phrase___phrase_role__special___amp___phrase___phrase_role__identifier__other__phrase__phrase_role__special_____phrase___code_"/>
|
|
<bridgehead renderas="sect4">
|
|
<link linkend="context.context.context._code__phrase_role__keyword__void__phrase___phrase_role__identifier__swap__phrase__phrase_role__special_____phrase___phrase_role__identifier__context__phrase___phrase_role__special___amp___phrase___phrase_role__identifier__other__phrase__phrase_role__special_____phrase___code_"><code><phrase
|
|
role="keyword">void</phrase> <phrase role="identifier">swap</phrase><phrase
|
|
role="special">(</phrase> <phrase role="identifier">context</phrase> <phrase
|
|
role="special">&</phrase> <phrase role="identifier">other</phrase><phrase
|
|
role="special">)</phrase></code></link>
|
|
</bridgehead>
|
|
<variablelist>
|
|
<title></title>
|
|
<varlistentry>
|
|
<term>Effects:</term>
|
|
<listitem>
|
|
<para>
|
|
Swaps the internal data from <code><phrase role="special">*</phrase><phrase
|
|
role="keyword">this</phrase></code> with the values of <code><phrase
|
|
role="identifier">other</phrase></code>.
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
<varlistentry>
|
|
<term>Throws:</term>
|
|
<listitem>
|
|
<para>
|
|
Nothing.
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
</variablelist>
|
|
<anchor id="context.context.context._code__phrase_role__keyword__bool__phrase___phrase_role__identifier__is_complete__phrase__phrase_role__special______phrase___phrase_role__keyword__const__phrase___code_"/>
|
|
<bridgehead renderas="sect4">
|
|
<link linkend="context.context.context._code__phrase_role__keyword__bool__phrase___phrase_role__identifier__is_complete__phrase__phrase_role__special______phrase___phrase_role__keyword__const__phrase___code_"><code><phrase
|
|
role="keyword">bool</phrase> <phrase role="identifier">is_complete</phrase><phrase
|
|
role="special">()</phrase> <phrase role="keyword">const</phrase></code></link>
|
|
</bridgehead>
|
|
<variablelist>
|
|
<title></title>
|
|
<varlistentry>
|
|
<term>Preconditions:</term>
|
|
<listitem>
|
|
<para>
|
|
<code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>
|
|
is not a <emphasis>not-a-context</emphasis>.
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
<varlistentry>
|
|
<term>Effects:</term>
|
|
<listitem>
|
|
<para>
|
|
Returns <code><phrase role="keyword">true</phrase></code> if context-function
|
|
of <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>
|
|
has returned.
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
<varlistentry>
|
|
<term>Throws:</term>
|
|
<listitem>
|
|
<para>
|
|
Nothing.
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
</variablelist>
|
|
<anchor id="context.context.context._code__phrase_role__keyword__bool__phrase___phrase_role__identifier__is_running__phrase__phrase_role__special______phrase___phrase_role__keyword__const__phrase___code_"/>
|
|
<bridgehead renderas="sect4">
|
|
<link linkend="context.context.context._code__phrase_role__keyword__bool__phrase___phrase_role__identifier__is_running__phrase__phrase_role__special______phrase___phrase_role__keyword__const__phrase___code_"><code><phrase
|
|
role="keyword">bool</phrase> <phrase role="identifier">is_running</phrase><phrase
|
|
role="special">()</phrase> <phrase role="keyword">const</phrase></code></link>
|
|
</bridgehead>
|
|
<variablelist>
|
|
<title></title>
|
|
<varlistentry>
|
|
<term>Preconditions:</term>
|
|
<listitem>
|
|
<para>
|
|
<code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>
|
|
is not a <emphasis>not-a-context</emphasis>.
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
<varlistentry>
|
|
<term>Effects:</term>
|
|
<listitem>
|
|
<para>
|
|
Returns <code><phrase role="keyword">true</phrase></code> if <code><phrase
|
|
role="special">*</phrase><phrase role="keyword">this</phrase></code>
|
|
is the currently active context.
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
<varlistentry>
|
|
<term>Throws:</term>
|
|
<listitem>
|
|
<para>
|
|
Nothing.
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
</variablelist>
|
|
<anchor id="context.context.context._code__phrase_role__identifier__intptr_t__phrase___phrase_role__identifier__start__phrase__phrase_role__special______phrase___code_"/>
|
|
<bridgehead renderas="sect4">
|
|
<link linkend="context.context.context._code__phrase_role__identifier__intptr_t__phrase___phrase_role__identifier__start__phrase__phrase_role__special______phrase___code_"><code><phrase
|
|
role="identifier">intptr_t</phrase> <phrase role="identifier">start</phrase><phrase
|
|
role="special">()</phrase></code></link>
|
|
</bridgehead>
|
|
<variablelist>
|
|
<title></title>
|
|
<varlistentry>
|
|
<term>Preconditions:</term>
|
|
<listitem>
|
|
<para>
|
|
<code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>
|
|
is not a <emphasis>not-a-context</emphasis>, <code><phrase role="special">!</phrase>
|
|
<phrase role="identifier">is_complete</phrase><phrase role="special">()</phrase></code>
|
|
and <code><phrase role="special">!</phrase> <phrase role="identifier">is_running</phrase><phrase
|
|
role="special">()</phrase></code>.
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
<varlistentry>
|
|
<term>Effects:</term>
|
|
<listitem>
|
|
<para>
|
|
<code><phrase role="identifier">start</phrase><phrase role="special">()</phrase></code>
|
|
enters the <emphasis>context-function</emphasis> <code><phrase role="identifier">fn</phrase></code>
|
|
with which the context was constructed. Upon return, the context was
|
|
either left via <code><phrase role="identifier">suspend</phrase><phrase
|
|
role="special">()</phrase></code> or the <emphasis>context-function</emphasis>
|
|
returned.
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
<varlistentry>
|
|
<term>Returns:</term>
|
|
<listitem>
|
|
<para>
|
|
A intptr_t passed to <code><phrase role="identifier">suspend</phrase><phrase
|
|
role="special">()</phrase></code> is returned if the context was left
|
|
with <code><phrase role="identifier">suspend</phrase><phrase role="special">()</phrase></code>.
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
<varlistentry>
|
|
<term>Throws:</term>
|
|
<listitem>
|
|
<para>
|
|
Nothing.
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
</variablelist>
|
|
<anchor id="context.context.context._code__phrase_role__identifier__intptr_t__phrase___phrase_role__identifier__resume__phrase__phrase_role__special_____phrase___phrase_role__identifier__intptr_t__phrase___phrase_role__identifier__vp__phrase___phrase_role__special_____phrase___phrase_role__number__0__phrase__phrase_role__special_____phrase___code_"/>
|
|
<bridgehead renderas="sect4">
|
|
<link linkend="context.context.context._code__phrase_role__identifier__intptr_t__phrase___phrase_role__identifier__resume__phrase__phrase_role__special_____phrase___phrase_role__identifier__intptr_t__phrase___phrase_role__identifier__vp__phrase___phrase_role__special_____phrase___phrase_role__number__0__phrase__phrase_role__special_____phrase___code_"><code><phrase
|
|
role="identifier">intptr_t</phrase> <phrase role="identifier">resume</phrase><phrase
|
|
role="special">(</phrase> <phrase role="identifier">intptr_t</phrase> <phrase
|
|
role="identifier">vp</phrase> <phrase role="special">=</phrase> <phrase role="number">0</phrase><phrase
|
|
role="special">)</phrase></code></link>
|
|
</bridgehead>
|
|
<variablelist>
|
|
<title></title>
|
|
<varlistentry>
|
|
<term>Preconditions:</term>
|
|
<listitem>
|
|
<para>
|
|
<code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>
|
|
is not a <emphasis>not-a-context</emphasis>, <code><phrase role="special">!</phrase>
|
|
<phrase role="identifier">is_complete</phrase><phrase role="special">()</phrase></code>
|
|
and <code><phrase role="special">!</phrase> <phrase role="identifier">is_running</phrase><phrase
|
|
role="special">()</phrase></code>, <code><phrase role="identifier">start</phrase><phrase
|
|
role="special">()</phrase></code> was called before.
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
<varlistentry>
|
|
<term>Effects:</term>
|
|
<listitem>
|
|
<para>
|
|
None, if *this was not suspended by a previous call to suspend(). Otherwise,
|
|
execution control is transferred back to the caller of suspend(), thereby
|
|
resuming *this. The argument, vp, will be returned by the previous
|
|
call to suspend().
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
<varlistentry>
|
|
<term>Throws:</term>
|
|
<listitem>
|
|
<para>
|
|
Nothing.
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
</variablelist>
|
|
<anchor id="context.context.context._code__phrase_role__identifier__intptr_t__phrase___phrase_role__identifier__suspend__phrase__phrase_role__special_____phrase___phrase_role__identifier__intptr_t__phrase___phrase_role__identifier__vp__phrase___phrase_role__special_____phrase___phrase_role__number__0__phrase__phrase_role__special_____phrase___code_"/>
|
|
<bridgehead renderas="sect4">
|
|
<link linkend="context.context.context._code__phrase_role__identifier__intptr_t__phrase___phrase_role__identifier__suspend__phrase__phrase_role__special_____phrase___phrase_role__identifier__intptr_t__phrase___phrase_role__identifier__vp__phrase___phrase_role__special_____phrase___phrase_role__number__0__phrase__phrase_role__special_____phrase___code_"><code><phrase
|
|
role="identifier">intptr_t</phrase> <phrase role="identifier">suspend</phrase><phrase
|
|
role="special">(</phrase> <phrase role="identifier">intptr_t</phrase> <phrase
|
|
role="identifier">vp</phrase> <phrase role="special">=</phrase> <phrase role="number">0</phrase><phrase
|
|
role="special">)</phrase></code></link>
|
|
</bridgehead>
|
|
<variablelist>
|
|
<title></title>
|
|
<varlistentry>
|
|
<term>Preconditions:</term>
|
|
<listitem>
|
|
<para>
|
|
<code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>
|
|
is not a <emphasis>not-a-context</emphasis>, <code><phrase role="special">!</phrase>
|
|
<phrase role="identifier">is_complete</phrase><phrase role="special">()</phrase></code>
|
|
and <code><phrase role="identifier">is_running</phrase><phrase role="special">()</phrase></code>.
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
<varlistentry>
|
|
<term>Effects:</term>
|
|
<listitem>
|
|
<para>
|
|
Transfers execution control to the caller of the most recent call to
|
|
start() or resume(). The argument, vp, will be returned by start()
|
|
or resume().
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
<varlistentry>
|
|
<term>Throws:</term>
|
|
<listitem>
|
|
<para>
|
|
<emphasis>forced_unwind</emphasis> if <emphasis>context::unwind_stack()</emphasis>
|
|
was called.
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
</variablelist>
|
|
<anchor id="context.context.context._code__phrase_role__keyword__void__phrase___phrase_role__identifier__unwind_stack__phrase__phrase_role__special______phrase___code_"/>
|
|
<bridgehead renderas="sect4">
|
|
<link linkend="context.context.context._code__phrase_role__keyword__void__phrase___phrase_role__identifier__unwind_stack__phrase__phrase_role__special______phrase___code_"><code><phrase
|
|
role="keyword">void</phrase> <phrase role="identifier">unwind_stack</phrase><phrase
|
|
role="special">()</phrase></code></link>
|
|
</bridgehead>
|
|
<variablelist>
|
|
<title></title>
|
|
<varlistentry>
|
|
<term>Preconditions:</term>
|
|
<listitem>
|
|
<para>
|
|
<code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>
|
|
is not a <emphasis>not-a-context</emphasis>, <code><phrase role="special">!</phrase>
|
|
<phrase role="identifier">is_complete</phrase><phrase role="special">()</phrase></code>
|
|
and <code><phrase role="special">!</phrase> <phrase role="identifier">is_running</phrase><phrase
|
|
role="special">()</phrase></code>.
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
<varlistentry>
|
|
<term>Effects:</term>
|
|
<listitem>
|
|
<para>
|
|
Destroys all objects allocated on the stack, owned by *this, in the
|
|
reverse order of their allocation.
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
<varlistentry>
|
|
<term>Throws:</term>
|
|
<listitem>
|
|
<para>
|
|
Nothing.
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
<varlistentry>
|
|
<term>Postconditions:</term>
|
|
<listitem>
|
|
<para>
|
|
<code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>
|
|
is not a <emphasis>not-a-context</emphasis> and <code><phrase role="identifier">is_complete</phrase><phrase
|
|
role="special">()</phrase></code>.
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
</variablelist>
|
|
<anchor id="context.context.context.non_member_function__code__phrase_role__identifier__swap__phrase__phrase_role__special______phrase___code_"/>
|
|
<bridgehead renderas="sect4">
|
|
<link linkend="context.context.context.non_member_function__code__phrase_role__identifier__swap__phrase__phrase_role__special______phrase___code_">Non-member
|
|
function <code><phrase role="identifier">swap</phrase><phrase role="special">()</phrase></code></link>
|
|
</bridgehead>
|
|
|
|
<programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">swap</phrase><phrase role="special">(</phrase> <phrase role="identifier">context</phrase> <phrase role="special">&</phrase> <phrase role="identifier">l</phrase><phrase role="special">,</phrase> <phrase role="identifier">context</phrase> <phrase role="special">&</phrase> <phrase role="identifier">r</phrase><phrase role="special">);</phrase>
|
|
</programlisting>
|
|
<variablelist>
|
|
<title></title>
|
|
<varlistentry>
|
|
<term>Effects:</term>
|
|
<listitem>
|
|
<para>
|
|
As if 'l.swap( r)'.
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
</variablelist>
|
|
</section>
|
|
</section>
|
|
<section id="context.stack">
|
|
<title><link linkend="context.stack">Stack allocation</link></title>
|
|
<para>
|
|
A <link linkend="context.context.context"><emphasis>context</emphasis></link>
|
|
requires a stack which will be allocated/deallocated by a <emphasis>StackAllocator</emphasis>.
|
|
<emphasis role="bold">Boost.Context</emphasis> uses <code><phrase role="identifier">stack_allocator</phrase></code>
|
|
by default but a customized <code><phrase role="identifier">stack</phrase>
|
|
<phrase role="identifier">allocator</phrase></code> can be passed to the context
|
|
constructor instead. If a context is constructed it invokes <emphasis>allocate()</emphasis>
|
|
function and by its destruction the stack gets released by <emphasis>deallocate()</emphasis>.
|
|
</para>
|
|
<anchor id="context.stack._emphasis_stackallocator_concept__emphasis_"/>
|
|
<bridgehead renderas="sect3">
|
|
<link linkend="context.stack._emphasis_stackallocator_concept__emphasis_"><emphasis>StackAllocator
|
|
concept</emphasis></link>
|
|
</bridgehead>
|
|
<para>
|
|
A <emphasis>StackAllocator</emphasis> must satisfy the <emphasis>StackAllocator
|
|
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">p</phrase></code> is a <code><phrase
|
|
role="keyword">void</phrase> <phrase role="special">*</phrase></code>, and
|
|
<code><phrase role="identifier">s</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">allocate</phrase><phrase role="special">(</phrase>
|
|
<phrase role="identifier">s</phrase><phrase role="special">)</phrase></code>
|
|
</para>
|
|
</entry>
|
|
<entry>
|
|
<para>
|
|
<code><phrase role="keyword">void</phrase> <phrase role="special">*</phrase></code>
|
|
</para>
|
|
</entry>
|
|
<entry>
|
|
<para>
|
|
returns a pointer to <code><phrase role="identifier">s</phrase></code>
|
|
bytes allocated from the 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">p</phrase><phrase role="special">,</phrase>
|
|
<phrase role="identifier">s</phrase><phrase role="special">)</phrase></code>
|
|
</para>
|
|
</entry>
|
|
<entry>
|
|
<para>
|
|
<code><phrase role="keyword">void</phrase></code>
|
|
</para>
|
|
</entry>
|
|
<entry>
|
|
<para>
|
|
deallocates <code><phrase role="identifier">s</phrase></code> bytes
|
|
of memory beginning at <code><phrase role="identifier">p</phrase></code>,
|
|
a pointer previously returned 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 pointer not returned by <code><phrase role="identifier">allocate</phrase><phrase
|
|
role="special">()</phrase></code> results in undefined behaviour.
|
|
</para>
|
|
</important>
|
|
<note>
|
|
<para>
|
|
The stack is not required to be aligned; alignment takes place inside <code><phrase
|
|
role="identifier">boost_fcontext_make</phrase><phrase role="special">()</phrase></code>.
|
|
</para>
|
|
</note>
|
|
<section id="context.stack.stack_allocator">
|
|
<title><link linkend="context.stack.stack_allocator">Class <code><phrase role="identifier">stack_allocator</phrase></code></link></title>
|
|
<para>
|
|
<emphasis role="bold">Boost.Context</emphasis> provides a <emphasis>StackAllocator</emphasis>
|
|
<code><phrase role="identifier">stack_allocator</phrase></code> which models
|
|
the <emphasis>StackAllocator concept</emphasis> concept. It appends a <emphasis>guard-page</emphasis>
|
|
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>
|
|
</section>
|
|
<section id="context.stack.stack_helper">
|
|
<title><link linkend="context.stack.stack_helper">Helper functions</link></title>
|
|
<para>
|
|
<emphasis role="bold">Boost.Context</emphasis> provides easy access to the
|
|
stack related limits defined by the environment.
|
|
</para>
|
|
|
|
<programlisting><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">default_stacksize</phrase><phrase role="special">();</phrase>
|
|
|
|
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">minimum_stacksize</phrase><phrase role="special">();</phrase>
|
|
|
|
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">maximum_stacksize</phrase><phrase role="special">();</phrase>
|
|
|
|
<phrase role="keyword">bool</phrase> <phrase role="identifier">is_stack_unbound</phrase><phrase role="special">();</phrase>
|
|
|
|
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">pagesize</phrase><phrase role="special">();</phrase>
|
|
|
|
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">page_count</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">stacksize</phrase><phrase role="special">);</phrase>
|
|
</programlisting>
|
|
<anchor id="context.stack.stack_helper._code__phrase_role__identifier__std__phrase__phrase_role__special______phrase__phrase_role__identifier__size_t__phrase___phrase_role__identifier__default_stacksize__phrase__phrase_role__special______phrase___code_"/>
|
|
<bridgehead renderas="sect4">
|
|
<link linkend="context.stack.stack_helper._code__phrase_role__identifier__std__phrase__phrase_role__special______phrase__phrase_role__identifier__size_t__phrase___phrase_role__identifier__default_stacksize__phrase__phrase_role__special______phrase___code_"><code><phrase
|
|
role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase>
|
|
<phrase role="identifier">default_stacksize</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. The present
|
|
implementation returns a value of 256 kB.
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
</variablelist>
|
|
<anchor id="context.stack.stack_helper._code__phrase_role__identifier__std__phrase__phrase_role__special______phrase__phrase_role__identifier__size_t__phrase___phrase_role__identifier__minimum_stacksize__phrase__phrase_role__special______phrase___code_"/>
|
|
<bridgehead renderas="sect4">
|
|
<link linkend="context.stack.stack_helper._code__phrase_role__identifier__std__phrase__phrase_role__special______phrase__phrase_role__identifier__size_t__phrase___phrase_role__identifier__minimum_stacksize__phrase__phrase_role__special______phrase___code_"><code><phrase
|
|
role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase>
|
|
<phrase role="identifier">minimum_stacksize</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.
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
<varlistentry>
|
|
<term>Throws:</term>
|
|
<listitem>
|
|
<para>
|
|
Nothing.
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
</variablelist>
|
|
<anchor id="context.stack.stack_helper._code__phrase_role__identifier__std__phrase__phrase_role__special______phrase__phrase_role__identifier__size_t__phrase___phrase_role__identifier__maximum_stacksize__phrase__phrase_role__special______phrase___code_"/>
|
|
<bridgehead renderas="sect4">
|
|
<link linkend="context.stack.stack_helper._code__phrase_role__identifier__std__phrase__phrase_role__special______phrase__phrase_role__identifier__size_t__phrase___phrase_role__identifier__maximum_stacksize__phrase__phrase_role__special______phrase___code_"><code><phrase
|
|
role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase>
|
|
<phrase role="identifier">maximum_stacksize</phrase><phrase role="special">()</phrase></code></link>
|
|
</bridgehead>
|
|
<variablelist>
|
|
<title></title>
|
|
<varlistentry>
|
|
<term>Preconditions:</term>
|
|
<listitem>
|
|
<para>
|
|
<code><phrase role="identifier">is_stack_unbound</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>
|
|
<anchor id="context.stack.stack_helper._code__phrase_role__keyword__bool__phrase___phrase_role__identifier__is_stack_unbound__phrase__phrase_role__special______phrase___code_"/>
|
|
<bridgehead renderas="sect4">
|
|
<link linkend="context.stack.stack_helper._code__phrase_role__keyword__bool__phrase___phrase_role__identifier__is_stack_unbound__phrase__phrase_role__special______phrase___code_"><code><phrase
|
|
role="keyword">bool</phrase> <phrase role="identifier">is_stack_unbound</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>
|
|
<anchor id="context.stack.stack_helper._code__phrase_role__identifier__std__phrase__phrase_role__special______phrase__phrase_role__identifier__size_t__phrase___phrase_role__identifier__pagesize__phrase__phrase_role__special______phrase___code_"/>
|
|
<bridgehead renderas="sect4">
|
|
<link linkend="context.stack.stack_helper._code__phrase_role__identifier__std__phrase__phrase_role__special______phrase__phrase_role__identifier__size_t__phrase___phrase_role__identifier__pagesize__phrase__phrase_role__special______phrase___code_"><code><phrase
|
|
role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase>
|
|
<phrase role="identifier">pagesize</phrase><phrase role="special">()</phrase></code></link>
|
|
</bridgehead>
|
|
<variablelist>
|
|
<title></title>
|
|
<varlistentry>
|
|
<term>Returns:</term>
|
|
<listitem>
|
|
<para>
|
|
Returns how many bytes the operating system allocates for one page.
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
<varlistentry>
|
|
<term>Throws:</term>
|
|
<listitem>
|
|
<para>
|
|
Nothing.
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
</variablelist>
|
|
<anchor id="context.stack.stack_helper._code__phrase_role__identifier__std__phrase__phrase_role__special______phrase__phrase_role__identifier__size_t__phrase___phrase_role__identifier__page_count__phrase__phrase_role__special_____phrase___phrase_role__identifier__std__phrase__phrase_role__special______phrase__phrase_role__identifier__size_t__phrase___phrase_role__identifier__stacksize__phrase__phrase_role__special_____phrase___code_"/>
|
|
<bridgehead renderas="sect4">
|
|
<link linkend="context.stack.stack_helper._code__phrase_role__identifier__std__phrase__phrase_role__special______phrase__phrase_role__identifier__size_t__phrase___phrase_role__identifier__page_count__phrase__phrase_role__special_____phrase___phrase_role__identifier__std__phrase__phrase_role__special______phrase__phrase_role__identifier__size_t__phrase___phrase_role__identifier__stacksize__phrase__phrase_role__special_____phrase___code_"><code><phrase
|
|
role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase>
|
|
<phrase role="identifier">page_count</phrase><phrase role="special">(</phrase>
|
|
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase
|
|
role="identifier">size_t</phrase> <phrase role="identifier">stacksize</phrase><phrase
|
|
role="special">)</phrase></code></link>
|
|
</bridgehead>
|
|
<variablelist>
|
|
<title></title>
|
|
<varlistentry>
|
|
<term>Returns:</term>
|
|
<listitem>
|
|
<para>
|
|
Returns how many pages have to be allocated for a stack of <code><phrase
|
|
role="identifier">stacksize</phrase></code> bytes.
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
<varlistentry>
|
|
<term>Throws:</term>
|
|
<listitem>
|
|
<para>
|
|
Nothing.
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
</variablelist>
|
|
</section>
|
|
</section>
|
|
<section id="context.capi">
|
|
<title><link linkend="context.capi">Low level API (boost_fcontext_t)</link></title>
|
|
<para>
|
|
<emphasis role="bold">Boost.Context</emphasis> uses and provides a low level
|
|
API which implements the execution control transfer mechanism. The boost_fcontext_t
|
|
API provides a similar interface like <ulink url="http://www.kernel.org/doc/man-pages/online/pages/man2/getcontext.2.html">ucontext_t</ulink>.
|
|
boost_fcontext_t and its functions are located in the global namespace and
|
|
the functions are declared as extern "C".
|
|
</para>
|
|
|
|
<programlisting><phrase role="preprocessor">#include</phrase> <phrase role="special"><</phrase><phrase role="identifier">cstdio</phrase><phrase role="special">></phrase>
|
|
<phrase role="preprocessor">#include</phrase> <phrase role="special"><</phrase><phrase role="identifier">cstdlib</phrase><phrase role="special">></phrase>
|
|
<phrase role="preprocessor">#include</phrase> <phrase role="special"><</phrase><phrase role="identifier">cstring</phrase><phrase role="special">></phrase>
|
|
<phrase role="preprocessor">#include</phrase> <phrase role="special"><</phrase><phrase role="identifier">vector</phrase><phrase role="special">></phrase>
|
|
|
|
<phrase role="preprocessor">#include</phrase> <phrase role="special"><</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">cstdint</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">></phrase>
|
|
<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">fcontext</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">></phrase>
|
|
|
|
<phrase role="identifier">boost_fcontext_t</phrase> <phrase role="identifier">fcm</phrase><phrase role="special">,</phrase> <phrase role="identifier">fc1</phrase><phrase role="special">,</phrase> <phrase role="identifier">fc2</phrase><phrase role="special">;</phrase>
|
|
|
|
<phrase role="keyword">void</phrase> <phrase role="identifier">f1</phrase><phrase role="special">(</phrase> <phrase role="identifier">intptr_t</phrase> <phrase role="identifier">p</phrase><phrase role="special">)</phrase>
|
|
<phrase role="special">{</phrase>
|
|
<phrase role="special">(</phrase><phrase role="keyword">void</phrase><phrase role="special">)</phrase> <phrase role="identifier">p</phrase><phrase role="special">;</phrase>
|
|
<phrase role="identifier">fprintf</phrase><phrase role="special">(</phrase><phrase role="identifier">stderr</phrase><phrase role="special">,</phrase><phrase role="string">"f1() started\n"</phrase><phrase role="special">);</phrase>
|
|
<phrase role="identifier">fprintf</phrase><phrase role="special">(</phrase><phrase role="identifier">stderr</phrase><phrase role="special">,</phrase><phrase role="string">"f1: call boost_fcontext_jump( & fc1, & fc2, 0)\n"</phrase><phrase role="special">);</phrase>
|
|
<phrase role="comment">// jump to context fc2
|
|
</phrase> <phrase role="identifier">boost_fcontext_jump</phrase><phrase role="special">(</phrase> <phrase role="special">&</phrase> <phrase role="identifier">fc1</phrase><phrase role="special">,</phrase> <phrase role="special">&</phrase> <phrase role="identifier">fc2</phrase><phrase role="special">,</phrase> <phrase role="number">0</phrase><phrase role="special">);</phrase>
|
|
<phrase role="comment">// returned from context fc2 (function f2())
|
|
</phrase> <phrase role="comment">// return from function f1()
|
|
</phrase> <phrase role="identifier">fprintf</phrase><phrase role="special">(</phrase><phrase role="identifier">stderr</phrase><phrase role="special">,</phrase><phrase role="string">"f1() returns\n"</phrase><phrase role="special">);</phrase>
|
|
<phrase role="special">}</phrase>
|
|
|
|
<phrase role="keyword">void</phrase> <phrase role="identifier">f2</phrase><phrase role="special">(</phrase> <phrase role="identifier">intptr_t</phrase> <phrase role="identifier">p</phrase><phrase role="special">)</phrase>
|
|
<phrase role="special">{</phrase>
|
|
<phrase role="special">(</phrase><phrase role="keyword">void</phrase><phrase role="special">)</phrase> <phrase role="identifier">p</phrase><phrase role="special">;</phrase>
|
|
<phrase role="identifier">fprintf</phrase><phrase role="special">(</phrase><phrase role="identifier">stderr</phrase><phrase role="special">,</phrase><phrase role="string">"f2() started\n"</phrase><phrase role="special">);</phrase>
|
|
<phrase role="identifier">fprintf</phrase><phrase role="special">(</phrase><phrase role="identifier">stderr</phrase><phrase role="special">,</phrase><phrase role="string">"f2: call boost_fcontext_jump( & fc2, & fc1, 0)\n"</phrase><phrase role="special">);</phrase>
|
|
<phrase role="comment">// jump to context fc1
|
|
</phrase> <phrase role="identifier">boost_fcontext_jump</phrase><phrase role="special">(</phrase> <phrase role="special">&</phrase> <phrase role="identifier">fc2</phrase><phrase role="special">,</phrase> <phrase role="special">&</phrase> <phrase role="identifier">fc1</phrase><phrase role="special">,</phrase> <phrase role="number">0</phrase><phrase role="special">);</phrase>
|
|
<phrase role="comment">// never reached
|
|
</phrase> <phrase role="identifier">fprintf</phrase><phrase role="special">(</phrase><phrase role="identifier">stderr</phrase><phrase role="special">,</phrase><phrase role="string">"f2() returns\n"</phrase><phrase role="special">);</phrase>
|
|
<phrase role="special">}</phrase>
|
|
|
|
<phrase role="keyword">int</phrase> <phrase role="identifier">main</phrase><phrase role="special">(</phrase> <phrase role="keyword">int</phrase> <phrase role="identifier">argc</phrase><phrase role="special">,</phrase> <phrase role="keyword">char</phrase> <phrase role="special">*</phrase> <phrase role="identifier">argv</phrase><phrase role="special">[])</phrase>
|
|
<phrase role="special">{</phrase>
|
|
<phrase role="comment">// creat two protected stacks
|
|
</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">contexts</phrase><phrase role="special">::</phrase><phrase role="identifier">protected_stack</phrase> <phrase role="identifier">b1</phrase><phrase role="special">(</phrase><phrase role="number">262144</phrase><phrase role="special">);</phrase>
|
|
<phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">contexts</phrase><phrase role="special">::</phrase><phrase role="identifier">protected_stack</phrase> <phrase role="identifier">b2</phrase><phrase role="special">(</phrase><phrase role="number">262144</phrase><phrase role="special">);</phrase>
|
|
|
|
<phrase role="comment">// let context fc1 use stack b1
|
|
</phrase> <phrase role="identifier">fc1</phrase><phrase role="special">.</phrase><phrase role="identifier">fc_stack</phrase><phrase role="special">.</phrase><phrase role="identifier">ss_base</phrase> <phrase role="special">=</phrase> <phrase role="identifier">b1</phrase><phrase role="special">.</phrase><phrase role="identifier">address</phrase><phrase role="special">();</phrase>
|
|
<phrase role="identifier">fc1</phrase><phrase role="special">.</phrase><phrase role="identifier">fc_stack</phrase><phrase role="special">.</phrase><phrase role="identifier">ss_limit</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="special">>(</phrase> <phrase role="identifier">fc1</phrase><phrase role="special">.</phrase><phrase role="identifier">fc_stack</phrase><phrase role="special">.</phrase><phrase role="identifier">ss_base</phrase><phrase role="special">)</phrase> <phrase role="special">-</phrase> <phrase role="identifier">b1</phrase><phrase role="special">.</phrase><phrase role="identifier">size</phrase><phrase role="special">();</phrase>
|
|
<phrase role="comment">// link context fcm;
|
|
</phrase> <phrase role="comment">// fcm will be invoked after fc1 terminated
|
|
</phrase> <phrase role="identifier">fc1</phrase><phrase role="special">.</phrase><phrase role="identifier">fc_link</phrase> <phrase role="special">=</phrase> <phrase role="special">&</phrase> <phrase role="identifier">fcm</phrase><phrase role="special">;</phrase>
|
|
<phrase role="comment">// context fc1 used f1() as context function
|
|
</phrase> <phrase role="identifier">boost_fcontext_make</phrase><phrase role="special">(</phrase> <phrase role="special">&</phrase> <phrase role="identifier">fc1</phrase><phrase role="special">,</phrase> <phrase role="identifier">f1</phrase><phrase role="special">,</phrase> <phrase role="number">0</phrase><phrase role="special">);</phrase>
|
|
|
|
<phrase role="comment">// let context fc2 use stack b2
|
|
</phrase> <phrase role="identifier">fc2</phrase><phrase role="special">.</phrase><phrase role="identifier">fc_stack</phrase><phrase role="special">.</phrase><phrase role="identifier">ss_base</phrase> <phrase role="special">=</phrase> <phrase role="identifier">b2</phrase><phrase role="special">.</phrase><phrase role="identifier">address</phrase><phrase role="special">();</phrase>
|
|
<phrase role="identifier">fc2</phrase><phrase role="special">.</phrase><phrase role="identifier">fc_stack</phrase><phrase role="special">.</phrase><phrase role="identifier">ss_limit</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="special">>(</phrase> <phrase role="identifier">fc2</phrase><phrase role="special">.</phrase><phrase role="identifier">fc_stack</phrase><phrase role="special">.</phrase><phrase role="identifier">ss_base</phrase><phrase role="special">)</phrase> <phrase role="special">-</phrase> <phrase role="identifier">b2</phrase><phrase role="special">.</phrase><phrase role="identifier">size</phrase><phrase role="special">();</phrase>
|
|
<phrase role="comment">// context fc2 used f2() as context function
|
|
</phrase> <phrase role="identifier">boost_fcontext_make</phrase><phrase role="special">(</phrase> <phrase role="special">&</phrase> <phrase role="identifier">fc2</phrase><phrase role="special">,</phrase> <phrase role="identifier">f2</phrase><phrase role="special">,</phrase> <phrase role="number">0</phrase><phrase role="special">);</phrase>
|
|
|
|
<phrase role="comment">// start context f1; entering f1()
|
|
</phrase> <phrase role="identifier">fprintf</phrase><phrase role="special">(</phrase><phrase role="identifier">stderr</phrase><phrase role="special">,</phrase><phrase role="string">"main: call boost_fcontext_start( & fcm, & fc1)\n"</phrase><phrase role="special">);</phrase>
|
|
<phrase role="identifier">boost_fcontext_start</phrase><phrase role="special">(</phrase> <phrase role="special">&</phrase> <phrase role="identifier">fcm</phrase><phrase role="special">,</phrase> <phrase role="special">&</phrase> <phrase role="identifier">fc1</phrase><phrase role="special">);</phrase>
|
|
|
|
<phrase role="identifier">fprintf</phrase><phrase role="special">(</phrase> <phrase role="identifier">stderr</phrase><phrase role="special">,</phrase> <phrase role="string">"main() returns\n"</phrase><phrase role="special">);</phrase>
|
|
<phrase role="keyword">return</phrase> <phrase role="identifier">EXIT_SUCCESS</phrase><phrase role="special">;</phrase>
|
|
<phrase role="special">}</phrase>
|
|
|
|
<phrase role="identifier">output</phrase><phrase role="special">:</phrase>
|
|
<phrase role="identifier">main</phrase><phrase role="special">:</phrase> <phrase role="identifier">call</phrase> <phrase role="identifier">boost_fcontext_start</phrase><phrase role="special">(</phrase> <phrase role="special">&</phrase> <phrase role="identifier">fcm</phrase><phrase role="special">,</phrase> <phrase role="special">&</phrase> <phrase role="identifier">fc1</phrase><phrase role="special">)</phrase>
|
|
<phrase role="identifier">f1</phrase><phrase role="special">()</phrase> <phrase role="identifier">started</phrase>
|
|
<phrase role="identifier">f1</phrase><phrase role="special">:</phrase> <phrase role="identifier">call</phrase> <phrase role="identifier">boost_fcontext_jump</phrase><phrase role="special">(</phrase> <phrase role="special">&</phrase> <phrase role="identifier">fc1</phrase><phrase role="special">,</phrase> <phrase role="special">&</phrase> <phrase role="identifier">fc2</phrase><phrase role="special">,</phrase> <phrase role="number">0</phrase><phrase role="special">)</phrase>
|
|
<phrase role="identifier">f2</phrase><phrase role="special">()</phrase> <phrase role="identifier">started</phrase>
|
|
<phrase role="identifier">f2</phrase><phrase role="special">:</phrase> <phrase role="identifier">call</phrase> <phrase role="identifier">boost_fcontext_jump</phrase><phrase role="special">(</phrase> <phrase role="special">&</phrase> <phrase role="identifier">fc2</phrase><phrase role="special">,</phrase> <phrase role="special">&</phrase> <phrase role="identifier">fc1</phrase><phrase role="special">,</phrase> <phrase role="number">0</phrase><phrase role="special">)</phrase>
|
|
<phrase role="identifier">f1</phrase><phrase role="special">()</phrase> <phrase role="identifier">returns</phrase>
|
|
<phrase role="identifier">main</phrase><phrase role="special">()</phrase> <phrase role="identifier">returns</phrase>
|
|
</programlisting>
|
|
<para>
|
|
Function <code><phrase role="identifier">boost_fcontext_start</phrase><phrase
|
|
role="special">()</phrase></code> enters the <emphasis>context-function</emphasis>
|
|
<code><phrase role="identifier">f1</phrase><phrase role="special">()</phrase></code>
|
|
by starting context fc1 (context fcm saves the registers of <code><phrase role="identifier">main</phrase><phrase
|
|
role="special">()</phrase></code>). For jumping between context's fc1 and fc2
|
|
<code><phrase role="identifier">boost_fcontext_jump</phrase><phrase role="special">()</phrase></code>
|
|
is called. Because context fcm is chained to fc1, <code><phrase role="identifier">main</phrase><phrase
|
|
role="special">()</phrase></code> is entered (returning from <code><phrase
|
|
role="identifier">boost_fcontext_start</phrase><phrase role="special">()</phrase></code>)
|
|
after context fc1 becomes complete (return from <code><phrase role="identifier">f1</phrase><phrase
|
|
role="special">()</phrase></code>).
|
|
</para>
|
|
<important>
|
|
<para>
|
|
The low level API is the part to port to new platforms.
|
|
</para>
|
|
</important>
|
|
<section id="context.capi.boost_fcontext">
|
|
<title><link linkend="context.capi.boost_fcontext">Struct <code><phrase role="identifier">boost_fcontext_t</phrase></code>
|
|
and related functions</link></title>
|
|
<programlisting><phrase role="keyword">typedef</phrase> <phrase role="keyword">struct</phrase> <phrase role="identifier">boost_fcontext_stack</phrase> <phrase role="identifier">boost_fcontext_stack_t</phrase><phrase role="special">;</phrase>
|
|
<phrase role="keyword">struct</phrase> <phrase role="identifier">boost_fcontext_stack</phrase>
|
|
<phrase role="special">{</phrase>
|
|
<phrase role="keyword">void</phrase> <phrase role="special">*</phrase> <phrase role="identifier">ss_base</phrase><phrase role="special">;</phrase>
|
|
<phrase role="keyword">void</phrase> <phrase role="special">*</phrase> <phrase role="identifier">ss_limit</phrase><phrase role="special">;</phrase>
|
|
<phrase role="special">};</phrase>
|
|
|
|
<phrase role="keyword">typedef</phrase> <phrase role="keyword">struct</phrase> <phrase role="identifier">boost_fcontext</phrase> <phrase role="identifier">boost_fcontext_t</phrase><phrase role="special">;</phrase>
|
|
<phrase role="keyword">struct</phrase> <phrase role="identifier">boost_fcontext</phrase>
|
|
<phrase role="special">{</phrase>
|
|
<phrase role="special"><</phrase> <phrase role="identifier">platform</phrase> <phrase role="identifier">specific</phrase> <phrase role="special">></phrase>
|
|
|
|
<phrase role="identifier">boost_fcontext_stack_t</phrase> <phrase role="identifier">fc_stack</phrase><phrase role="special">;</phrase>
|
|
<phrase role="identifier">boost_fcontext_t</phrase> <phrase role="special">*</phrase> <phrase role="identifier">fc_link</phrase><phrase role="special">;</phrase>
|
|
<phrase role="special">};</phrase>
|
|
|
|
<phrase role="identifier">intptr_t</phrase> <phrase role="identifier">boost_fcontext_start</phrase><phrase role="special">(</phrase> <phrase role="identifier">boost_fcontext_t</phrase> <phrase role="special">*</phrase> <phrase role="identifier">ofc</phrase><phrase role="special">,</phrase> <phrase role="identifier">boost_fcontext_t</phrase> <phrase role="keyword">const</phrase><phrase role="special">*</phrase> <phrase role="identifier">nfc</phrase><phrase role="special">);</phrase>
|
|
<phrase role="identifier">intptr_t</phrase> <phrase role="identifier">boost_fcontext_jump</phrase><phrase role="special">(</phrase> <phrase role="identifier">boost_fcontext_t</phrase> <phrase role="special">*</phrase> <phrase role="identifier">ofc</phrase><phrase role="special">,</phrase> <phrase role="identifier">boost_fcontext_t</phrase> <phrase role="keyword">const</phrase><phrase role="special">*</phrase> <phrase role="identifier">nfc</phrase><phrase role="special">,</phrase> <phrase role="identifier">intptr_t</phrase> <phrase role="identifier">vp</phrase><phrase role="special">);</phrase>
|
|
<phrase role="keyword">void</phrase> <phrase role="identifier">boost_fcontext_make</phrase><phrase role="special">(</phrase> <phrase role="identifier">boost_fcontext_t</phrase> <phrase role="special">*</phrase> <phrase role="identifier">fc</phrase><phrase role="special">,</phrase> <phrase role="keyword">void</phrase><phrase role="special">(*</phrase> <phrase role="identifier">fn</phrase><phrase role="special">)(</phrase><phrase role="keyword">void</phrase><phrase role="special">*),</phrase> <phrase role="identifier">intptr_t</phrase> <phrase role="identifier">p</phrase><phrase role="special">);</phrase>
|
|
</programlisting>
|
|
<anchor id="context.capi.boost_fcontext._code__phrase_role__identifier__ss_base__phrase___code_"/>
|
|
<bridgehead renderas="sect4">
|
|
<link linkend="context.capi.boost_fcontext._code__phrase_role__identifier__ss_base__phrase___code_"><code><phrase
|
|
role="identifier">ss_base</phrase></code></link>
|
|
</bridgehead>
|
|
<variablelist>
|
|
<title></title>
|
|
<varlistentry>
|
|
<term>Member:</term>
|
|
<listitem>
|
|
<para>
|
|
Pointer to the top of the stack.
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
</variablelist>
|
|
<anchor id="context.capi.boost_fcontext._code__phrase_role__identifier__ss_limit__phrase___code_"/>
|
|
<bridgehead renderas="sect4">
|
|
<link linkend="context.capi.boost_fcontext._code__phrase_role__identifier__ss_limit__phrase___code_"><code><phrase
|
|
role="identifier">ss_limit</phrase></code></link>
|
|
</bridgehead>
|
|
<variablelist>
|
|
<title></title>
|
|
<varlistentry>
|
|
<term>Member:</term>
|
|
<listitem>
|
|
<para>
|
|
Pointer to the bottom of the stack.
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
</variablelist>
|
|
<anchor id="context.capi.boost_fcontext._code__phrase_role__identifier__fc_stack__phrase___code_"/>
|
|
<bridgehead renderas="sect4">
|
|
<link linkend="context.capi.boost_fcontext._code__phrase_role__identifier__fc_stack__phrase___code_"><code><phrase
|
|
role="identifier">fc_stack</phrase></code></link>
|
|
</bridgehead>
|
|
<variablelist>
|
|
<title></title>
|
|
<varlistentry>
|
|
<term>Member:</term>
|
|
<listitem>
|
|
<para>
|
|
Tracks the memory for the context's stack.
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
</variablelist>
|
|
<anchor id="context.capi.boost_fcontext._code__phrase_role__identifier__fc_link__phrase___code_"/>
|
|
<bridgehead renderas="sect4">
|
|
<link linkend="context.capi.boost_fcontext._code__phrase_role__identifier__fc_link__phrase___code_"><code><phrase
|
|
role="identifier">fc_link</phrase></code></link>
|
|
</bridgehead>
|
|
<variablelist>
|
|
<title></title>
|
|
<varlistentry>
|
|
<term>Member:</term>
|
|
<listitem>
|
|
<para>
|
|
The address of the next context link in a chain, if any.
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
</variablelist>
|
|
<anchor id="context.capi.boost_fcontext._code__phrase_role__identifier__intptr_t__phrase___phrase_role__identifier__boost_fcontext_start__phrase__phrase_role__special_____phrase___phrase_role__identifier__boost_fcontext_t__phrase___phrase_role__special_____phrase___phrase_role__identifier__ofc__phrase__phrase_role__special_____phrase_____phrase_role__identifier__boost_fcontext_t__phrase___phrase_role__special_____phrase___phrase_role__identifier__nfc__phrase__phrase_role__special_____phrase___code_"/>
|
|
<bridgehead renderas="sect4">
|
|
<link linkend="context.capi.boost_fcontext._code__phrase_role__identifier__intptr_t__phrase___phrase_role__identifier__boost_fcontext_start__phrase__phrase_role__special_____phrase___phrase_role__identifier__boost_fcontext_t__phrase___phrase_role__special_____phrase___phrase_role__identifier__ofc__phrase__phrase_role__special_____phrase_____phrase_role__identifier__boost_fcontext_t__phrase___phrase_role__special_____phrase___phrase_role__identifier__nfc__phrase__phrase_role__special_____phrase___code_"><code><phrase
|
|
role="identifier">intptr_t</phrase> <phrase role="identifier">boost_fcontext_start</phrase><phrase
|
|
role="special">(</phrase> <phrase role="identifier">boost_fcontext_t</phrase>
|
|
<phrase role="special">*</phrase> <phrase role="identifier">ofc</phrase><phrase
|
|
role="special">,</phrase> <phrase role="identifier">boost_fcontext_t</phrase>
|
|
<phrase role="special">*</phrase> <phrase role="identifier">nfc</phrase><phrase
|
|
role="special">)</phrase></code></link>
|
|
</bridgehead>
|
|
<variablelist>
|
|
<title></title>
|
|
<varlistentry>
|
|
<term>Effects:</term>
|
|
<listitem>
|
|
<para>
|
|
Stores the current context data (stack pointer, instruction pointer,
|
|
and CPU registers) to <code><phrase role="special">*</phrase><phrase
|
|
role="identifier">ofc</phrase></code> and restores the context data
|
|
from <code><phrase role="special">*</phrase><phrase role="identifier">nfc</phrase></code>,
|
|
which implies jumping to <code><phrase role="special">*</phrase><phrase
|
|
role="identifier">nfc</phrase></code>'s execution context. This function
|
|
must be called when first entering <code><phrase role="special">*</phrase><phrase
|
|
role="identifier">nfc</phrase></code>'s execution context.
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
<varlistentry>
|
|
<term>Returns:</term>
|
|
<listitem>
|
|
<para>
|
|
The result of calling <code><phrase role="identifier">boost_fcontext_jump</phrase><phrase
|
|
role="special">()</phrase></code>.
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
</variablelist>
|
|
<anchor id="context.capi.boost_fcontext._code__phrase_role__identifier__intptr_t__phrase___phrase_role__identifier__boost_fcontext_jump__phrase__phrase_role__special_____phrase___phrase_role__identifier__boost_fcontext_t__phrase___phrase_role__special_____phrase___phrase_role__identifier__ofc__phrase__phrase_role__special_____phrase___phrase_role__identifier__boost_fcontext_t__phrase___phrase_role__special_____phrase___phrase_role__identifier__nfc__phrase__phrase_role__special_____phrase___phrase_role__identifier__intptr_t__phrase___phrase_role__identifier__p__phrase__phrase_role__special_____phrase___code_"/>
|
|
<bridgehead renderas="sect4">
|
|
<link linkend="context.capi.boost_fcontext._code__phrase_role__identifier__intptr_t__phrase___phrase_role__identifier__boost_fcontext_jump__phrase__phrase_role__special_____phrase___phrase_role__identifier__boost_fcontext_t__phrase___phrase_role__special_____phrase___phrase_role__identifier__ofc__phrase__phrase_role__special_____phrase___phrase_role__identifier__boost_fcontext_t__phrase___phrase_role__special_____phrase___phrase_role__identifier__nfc__phrase__phrase_role__special_____phrase___phrase_role__identifier__intptr_t__phrase___phrase_role__identifier__p__phrase__phrase_role__special_____phrase___code_"><code><phrase
|
|
role="identifier">intptr_t</phrase> <phrase role="identifier">boost_fcontext_jump</phrase><phrase
|
|
role="special">(</phrase> <phrase role="identifier">boost_fcontext_t</phrase>
|
|
<phrase role="special">*</phrase> <phrase role="identifier">ofc</phrase><phrase
|
|
role="special">,</phrase> <phrase role="identifier">boost_fcontext_t</phrase>
|
|
<phrase role="special">*</phrase> <phrase role="identifier">nfc</phrase><phrase
|
|
role="special">,</phrase> <phrase role="identifier">intptr_t</phrase> <phrase
|
|
role="identifier">p</phrase><phrase role="special">)</phrase></code></link>
|
|
</bridgehead>
|
|
<variablelist>
|
|
<title></title>
|
|
<varlistentry>
|
|
<term>Effects:</term>
|
|
<listitem>
|
|
<para>
|
|
Stores the current context data (stack pointer, instruction pointer,
|
|
and CPU registers) to <code><phrase role="special">*</phrase><phrase
|
|
role="identifier">ofc</phrase></code> and restores the context data
|
|
from <code><phrase role="special">*</phrase><phrase role="identifier">nfc</phrase></code>,
|
|
which implies jumping to <code><phrase role="special">*</phrase><phrase
|
|
role="identifier">nfc</phrase></code>'s execution context. The intptr_t
|
|
argument, <code><phrase role="identifier">p</phrase></code>, is passed
|
|
to the current context to be returned by the most recent call to <code><phrase
|
|
role="identifier">boost_fcontext_start</phrase><phrase role="special">()</phrase></code>
|
|
or <code><phrase role="identifier">boost_fcontext_jump</phrase><phrase
|
|
role="special">()</phrase></code> in the same thread.
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
<varlistentry>
|
|
<term>Returns:</term>
|
|
<listitem>
|
|
<para>
|
|
The third pointer argument passed to the most recent call to <code><phrase
|
|
role="identifier">boost_fcontext_jump</phrase><phrase role="special">()</phrase></code>,
|
|
if any.
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
</variablelist>
|
|
<anchor id="context.capi.boost_fcontext._code__phrase_role__keyword__void__phrase___phrase_role__identifier__boost_fcontext_make__phrase__phrase_role__special_____phrase___phrase_role__identifier__boost_fcontext_t__phrase___phrase_role__special_____phrase___phrase_role__identifier__fc__phrase__phrase_role__special_____phrase___phrase_role__keyword__void__phrase__phrase_role__special______phrase__phrase_role__identifier__fn__phrase__phrase_role__special______phrase__phrase_role__identifier__intptr_t__phrase__phrase_role__special______phrase___phrase_role__identifier__intptr_t__phrase___phrase_role__identifier__p__phrase__phrase_role__special_____phrase___code_"/>
|
|
<bridgehead renderas="sect4">
|
|
<link linkend="context.capi.boost_fcontext._code__phrase_role__keyword__void__phrase___phrase_role__identifier__boost_fcontext_make__phrase__phrase_role__special_____phrase___phrase_role__identifier__boost_fcontext_t__phrase___phrase_role__special_____phrase___phrase_role__identifier__fc__phrase__phrase_role__special_____phrase___phrase_role__keyword__void__phrase__phrase_role__special______phrase__phrase_role__identifier__fn__phrase__phrase_role__special______phrase__phrase_role__identifier__intptr_t__phrase__phrase_role__special______phrase___phrase_role__identifier__intptr_t__phrase___phrase_role__identifier__p__phrase__phrase_role__special_____phrase___code_"><code><phrase
|
|
role="keyword">void</phrase> <phrase role="identifier">boost_fcontext_make</phrase><phrase
|
|
role="special">(</phrase> <phrase role="identifier">boost_fcontext_t</phrase>
|
|
<phrase role="special">*</phrase> <phrase role="identifier">fc</phrase><phrase
|
|
role="special">,</phrase> <phrase role="keyword">void</phrase><phrase role="special">(*</phrase><phrase
|
|
role="identifier">fn</phrase><phrase role="special">)(</phrase><phrase role="identifier">intptr_t</phrase><phrase
|
|
role="special">),</phrase> <phrase role="identifier">intptr_t</phrase> <phrase
|
|
role="identifier">p</phrase><phrase role="special">)</phrase></code></link>
|
|
</bridgehead>
|
|
<variablelist>
|
|
<title></title>
|
|
<varlistentry>
|
|
<term>Precondition:</term>
|
|
<listitem>
|
|
<para>
|
|
A stack is applied to <code><phrase role="special">*</phrase><phrase
|
|
role="identifier">fc</phrase></code> before <code><phrase role="identifier">boost_fcontext_make</phrase><phrase
|
|
role="special">()</phrase></code> is called. If a successor context
|
|
should be executed after <code><phrase role="special">*</phrase><phrase
|
|
role="identifier">fc</phrase></code> finishes the address of the successor
|
|
context must be stored ir <code><phrase role="identifier">fc</phrase><phrase
|
|
role="special">-></phrase><phrase role="identifier">fc_link</phrase></code>.
|
|
The application exits otherwise.
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
<varlistentry>
|
|
<term>Effects:</term>
|
|
<listitem>
|
|
<para>
|
|
Modifies <code><phrase role="special">*</phrase><phrase role="identifier">fc</phrase></code>
|
|
in order to execute <code><phrase role="identifier">fn</phrase></code>
|
|
with argument <code><phrase role="identifier">p</phrase></code> when
|
|
the context is activated next.
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
</variablelist>
|
|
</section>
|
|
</section>
|
|
<section id="context.examples">
|
|
<title><link linkend="context.examples">Examples</link></title>
|
|
<section id="context.examples.enumerator">
|
|
<title><link linkend="context.examples.enumerator">Enumerator</link></title>
|
|
<para>
|
|
Class <code><phrase role="identifier">power</phrase></code> computes the
|
|
power of <code><phrase role="identifier">number</phrase></code> for the exponents
|
|
in the range from <code><phrase role="number">1</phrase></code> to <code><phrase
|
|
role="identifier">number</phrase></code> (constructor arguments).
|
|
</para>
|
|
|
|
<programlisting><phrase role="keyword">class</phrase> <phrase role="identifier">power</phrase>
|
|
<phrase role="special">{</phrase>
|
|
<phrase role="keyword">public</phrase><phrase role="special">:</phrase>
|
|
<phrase role="identifier">power</phrase><phrase role="special">(</phrase> <phrase role="keyword">int</phrase> <phrase role="identifier">number</phrase><phrase role="special">,</phrase> <phrase role="keyword">int</phrase> <phrase role="identifier">exponent</phrase><phrase role="special">);</phrase>
|
|
|
|
<phrase role="keyword">bool</phrase> <phrase role="identifier">get</phrase><phrase role="special">(</phrase> <phrase role="keyword">int</phrase> <phrase role="special">&</phrase> <phrase role="identifier">data</phrase><phrase role="special">);</phrase>
|
|
<phrase role="special">};</phrase>
|
|
</programlisting>
|
|
<para>
|
|
Each call to <code><phrase role="identifier">power</phrase><phrase role="special">::</phrase><phrase
|
|
role="identifier">get</phrase><phrase role="special">()</phrase></code> returns
|
|
a boolean indicating a vaild result. The reference argument <code><phrase
|
|
role="identifier">data</phrase></code> contains the computed result.
|
|
</para>
|
|
|
|
<programlisting><phrase role="keyword">int</phrase> <phrase role="identifier">main</phrase><phrase role="special">()</phrase>
|
|
<phrase role="special">{</phrase>
|
|
<phrase role="special">{</phrase>
|
|
<phrase role="identifier">power</phrase> <phrase role="identifier">pw</phrase><phrase role="special">(</phrase> <phrase role="number">2</phrase><phrase role="special">,</phrase> <phrase role="number">8</phrase><phrase role="special">);</phrase>
|
|
<phrase role="keyword">int</phrase> <phrase role="identifier">i</phrase><phrase role="special">;</phrase>
|
|
<phrase role="comment">// pw.get() returns the computed result
|
|
</phrase> <phrase role="comment">// for each value from 1 to 8
|
|
</phrase> <phrase role="comment">// return value of pw.get() indicates that
|
|
</phrase> <phrase role="comment">// a valid result
|
|
</phrase> <phrase role="keyword">while</phrase> <phrase role="special">(</phrase> <phrase role="identifier">pw</phrase><phrase role="special">.</phrase><phrase role="identifier">get</phrase><phrase role="special">(</phrase> <phrase role="identifier">i</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">cout</phrase> <phrase role="special"><<</phrase> <phrase role="identifier">i</phrase> <phrase role="special"><<</phrase> <phrase role="string">" "</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">cout</phrase> <phrase role="special"><<</phrase> <phrase role="string">"\nDone"</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">EXIT_SUCCESS</phrase><phrase role="special">;</phrase>
|
|
<phrase role="special">}</phrase>
|
|
|
|
<phrase role="identifier">output</phrase><phrase role="special">:</phrase>
|
|
<phrase role="number">2</phrase> <phrase role="number">4</phrase> <phrase role="number">8</phrase> <phrase role="number">16</phrase> <phrase role="number">32</phrase> <phrase role="number">64</phrase> <phrase role="number">128</phrase> <phrase role="number">256</phrase>
|
|
<phrase role="identifier">Done</phrase>
|
|
</programlisting>
|
|
<para>
|
|
In <code><phrase role="identifier">main</phrase><phrase role="special">()</phrase></code>
|
|
an instance of <code><phrase role="identifier">power</phrase></code> is constructed,
|
|
computing the power of 2 for exponents in the range from 1 to 8 by each call
|
|
to <code><phrase role="identifier">power</phrase><phrase role="special">::</phrase><phrase
|
|
role="identifier">get</phrase><phrase role="special">()</phrase></code>.
|
|
</para>
|
|
<para>
|
|
It is intended to compute the numbers in a loop and transfer each result
|
|
to the caller without disrupting the loop.
|
|
</para>
|
|
<para>
|
|
<emphasis role="bold">Boost.Context</emphasis> can be used to implement an
|
|
equivalent to C#'s <code><phrase role="identifier">yield</phrase></code>
|
|
facility (C# provides the keywords <code><phrase role="identifier">yield</phrase>
|
|
<phrase role="keyword">return</phrase></code> and <code><phrase role="identifier">yield</phrase>
|
|
<phrase role="keyword">break</phrase></code>). For this purpose helper-template
|
|
<code><phrase role="identifier">enumerator</phrase></code> is defined containing
|
|
the private member <code><phrase role="identifier">ctx_</phrase></code> executing
|
|
<code><phrase role="identifier">enumerate</phrase><phrase role="special">()</phrase></code>
|
|
as <emphasis>context-function</emphasis>.
|
|
</para>
|
|
|
|
<programlisting><phrase role="keyword">template</phrase><phrase role="special"><</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">T</phrase> <phrase role="special">></phrase>
|
|
<phrase role="keyword">class</phrase> <phrase role="identifier">enumerator</phrase> <phrase role="special">{</phrase>
|
|
<phrase role="keyword">private</phrase><phrase role="special">:</phrase>
|
|
<phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">contexts</phrase><phrase role="special">::</phrase><phrase role="identifier">context</phrase> <phrase role="identifier">ctx_</phrase><phrase role="special">;</phrase>
|
|
<phrase role="keyword">bool</phrase> <phrase role="identifier">complete_</phrase><phrase role="special">;</phrase>
|
|
<phrase role="keyword">bool</phrase> <phrase role="identifier">do_unwind_</phrase><phrase role="special">;</phrase>
|
|
<phrase role="keyword">bool</phrase> <phrase role="identifier">started_</phrase><phrase role="special">;</phrase>
|
|
|
|
<phrase role="keyword">static</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">run</phrase><phrase role="special">(</phrase> <phrase role="identifier">enumerator</phrase> <phrase role="special">*</phrase> <phrase role="identifier">self</phrase><phrase role="special">)</phrase>
|
|
<phrase role="special">{</phrase> <phrase role="identifier">self</phrase><phrase role="special">-></phrase><phrase role="identifier">enumerate</phrase><phrase role="special">();</phrase> <phrase role="special">}</phrase>
|
|
|
|
<phrase role="keyword">protected</phrase><phrase role="special">:</phrase>
|
|
<phrase role="keyword">virtual</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">enumerate</phrase><phrase role="special">()</phrase> <phrase role="special">=</phrase> <phrase role="number">0</phrase><phrase role="special">;</phrase>
|
|
|
|
<phrase role="keyword">void</phrase> <phrase role="identifier">yield_return</phrase><phrase role="special">(</phrase> <phrase role="identifier">T</phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">v</phrase><phrase role="special">)</phrase>
|
|
<phrase role="special">{</phrase>
|
|
<phrase role="identifier">intptr_t</phrase> <phrase role="identifier">vp</phrase> <phrase role="special">=</phrase> <phrase role="keyword">reinterpret_cast</phrase><phrase role="special"><</phrase> <phrase role="identifier">intptr_t</phrase> <phrase role="special">>(</phrase> <phrase role="special">&</phrase> <phrase role="identifier">v</phrase><phrase role="special">);</phrase>
|
|
<phrase role="identifier">ctx_</phrase><phrase role="special">.</phrase><phrase role="identifier">suspend</phrase><phrase role="special">(</phrase> <phrase role="identifier">vp</phrase><phrase role="special">);</phrase>
|
|
<phrase role="special">}</phrase>
|
|
|
|
<phrase role="keyword">void</phrase> <phrase role="identifier">yield_break</phrase><phrase role="special">()</phrase>
|
|
<phrase role="special">{</phrase>
|
|
<phrase role="identifier">complete_</phrase> <phrase role="special">=</phrase> <phrase role="keyword">true</phrase><phrase role="special">;</phrase>
|
|
<phrase role="identifier">ctx_</phrase><phrase role="special">.</phrase><phrase role="identifier">suspend</phrase><phrase role="special">();</phrase>
|
|
<phrase role="special">}</phrase>
|
|
|
|
<phrase role="keyword">public</phrase><phrase role="special">:</phrase>
|
|
<phrase role="identifier">enumerator</phrase><phrase role="special">(</phrase> <phrase role="keyword">bool</phrase> <phrase role="identifier">do_unwind</phrase> <phrase role="special">=</phrase> <phrase role="keyword">true</phrase><phrase role="special">):</phrase>
|
|
<phrase role="identifier">ctx_</phrase><phrase role="special">(</phrase>
|
|
<phrase role="special">&</phrase> <phrase role="identifier">enumerator</phrase><phrase role="special">::</phrase><phrase role="identifier">run</phrase><phrase role="special">,</phrase> <phrase role="keyword">this</phrase><phrase role="special">,</phrase>
|
|
<phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">contexts</phrase><phrase role="special">::</phrase><phrase role="identifier">default_stacksize</phrase><phrase role="special">(),</phrase>
|
|
<phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">contexts</phrase><phrase role="special">::</phrase><phrase role="identifier">no_stack_unwind</phrase><phrase role="special">,</phrase>
|
|
<phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">contexts</phrase><phrase role="special">::</phrase><phrase role="identifier">return_to_caller</phrase><phrase role="special">),</phrase>
|
|
<phrase role="identifier">complete_</phrase><phrase role="special">(</phrase> <phrase role="keyword">false</phrase><phrase role="special">),</phrase>
|
|
<phrase role="identifier">do_unwind_</phrase><phrase role="special">(</phrase> <phrase role="identifier">do_unwind</phrase><phrase role="special">),</phrase>
|
|
<phrase role="identifier">started_</phrase><phrase role="special">(</phrase> <phrase role="keyword">false</phrase><phrase role="special">)</phrase>
|
|
<phrase role="special">{}</phrase>
|
|
|
|
<phrase role="special">~</phrase><phrase role="identifier">enumerator</phrase><phrase role="special">()</phrase>
|
|
<phrase role="special">{</phrase>
|
|
<phrase role="keyword">if</phrase> <phrase role="special">(</phrase> <phrase role="identifier">do_unwind_</phrase> <phrase role="special">&&</phrase> <phrase role="special">!</phrase> <phrase role="identifier">ctx_</phrase><phrase role="special">.</phrase><phrase role="identifier">is_complete</phrase><phrase role="special">()</phrase> <phrase role="special">)</phrase>
|
|
<phrase role="identifier">ctx_</phrase><phrase role="special">.</phrase><phrase role="identifier">unwind_stack</phrase><phrase role="special">();</phrase>
|
|
<phrase role="special">}</phrase>
|
|
|
|
<phrase role="keyword">bool</phrase> <phrase role="identifier">get</phrase><phrase role="special">(</phrase> <phrase role="identifier">T</phrase> <phrase role="special">&</phrase> <phrase role="identifier">result</phrase><phrase role="special">)</phrase>
|
|
<phrase role="special">{</phrase>
|
|
<phrase role="identifier">intptr_t</phrase> <phrase role="identifier">vp</phrase> <phrase role="special">=</phrase> <phrase role="number">0</phrase><phrase role="special">;</phrase>
|
|
<phrase role="keyword">if</phrase> <phrase role="special">(</phrase> <phrase role="special">!</phrase> <phrase role="identifier">started_</phrase><phrase role="special">)</phrase>
|
|
<phrase role="special">{</phrase>
|
|
<phrase role="identifier">started_</phrase> <phrase role="special">=</phrase> <phrase role="keyword">true</phrase><phrase role="special">;</phrase>
|
|
<phrase role="identifier">vp</phrase> <phrase role="special">=</phrase> <phrase role="identifier">ctx_</phrase><phrase role="special">.</phrase><phrase role="identifier">start</phrase><phrase role="special">();</phrase>
|
|
<phrase role="special">}</phrase>
|
|
<phrase role="keyword">else</phrase>
|
|
<phrase role="special">{</phrase>
|
|
<phrase role="identifier">vp</phrase> <phrase role="special">=</phrase> <phrase role="identifier">ctx_</phrase><phrase role="special">.</phrase><phrase role="identifier">resume</phrase><phrase role="special">();</phrase>
|
|
<phrase role="special">}</phrase>
|
|
<phrase role="keyword">if</phrase> <phrase role="special">(</phrase> <phrase role="identifier">vp</phrase><phrase role="special">)</phrase> <phrase role="identifier">result</phrase> <phrase role="special">=</phrase> <phrase role="special">*</phrase> <phrase role="keyword">reinterpret_cast</phrase><phrase role="special"><</phrase> <phrase role="identifier">T</phrase> <phrase role="special">*</phrase> <phrase role="special">>(</phrase> <phrase role="identifier">vp</phrase><phrase role="special">);</phrase>
|
|
<phrase role="keyword">return</phrase> <phrase role="special">!</phrase> <phrase role="special">(</phrase> <phrase role="identifier">complete_</phrase> <phrase role="special">||</phrase> <phrase role="identifier">ctx_</phrase><phrase role="special">.</phrase><phrase role="identifier">is_complete</phrase><phrase role="special">()</phrase> <phrase role="special">);</phrase>
|
|
<phrase role="special">}</phrase>
|
|
<phrase role="special">};</phrase>
|
|
</programlisting>
|
|
<para>
|
|
Member-function <code><phrase role="identifier">get</phrase><phrase role="special">()</phrase></code>
|
|
starts / resumes <code><phrase role="identifier">context</phrase> </code>ctx_<code>
|
|
<phrase role="identifier">by</phrase> <phrase role="identifier">calling</phrase>
|
|
<emphasis>context::start()</emphasis> <phrase role="special">/</phrase>
|
|
<emphasis>context::resume()</emphasis> <phrase role="identifier">so</phrase>
|
|
<phrase role="identifier">that</phrase> </code>enumerate()` is (re-)entered.
|
|
Functions <emphasis>context::start()</emphasis> / <emphasis>context::resume()</emphasis>
|
|
return the computed values.
|
|
</para>
|
|
<para>
|
|
<code><phrase role="identifier">yield_return</phrase><phrase role="special">()</phrase></code>
|
|
(equivalent to C# <code><phrase role="identifier">yield</phrase> <phrase
|
|
role="keyword">return</phrase></code>) jumps to <code><phrase role="identifier">get</phrase><phrase
|
|
role="special">()</phrase></code> transfering the execution control and computed
|
|
value back. With <code><phrase role="identifier">yield_break</phrase><phrase
|
|
role="special">()</phrase></code> (equivalent to C# <code><phrase role="identifier">yield</phrase>
|
|
<phrase role="keyword">break</phrase></code>) the control is unconditionally
|
|
returned to <code><phrase role="identifier">get</phrase><phrase role="special">()</phrase></code>
|
|
to signal the end of iteration.
|
|
</para>
|
|
<para>
|
|
Class <code><phrase role="identifier">power</phrase></code> derives from
|
|
<code><phrase role="identifier">enumerate</phrase><phrase role="special"><</phrase>
|
|
<phrase role="keyword">int</phrase> <phrase role="special">></phrase></code>
|
|
and its implementation of <code><phrase role="identifier">enumerate</phrase><phrase
|
|
role="special">()</phrase></code> computes the power in a local loop. Each
|
|
computed result is transfered to <code><phrase role="identifier">get</phrase><phrase
|
|
role="special">()</phrase></code> by calling <code><phrase role="identifier">yield_return</phrase><phrase
|
|
role="special">()</phrase></code>.
|
|
</para>
|
|
|
|
<programlisting><phrase role="keyword">class</phrase> <phrase role="identifier">power</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <phrase role="identifier">enumerator</phrase><phrase role="special"><</phrase> <phrase role="keyword">int</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">enumerate</phrase><phrase role="special">()</phrase>
|
|
<phrase role="special">{</phrase>
|
|
<phrase role="keyword">int</phrase> <phrase role="identifier">counter</phrase> <phrase role="special">=</phrase> <phrase role="number">0</phrase><phrase role="special">;</phrase>
|
|
<phrase role="keyword">int</phrase> <phrase role="identifier">result</phrase> <phrase role="special">=</phrase> <phrase role="number">1</phrase><phrase role="special">;</phrase>
|
|
<phrase role="comment">// local scoped while loop
|
|
</phrase> <phrase role="keyword">while</phrase> <phrase role="special">(</phrase> <phrase role="identifier">counter</phrase><phrase role="special">++</phrase> <phrase role="special"><</phrase> <phrase role="identifier">exponent_</phrase><phrase role="special">)</phrase>
|
|
<phrase role="special">{</phrase>
|
|
<phrase role="comment">// compute the value
|
|
</phrase> <phrase role="identifier">result</phrase> <phrase role="special">=</phrase> <phrase role="identifier">result</phrase> <phrase role="special">*</phrase> <phrase role="identifier">number_</phrase><phrase role="special">;</phrase>
|
|
|
|
<phrase role="comment">// return the value by jumping to calling context
|
|
</phrase> <phrase role="comment">// == jump to while-loop in main()
|
|
</phrase> <phrase role="identifier">yield_return</phrase><phrase role="special">(</phrase> <phrase role="identifier">result</phrase><phrase role="special">);</phrase>
|
|
<phrase role="special">}</phrase>
|
|
<phrase role="special">}</phrase>
|
|
|
|
<phrase role="keyword">int</phrase> <phrase role="identifier">number_</phrase><phrase role="special">;</phrase>
|
|
<phrase role="keyword">int</phrase> <phrase role="identifier">exponent_</phrase><phrase role="special">;</phrase>
|
|
|
|
<phrase role="keyword">public</phrase><phrase role="special">:</phrase>
|
|
<phrase role="identifier">power</phrase><phrase role="special">(</phrase> <phrase role="keyword">int</phrase> <phrase role="identifier">number</phrase><phrase role="special">,</phrase> <phrase role="keyword">int</phrase> <phrase role="identifier">exponent</phrase><phrase role="special">)</phrase> <phrase role="special">:</phrase>
|
|
<phrase role="identifier">number_</phrase><phrase role="special">(</phrase> <phrase role="identifier">number</phrase><phrase role="special">),</phrase> <phrase role="identifier">exponent_</phrase><phrase role="special">(</phrase> <phrase role="identifier">exponent</phrase><phrase role="special">)</phrase>
|
|
<phrase role="special">{}</phrase>
|
|
<phrase role="special">};</phrase>
|
|
</programlisting>
|
|
</section>
|
|
<section id="context.examples.continuation">
|
|
<title><link linkend="context.examples.continuation">Continuation</link></title>
|
|
<para>
|
|
Adapted from <ulink url="https://code.google.com/p/jyield/wiki/Samples">the
|
|
Java continuation</ulink> documentation example.
|
|
</para>
|
|
<para>
|
|
Class <code><phrase role="identifier">continuation</phrase></code> provides
|
|
the ability for a functor to suspend itself. The functor is required to accept
|
|
a const reference to its own <code><phrase role="identifier">continuation</phrase></code>
|
|
instance.
|
|
</para>
|
|
|
|
<programlisting><phrase role="keyword">class</phrase> <phrase role="identifier">continuation</phrase>
|
|
<phrase role="special">{</phrase>
|
|
<phrase role="keyword">private</phrase><phrase role="special">:</phrase>
|
|
<phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">contexts</phrase><phrase role="special">::</phrase><phrase role="identifier">context</phrase> <phrase role="identifier">ctx_</phrase><phrase role="special">;</phrase>
|
|
<phrase role="identifier">boost</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="identifier">continuation</phrase> <phrase role="special">&)</phrase> <phrase role="special">></phrase> <phrase role="identifier">fn_</phrase><phrase role="special">;</phrase>
|
|
<phrase role="keyword">bool</phrase> <phrase role="identifier">started_</phrase><phrase role="special">;</phrase>
|
|
|
|
<phrase role="keyword">void</phrase> <phrase role="identifier">trampoline_</phrase><phrase role="special">()</phrase>
|
|
<phrase role="special">{</phrase> <phrase role="identifier">fn_</phrase><phrase role="special">(</phrase> <phrase role="special">*</phrase> <phrase role="keyword">this</phrase><phrase role="special">);</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="identifier">boost</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="identifier">continuation</phrase> <phrase role="special">&)</phrase> <phrase role="special">></phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">fn</phrase><phrase role="special">)</phrase> <phrase role="special">:</phrase>
|
|
<phrase role="identifier">ctx_</phrase><phrase role="special">(</phrase>
|
|
<phrase role="special">&</phrase> <phrase role="identifier">continuation</phrase><phrase role="special">::</phrase><phrase role="identifier">trampoline_</phrase><phrase role="special">,</phrase> <phrase role="keyword">this</phrase><phrase role="special">,</phrase>
|
|
<phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">contexts</phrase><phrase role="special">::</phrase><phrase role="identifier">default_stacksize</phrase><phrase role="special">(),</phrase>
|
|
<phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">contexts</phrase><phrase role="special">::</phrase><phrase role="identifier">no_stack_unwind</phrase><phrase role="special">,</phrase>
|
|
<phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">contexts</phrase><phrase role="special">::</phrase><phrase role="identifier">return_to_caller</phrase><phrase role="special">),</phrase>
|
|
<phrase role="keyword">false</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="identifier">started_</phrase><phrase role="special">(</phrase> <phrase role="keyword">false</phrase><phrase role="special">)</phrase>
|
|
<phrase role="special">{}</phrase>
|
|
|
|
<phrase role="keyword">void</phrase> <phrase role="identifier">resume</phrase><phrase role="special">()</phrase>
|
|
<phrase role="special">{</phrase>
|
|
<phrase role="keyword">if</phrase> <phrase role="special">(</phrase> <phrase role="special">!</phrase> <phrase role="identifier">started_</phrase><phrase role="special">)</phrase>
|
|
<phrase role="special">{</phrase>
|
|
<phrase role="identifier">started_</phrase> <phrase role="special">=</phrase> <phrase role="keyword">true</phrase><phrase role="special">;</phrase>
|
|
<phrase role="identifier">ctx_</phrase><phrase role="special">.</phrase><phrase role="identifier">start</phrase><phrase role="special">();</phrase>
|
|
<phrase role="special">}</phrase>
|
|
<phrase role="keyword">else</phrase> <phrase role="identifier">ctx_</phrase><phrase role="special">.</phrase><phrase role="identifier">resume</phrase><phrase role="special">();</phrase>
|
|
<phrase role="special">}</phrase>
|
|
|
|
<phrase role="keyword">void</phrase> <phrase role="identifier">suspend</phrase><phrase role="special">()</phrase>
|
|
<phrase role="special">{</phrase> <phrase role="identifier">ctx_</phrase><phrase role="special">.</phrase><phrase role="identifier">suspend</phrase><phrase role="special">();</phrase> <phrase role="special">}</phrase>
|
|
|
|
<phrase role="keyword">bool</phrase> <phrase role="identifier">is_complete</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase>
|
|
<phrase role="special">{</phrase> <phrase role="keyword">return</phrase> <phrase role="identifier">ctx_</phrase><phrase role="special">.</phrase><phrase role="identifier">is_complete</phrase><phrase role="special">();</phrase> <phrase role="special">}</phrase>
|
|
<phrase role="special">};</phrase>
|
|
</programlisting>
|
|
<para>
|
|
The functions <code><phrase role="identifier">first</phrase><phrase role="special">()</phrase></code>
|
|
and <code><phrase role="identifier">second</phrase><phrase role="special">()</phrase></code>
|
|
are so-called coroutines running 'quasi parallel'. Please note that the variables
|
|
in the for-loops have local scope.
|
|
</para>
|
|
|
|
<programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">first</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">"started first! "</phrase><phrase role="special">;</phrase>
|
|
<phrase role="keyword">for</phrase> <phrase role="special">(</phrase> <phrase role="keyword">int</phrase> <phrase role="identifier">i</phrase> <phrase role="special">=</phrase> <phrase role="number">0</phrase><phrase role="special">;</phrase> <phrase role="identifier">i</phrase> <phrase role="special"><</phrase> <phrase role="number">10</phrase><phrase role="special">;</phrase> <phrase role="special">++</phrase><phrase role="identifier">i</phrase><phrase role="special">)</phrase>
|
|
<phrase role="special">{</phrase>
|
|
<phrase role="identifier">c</phrase><phrase role="special">.</phrase><phrase role="identifier">suspend</phrase><phrase role="special">();</phrase> <phrase role="comment">// jump back to main()
|
|
</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cout</phrase> <phrase role="special"><<</phrase> <phrase role="string">"a"</phrase> <phrase role="special"><<</phrase> <phrase role="identifier">i</phrase><phrase role="special">;</phrase> <phrase role="comment">// output
|
|
</phrase> <phrase role="special">}</phrase>
|
|
<phrase role="special">}</phrase>
|
|
|
|
<phrase role="keyword">void</phrase> <phrase role="identifier">second</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">"started second! "</phrase><phrase role="special">;</phrase>
|
|
<phrase role="keyword">for</phrase> <phrase role="special">(</phrase> <phrase role="keyword">int</phrase> <phrase role="identifier">i</phrase> <phrase role="special">=</phrase> <phrase role="number">0</phrase><phrase role="special">;</phrase> <phrase role="identifier">i</phrase> <phrase role="special"><</phrase> <phrase role="number">10</phrase><phrase role="special">;</phrase> <phrase role="special">++</phrase><phrase role="identifier">i</phrase><phrase role="special">)</phrase>
|
|
<phrase role="special">{</phrase>
|
|
<phrase role="identifier">c</phrase><phrase role="special">.</phrase><phrase role="identifier">suspend</phrase><phrase role="special">();</phrase> <phrase role="comment">// jump back to main()
|
|
</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cout</phrase> <phrase role="special"><<</phrase> <phrase role="string">"b"</phrase> <phrase role="special"><<</phrase> <phrase role="identifier">i</phrase><phrase role="special">;</phrase> <phrase role="comment">// output
|
|
</phrase> <phrase role="special">}</phrase>
|
|
<phrase role="special">}</phrase>
|
|
|
|
<phrase role="keyword">int</phrase> <phrase role="identifier">main</phrase><phrase role="special">(</phrase> <phrase role="keyword">int</phrase> <phrase role="identifier">argc</phrase><phrase role="special">,</phrase> <phrase role="keyword">char</phrase> <phrase role="special">*</phrase> <phrase role="identifier">argv</phrase><phrase role="special">[])</phrase>
|
|
<phrase role="special">{</phrase>
|
|
<phrase role="special">{</phrase>
|
|
<phrase role="identifier">continuation</phrase> <phrase role="identifier">c1</phrase><phrase role="special">(</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">bind</phrase><phrase role="special">(</phrase> <phrase role="identifier">first</phrase><phrase role="special">,</phrase> <phrase role="identifier">_1</phrase><phrase role="special">)</phrase> <phrase role="special">);</phrase>
|
|
<phrase role="identifier">continuation</phrase> <phrase role="identifier">c2</phrase><phrase role="special">(</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">bind</phrase><phrase role="special">(</phrase> <phrase role="identifier">second</phrase><phrase role="special">,</phrase> <phrase role="identifier">_1</phrase><phrase role="special">)</phrase> <phrase role="special">);</phrase>
|
|
<phrase role="comment">// loop until coroutines c1 and c2 are complete
|
|
</phrase> <phrase role="keyword">while</phrase> <phrase role="special">(</phrase> <phrase role="special">!</phrase> <phrase role="identifier">c1</phrase><phrase role="special">.</phrase><phrase role="identifier">is_complete</phrase><phrase role="special">()</phrase> <phrase role="special">&&</phrase> <phrase role="special">!</phrase> <phrase role="identifier">c2</phrase><phrase role="special">.</phrase><phrase role="identifier">is_complete</phrase><phrase role="special">()</phrase> <phrase role="special">)</phrase> <phrase role="special">{</phrase>
|
|
<phrase role="identifier">c1</phrase><phrase role="special">.</phrase><phrase role="identifier">resume</phrase><phrase role="special">();</phrase> <phrase role="comment">// call coroutine c1 -> first()
|
|
</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cout</phrase> <phrase role="special"><<</phrase> <phrase role="string">" "</phrase><phrase role="special">;</phrase>
|
|
<phrase role="identifier">c2</phrase><phrase role="special">.</phrase><phrase role="identifier">resume</phrase><phrase role="special">();</phrase> <phrase role="comment">// call coroutine c2 -> second()
|
|
</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cout</phrase> <phrase role="special"><<</phrase> <phrase role="string">" "</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">cout</phrase> <phrase role="special"><<</phrase> <phrase role="string">"\nDone"</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">EXIT_SUCCESS</phrase><phrase role="special">;</phrase>
|
|
<phrase role="special">}</phrase>
|
|
|
|
<phrase role="identifier">output</phrase><phrase role="special">:</phrase>
|
|
<phrase role="identifier">started</phrase> <phrase role="identifier">first</phrase><phrase role="special">!</phrase> <phrase role="identifier">started</phrase> <phrase role="identifier">second</phrase><phrase role="special">!</phrase> <phrase role="identifier">a0</phrase> <phrase role="identifier">b0</phrase> <phrase role="identifier">a1</phrase> <phrase role="identifier">b1</phrase> <phrase role="identifier">a2</phrase> <phrase role="identifier">b2</phrase> <phrase role="identifier">a3</phrase> <phrase role="identifier">b3</phrase> <phrase role="identifier">a4</phrase> <phrase role="identifier">b4</phrase> <phrase role="identifier">a5</phrase> <phrase role="identifier">b5</phrase> <phrase role="identifier">a6</phrase> <phrase role="identifier">b6</phrase> <phrase role="identifier">a7</phrase> <phrase role="identifier">b7</phrase> <phrase role="identifier">a8</phrase> <phrase role="identifier">b8</phrase> <phrase role="identifier">a9</phrase> <phrase role="identifier">b9</phrase>
|
|
<phrase role="identifier">Done</phrase>
|
|
</programlisting>
|
|
</section>
|
|
<section id="context.examples.asio">
|
|
<title><link linkend="context.examples.asio">ASIO</link></title>
|
|
<para>
|
|
Adapted from <ulink url="http://blog.think-async.com/2009/08/secret-sauce-revealed.html">Thinking
|
|
Asynchronously in C++</ulink> using boost.asio to implement a simple echo
|
|
server.
|
|
</para>
|
|
<para>
|
|
Chris Kohlhoff uses stackless coroutines based on preprocessor-based switch
|
|
statements to implement an echo server using boost.asio. Class <code><phrase
|
|
role="identifier">continuation</phrase></code> provides a simple coroutine
|
|
implemenatation using boost.context.
|
|
</para>
|
|
|
|
<programlisting><phrase role="keyword">class</phrase> <phrase role="identifier">continuation</phrase>
|
|
<phrase role="special">{</phrase>
|
|
<phrase role="keyword">private</phrase><phrase role="special">:</phrase>
|
|
<phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">contexts</phrase><phrase role="special">::</phrase><phrase role="identifier">context</phrase> <phrase role="identifier">ctx_</phrase><phrase role="special">;</phrase>
|
|
<phrase role="identifier">boost</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="identifier">continuation</phrase> <phrase role="special">&)</phrase> <phrase role="special">></phrase> <phrase role="identifier">fn_</phrase><phrase role="special">;</phrase>
|
|
<phrase role="keyword">bool</phrase> <phrase role="identifier">started_</phrase><phrase role="special">;</phrase>
|
|
|
|
<phrase role="keyword">void</phrase> <phrase role="identifier">trampoline_</phrase><phrase role="special">()</phrase>
|
|
<phrase role="special">{</phrase> <phrase role="identifier">fn_</phrase><phrase role="special">(</phrase> <phrase role="special">*</phrase> <phrase role="keyword">this</phrase><phrase role="special">);</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="identifier">boost</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="identifier">continuation</phrase> <phrase role="special">&)</phrase> <phrase role="special">></phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">fn</phrase><phrase role="special">)</phrase> <phrase role="special">:</phrase>
|
|
<phrase role="identifier">ctx_</phrase><phrase role="special">(</phrase>
|
|
<phrase role="special">&</phrase> <phrase role="identifier">continuation</phrase><phrase role="special">::</phrase><phrase role="identifier">trampoline_</phrase><phrase role="special">,</phrase> <phrase role="keyword">this</phrase><phrase role="special">,</phrase>
|
|
<phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">contexts</phrase><phrase role="special">::</phrase><phrase role="identifier">default_stacksize</phrase><phrase role="special">(),</phrase>
|
|
<phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">contexts</phrase><phrase role="special">::</phrase><phrase role="identifier">no_stack_unwind</phrase><phrase role="special">,</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">contexts</phrase><phrase role="special">::</phrase><phrase role="identifier">return_to_caller</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="identifier">started_</phrase><phrase role="special">(</phrase> <phrase role="keyword">false</phrase><phrase role="special">)</phrase>
|
|
<phrase role="special">{}</phrase>
|
|
|
|
<phrase role="keyword">void</phrase> <phrase role="identifier">resume</phrase><phrase role="special">()</phrase>
|
|
<phrase role="special">{</phrase>
|
|
<phrase role="keyword">if</phrase> <phrase role="special">(</phrase> <phrase role="special">!</phrase> <phrase role="identifier">started_</phrase><phrase role="special">)</phrase>
|
|
<phrase role="special">{</phrase>
|
|
<phrase role="identifier">started_</phrase> <phrase role="special">=</phrase> <phrase role="keyword">true</phrase><phrase role="special">;</phrase>
|
|
<phrase role="identifier">ctx_</phrase><phrase role="special">.</phrase><phrase role="identifier">start</phrase><phrase role="special">();</phrase>
|
|
<phrase role="special">}</phrase>
|
|
<phrase role="keyword">else</phrase> <phrase role="identifier">ctx_</phrase><phrase role="special">.</phrase><phrase role="identifier">resume</phrase><phrase role="special">();</phrase>
|
|
<phrase role="special">}</phrase>
|
|
|
|
<phrase role="keyword">void</phrase> <phrase role="identifier">suspend</phrase><phrase role="special">()</phrase>
|
|
<phrase role="special">{</phrase> <phrase role="identifier">ctx_</phrase><phrase role="special">.</phrase><phrase role="identifier">suspend</phrase><phrase role="special">();</phrase> <phrase role="special">}</phrase>
|
|
|
|
<phrase role="keyword">bool</phrase> <phrase role="identifier">is_complete</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase>
|
|
<phrase role="special">{</phrase> <phrase role="keyword">return</phrase> <phrase role="identifier">ctx_</phrase><phrase role="special">.</phrase><phrase role="identifier">is_complete</phrase><phrase role="special">();</phrase> <phrase role="special">}</phrase>
|
|
<phrase role="special">};</phrase>
|
|
</programlisting>
|
|
<para>
|
|
The operator <code><phrase role="identifier">server</phrase><phrase role="special">::</phrase><phrase
|
|
role="keyword">operator</phrase><phrase role="special">()</phrase></code>
|
|
is called by the asio reactor and jumps to coroutine (which is entering or
|
|
resuming in function <code><phrase role="identifier">server</phrase><phrase
|
|
role="special">::</phrase><phrase role="identifier">do_</phrase><phrase role="special">()</phrase></code>).
|
|
In function <code><phrase role="identifier">sever</phrase><phrase role="special">::</phrase><phrase
|
|
role="identifier">do_</phrase><phrase role="special">()</phrase></code> the
|
|
control flow is all in one place and easy to follow; *this is queued for
|
|
accepting a connection before control flow is passed back to the reactor
|
|
via <code><phrase role="identifier">suspend</phrase><phrase role="special">()</phrase></code>.
|
|
If <code><phrase role="identifier">server</phrase><phrase role="special">::</phrase><phrase
|
|
role="identifier">do_</phrase><phrase role="special">()</phrase></code> is
|
|
reentered, a local buffer is created and an asynch. read operation is queued
|
|
into the reactor. The control flow is then returned to the reactor for io-multiplexing
|
|
again. After some bytes were received <code><phrase role="identifier">server</phrase><phrase
|
|
role="special">::</phrase><phrase role="identifier">do_</phrase><phrase role="special">()</phrase></code>
|
|
is reentred again starting a asynch. write operation.
|
|
</para>
|
|
<para>
|
|
The advantage over the ordinary <code><phrase role="identifier">bind</phrase><phrase
|
|
role="special">()</phrase></code> version is that the state of execution
|
|
is preserved so that variables used by the read/write operations may have
|
|
local scope. Stackfull coroutines (as boost.context provides) enable application-protocol
|
|
stacks which can be more easily implemented. For instance, if only part of
|
|
a message is received (some bytes are outstanding before message can be parsed
|
|
or serviced), then the current state can be easily suspended/preserved (even
|
|
from nested functions of the protocol stack) until the remaining bytes are
|
|
received.
|
|
</para>
|
|
|
|
<programlisting><phrase role="keyword">class</phrase> <phrase role="identifier">server</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">enable_shared_from_this</phrase><phrase role="special"><</phrase> <phrase role="identifier">server</phrase> <phrase role="special">>,</phrase>
|
|
<phrase role="keyword">private</phrase> <phrase role="identifier">continuation</phrase>
|
|
<phrase role="special">{</phrase>
|
|
<phrase role="keyword">private</phrase><phrase role="special">:</phrase>
|
|
<phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">asio</phrase><phrase role="special">::</phrase><phrase role="identifier">ip</phrase><phrase role="special">::</phrase><phrase role="identifier">tcp</phrase><phrase role="special">::</phrase><phrase role="identifier">acceptor</phrase> <phrase role="identifier">acceptor_</phrase><phrase role="special">;</phrase>
|
|
<phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">system</phrase><phrase role="special">::</phrase><phrase role="identifier">error_code</phrase> <phrase role="identifier">ec_</phrase><phrase role="special">;</phrase>
|
|
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">n_</phrase><phrase role="special">;</phrase>
|
|
|
|
<phrase role="keyword">void</phrase> <phrase role="identifier">do_</phrase><phrase role="special">()</phrase>
|
|
<phrase role="special">{</phrase>
|
|
<phrase role="keyword">for</phrase> <phrase role="special">(;;)</phrase>
|
|
<phrase role="special">{</phrase>
|
|
<phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">asio</phrase><phrase role="special">::</phrase><phrase role="identifier">ip</phrase><phrase role="special">::</phrase><phrase role="identifier">tcp</phrase><phrase role="special">::</phrase><phrase role="identifier">socket</phrase> <phrase role="identifier">socket</phrase><phrase role="special">(</phrase> <phrase role="identifier">acceptor_</phrase><phrase role="special">.</phrase><phrase role="identifier">get_io_service</phrase><phrase role="special">()</phrase> <phrase role="special">);</phrase>
|
|
<phrase role="comment">// accept connection request and enque *this for reading data from conenction
|
|
</phrase> <phrase role="identifier">acceptor_</phrase><phrase role="special">.</phrase><phrase role="identifier">async_accept</phrase><phrase role="special">(</phrase> <phrase role="identifier">socket</phrase><phrase role="special">,</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">bind</phrase><phrase role="special">(</phrase> <phrase role="special">&</phrase> <phrase role="identifier">server</phrase><phrase role="special">::</phrase><phrase role="keyword">operator</phrase><phrase role="special">(),</phrase> <phrase role="keyword">this</phrase><phrase role="special">-></phrase><phrase role="identifier">shared_from_this</phrase><phrase role="special">(),</phrase> <phrase role="identifier">_1</phrase><phrase role="special">,</phrase> <phrase role="number">0</phrase><phrase role="special">)</phrase> <phrase role="special">);</phrase>
|
|
<phrase role="comment">// suspend() jumps back to operator() which returns to asio reactor
|
|
</phrase> <phrase role="identifier">suspend</phrase><phrase role="special">();</phrase>
|
|
|
|
<phrase role="keyword">while</phrase> <phrase role="special">(</phrase> <phrase role="special">!</phrase> <phrase role="identifier">ec_</phrase><phrase role="special">)</phrase>
|
|
<phrase role="special">{</phrase>
|
|
<phrase role="comment">// buffer has local scope!
|
|
</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">array</phrase><phrase role="special"><</phrase> <phrase role="keyword">char</phrase><phrase role="special">,</phrase> <phrase role="number">1024</phrase> <phrase role="special">></phrase> <phrase role="identifier">buffer</phrase><phrase role="special">;</phrase>
|
|
|
|
<phrase role="comment">// enqueue *this to read some bytes from the connection into buffer
|
|
</phrase> <phrase role="identifier">socket</phrase><phrase role="special">.</phrase><phrase role="identifier">async_read_some</phrase><phrase role="special">(</phrase>
|
|
<phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">asio</phrase><phrase role="special">::</phrase><phrase role="identifier">buffer</phrase><phrase role="special">(</phrase> <phrase role="identifier">buffer</phrase><phrase role="special">),</phrase>
|
|
<phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">bind</phrase><phrase role="special">(</phrase> <phrase role="special">&</phrase> <phrase role="identifier">server</phrase><phrase role="special">::</phrase><phrase role="keyword">operator</phrase><phrase role="special">(),</phrase> <phrase role="keyword">this</phrase><phrase role="special">-></phrase><phrase role="identifier">shared_from_this</phrase><phrase role="special">(),</phrase> <phrase role="identifier">_1</phrase><phrase role="special">,</phrase> <phrase role="identifier">_2</phrase><phrase role="special">)</phrase> <phrase role="special">);</phrase>
|
|
<phrase role="comment">// suspend() jumps back to operator(); asio reactor
|
|
</phrase> <phrase role="identifier">suspend</phrase><phrase role="special">();</phrase>
|
|
|
|
<phrase role="comment">// finish and return
|
|
</phrase> <phrase role="keyword">if</phrase> <phrase role="special">(</phrase> <phrase role="identifier">ec_</phrase><phrase role="special">)</phrase> <phrase role="keyword">break</phrase><phrase role="special">;</phrase>
|
|
|
|
<phrase role="comment">// enqueue *this to write data from buffer to connection
|
|
</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">asio</phrase><phrase role="special">::</phrase><phrase role="identifier">async_write</phrase><phrase role="special">(</phrase>
|
|
<phrase role="identifier">socket</phrase><phrase role="special">,</phrase>
|
|
<phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">asio</phrase><phrase role="special">::</phrase><phrase role="identifier">buffer</phrase><phrase role="special">(</phrase> <phrase role="identifier">buffer</phrase><phrase role="special">,</phrase> <phrase role="identifier">n_</phrase><phrase role="special">),</phrase>
|
|
<phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">bind</phrase><phrase role="special">(</phrase> <phrase role="special">&</phrase> <phrase role="identifier">server</phrase><phrase role="special">::</phrase><phrase role="keyword">operator</phrase><phrase role="special">(),</phrase> <phrase role="keyword">this</phrase><phrase role="special">-></phrase><phrase role="identifier">shared_from_this</phrase><phrase role="special">(),</phrase> <phrase role="identifier">_1</phrase><phrase role="special">,</phrase> <phrase role="identifier">_2</phrase><phrase role="special">)</phrase> <phrase role="special">);</phrase>
|
|
<phrase role="comment">// suspend() jumps back to operator(); asio reactor
|
|
</phrase> <phrase role="identifier">suspend</phrase><phrase role="special">();</phrase>
|
|
<phrase role="special">}</phrase>
|
|
<phrase role="special">}</phrase>
|
|
<phrase role="special">}</phrase>
|
|
|
|
<phrase role="identifier">server</phrase><phrase role="special">(</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">asio</phrase><phrase role="special">::</phrase><phrase role="identifier">io_service</phrase> <phrase role="special">&</phrase> <phrase role="identifier">io_service</phrase><phrase role="special">,</phrase> <phrase role="keyword">short</phrase> <phrase role="identifier">port</phrase><phrase role="special">)</phrase> <phrase role="special">:</phrase>
|
|
<phrase role="identifier">continuation</phrase><phrase role="special">(</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">bind</phrase><phrase role="special">(</phrase> <phrase role="special">&</phrase> <phrase role="identifier">server</phrase><phrase role="special">::</phrase><phrase role="identifier">do_</phrase><phrase role="special">,</phrase> <phrase role="keyword">this</phrase><phrase role="special">)</phrase> <phrase role="special">),</phrase>
|
|
<phrase role="identifier">acceptor_</phrase><phrase role="special">(</phrase> <phrase role="identifier">io_service</phrase><phrase role="special">,</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">asio</phrase><phrase role="special">::</phrase><phrase role="identifier">ip</phrase><phrase role="special">::</phrase><phrase role="identifier">tcp</phrase><phrase role="special">::</phrase><phrase role="identifier">endpoint</phrase><phrase role="special">(</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">asio</phrase><phrase role="special">::</phrase><phrase role="identifier">ip</phrase><phrase role="special">::</phrase><phrase role="identifier">tcp</phrase><phrase role="special">::</phrase><phrase role="identifier">v4</phrase><phrase role="special">(),</phrase> <phrase role="identifier">port</phrase><phrase role="special">)</phrase> <phrase role="special">),</phrase>
|
|
<phrase role="identifier">ec_</phrase><phrase role="special">(),</phrase> <phrase role="identifier">n_</phrase><phrase role="special">(</phrase> <phrase role="number">0</phrase><phrase role="special">)</phrase>
|
|
<phrase role="special">{}</phrase>
|
|
|
|
<phrase role="keyword">public</phrase><phrase role="special">:</phrase>
|
|
<phrase role="keyword">typedef</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">shared_ptr</phrase><phrase role="special"><</phrase> <phrase role="identifier">server</phrase> <phrase role="special">></phrase> <phrase role="identifier">ptr_t</phrase><phrase role="special">;</phrase>
|
|
|
|
<phrase role="keyword">static</phrase> <phrase role="identifier">ptr_t</phrase> <phrase role="identifier">create</phrase><phrase role="special">(</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">asio</phrase><phrase role="special">::</phrase><phrase role="identifier">io_service</phrase> <phrase role="special">&</phrase> <phrase role="identifier">io_service</phrase><phrase role="special">,</phrase> <phrase role="keyword">short</phrase> <phrase role="identifier">port</phrase><phrase role="special">)</phrase>
|
|
<phrase role="special">{</phrase> <phrase role="keyword">return</phrase> <phrase role="identifier">ptr_t</phrase><phrase role="special">(</phrase> <phrase role="keyword">new</phrase> <phrase role="identifier">server</phrase><phrase role="special">(</phrase> <phrase role="identifier">io_service</phrase><phrase role="special">,</phrase> <phrase role="identifier">port</phrase><phrase role="special">)</phrase> <phrase role="special">);</phrase> <phrase role="special">}</phrase>
|
|
|
|
<phrase role="keyword">void</phrase> <phrase role="keyword">operator</phrase><phrase role="special">()(</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">system</phrase><phrase role="special">::</phrase><phrase role="identifier">error_code</phrase> <phrase role="identifier">ec</phrase><phrase role="special">,</phrase> <phrase role="identifier">size_t</phrase> <phrase role="identifier">n</phrase><phrase role="special">)</phrase>
|
|
<phrase role="special">{</phrase>
|
|
<phrase role="identifier">ec_</phrase> <phrase role="special">=</phrase> <phrase role="identifier">ec</phrase><phrase role="special">;</phrase>
|
|
<phrase role="identifier">n_</phrase> <phrase role="special">=</phrase> <phrase role="identifier">n</phrase><phrase role="special">;</phrase>
|
|
<phrase role="comment">// jump to coroutine (do_())
|
|
</phrase> <phrase role="identifier">resume</phrase><phrase role="special">();</phrase>
|
|
<phrase role="special">}</phrase>
|
|
<phrase role="special">};</phrase>
|
|
|
|
<phrase role="keyword">int</phrase> <phrase role="identifier">main</phrase><phrase role="special">(</phrase> <phrase role="keyword">int</phrase> <phrase role="identifier">argc</phrase><phrase role="special">,</phrase> <phrase role="keyword">char</phrase> <phrase role="special">*</phrase> <phrase role="identifier">argv</phrase><phrase role="special">[])</phrase>
|
|
<phrase role="special">{</phrase>
|
|
<phrase role="keyword">try</phrase>
|
|
<phrase role="special">{</phrase>
|
|
<phrase role="keyword">if</phrase> <phrase role="special">(</phrase> <phrase role="identifier">argc</phrase> <phrase role="special">!=</phrase> <phrase role="number">2</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">"Usage: echo_server <port>\n"</phrase><phrase role="special">;</phrase>
|
|
<phrase role="keyword">return</phrase> <phrase role="number">1</phrase><phrase role="special">;</phrase>
|
|
<phrase role="special">}</phrase>
|
|
<phrase role="special">{</phrase>
|
|
<phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">asio</phrase><phrase role="special">::</phrase><phrase role="identifier">io_service</phrase> <phrase role="identifier">io_service</phrase><phrase role="special">;</phrase>
|
|
<phrase role="identifier">io_service</phrase><phrase role="special">.</phrase><phrase role="identifier">post</phrase><phrase role="special">(</phrase>
|
|
<phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">bind</phrase><phrase role="special">(</phrase>
|
|
<phrase role="special">&</phrase> <phrase role="identifier">server</phrase><phrase role="special">::</phrase><phrase role="keyword">operator</phrase><phrase role="special">(),</phrase>
|
|
<phrase role="identifier">server</phrase><phrase role="special">::</phrase><phrase role="identifier">create</phrase><phrase role="special">(</phrase> <phrase role="identifier">io_service</phrase><phrase role="special">,</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">lexical_cast</phrase><phrase role="special"><</phrase> <phrase role="keyword">short</phrase> <phrase role="special">>(</phrase> <phrase role="identifier">argv</phrase><phrase role="special">[</phrase><phrase role="number">1</phrase><phrase role="special">])</phrase> <phrase role="special">),</phrase>
|
|
<phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">system</phrase><phrase role="special">::</phrase><phrase role="identifier">error_code</phrase><phrase role="special">(),</phrase> <phrase role="number">0</phrase><phrase role="special">)</phrase> <phrase role="special">);</phrase>
|
|
<phrase role="identifier">io_service</phrase><phrase role="special">.</phrase><phrase role="identifier">run</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">"Done"</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">EXIT_SUCCESS</phrase><phrase role="special">;</phrase>
|
|
<phrase role="special">}</phrase>
|
|
<phrase role="keyword">catch</phrase> <phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">exception</phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">e</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">"Exception: "</phrase> <phrase role="special"><<</phrase> <phrase role="identifier">e</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="special">}</phrase>
|
|
|
|
<phrase role="keyword">return</phrase> <phrase role="identifier">EXIT_FAILURE</phrase><phrase role="special">;</phrase>
|
|
<phrase role="special">}</phrase>
|
|
</programlisting>
|
|
</section>
|
|
</section>
|
|
<section id="context.performance">
|
|
<title><link linkend="context.performance">Performance</link></title>
|
|
<para>
|
|
Performance of <emphasis role="bold">Boost.Context</emphasis> was measured
|
|
on the platforms shown in the following table. Performance measurements were
|
|
taken using <code><phrase role="identifier">rdtsc</phrase></code>, with overhead
|
|
corrections, on x86 platforms. In each case, stack protection was active, cache
|
|
warm-up was accounted for, and the one running thread was pinned to a single
|
|
CPU. The code was compiled using the build options, 'variant<literal>release
|
|
cxxflags</literal>-DBOOST_DISABLE_ASSERTS'.
|
|
</para>
|
|
<para>
|
|
The numbers in the table are the number of cycles per iteration, based upon
|
|
an average computed over 1000 iterations.
|
|
</para>
|
|
<table frame="all">
|
|
<title>Perfomance of context switch</title>
|
|
<tgroup cols="3">
|
|
<thead>
|
|
<row>
|
|
<entry>
|
|
<para>
|
|
Platform
|
|
</para>
|
|
</entry>
|
|
<entry>
|
|
<para>
|
|
ucontext_t
|
|
</para>
|
|
</entry>
|
|
<entry>
|
|
<para>
|
|
fcontext_t
|
|
</para>
|
|
</entry>
|
|
</row>
|
|
</thead>
|
|
<tbody>
|
|
<row>
|
|
<entry>
|
|
<para>
|
|
AMD Athlon 64 DualCore 4400+ (32bit Linux)
|
|
</para>
|
|
</entry>
|
|
<entry>
|
|
<para>
|
|
1771 cycles
|
|
</para>
|
|
</entry>
|
|
<entry>
|
|
<para>
|
|
146 cycles
|
|
</para>
|
|
</entry>
|
|
</row>
|
|
<row>
|
|
<entry>
|
|
<para>
|
|
Intel Core2 Quad (64bit Linux)
|
|
</para>
|
|
</entry>
|
|
<entry>
|
|
<para>
|
|
1739 cycles
|
|
</para>
|
|
</entry>
|
|
<entry>
|
|
<para>
|
|
117 cycles
|
|
</para>
|
|
</entry>
|
|
</row>
|
|
</tbody>
|
|
</tgroup>
|
|
</table>
|
|
</section>
|
|
<section id="context.tested">
|
|
<title><link linkend="context.tested">Tested Platforms</link></title>
|
|
<informaltable frame="all">
|
|
<tgroup cols="4">
|
|
<thead>
|
|
<row>
|
|
<entry>
|
|
<para>
|
|
Platform
|
|
</para>
|
|
</entry>
|
|
<entry>
|
|
<para>
|
|
OS
|
|
</para>
|
|
</entry>
|
|
<entry>
|
|
<para>
|
|
Compiler
|
|
</para>
|
|
</entry>
|
|
<entry>
|
|
<para>
|
|
ABI
|
|
</para>
|
|
</entry>
|
|
</row>
|
|
</thead>
|
|
<tbody>
|
|
<row>
|
|
<entry>
|
|
<para>
|
|
ARM (ARM926EJ-S)
|
|
</para>
|
|
</entry>
|
|
<entry>
|
|
<para>
|
|
Debian GNU/Linux (Lenny)
|
|
</para>
|
|
</entry>
|
|
<entry>
|
|
<para>
|
|
GCC 4.4.4
|
|
</para>
|
|
</entry>
|
|
<entry>
|
|
<para>
|
|
ARM APCS (Linux)
|
|
</para>
|
|
</entry>
|
|
</row>
|
|
<row>
|
|
<entry>
|
|
<para>
|
|
MIPS (MIPS 24K)
|
|
</para>
|
|
</entry>
|
|
<entry>
|
|
<para>
|
|
Debian GNU/Linux (Lenny)
|
|
</para>
|
|
</entry>
|
|
<entry>
|
|
<para>
|
|
GCC 4.3.2
|
|
</para>
|
|
</entry>
|
|
<entry>
|
|
<para>
|
|
O32
|
|
</para>
|
|
</entry>
|
|
</row>
|
|
<row>
|
|
<entry>
|
|
<para>
|
|
MIPS (O2 / MIPS R5000)
|
|
</para>
|
|
</entry>
|
|
<entry>
|
|
<para>
|
|
Debian GNU/Linux (Lenny)
|
|
</para>
|
|
</entry>
|
|
<entry>
|
|
<para>
|
|
GCC 4.3.2
|
|
</para>
|
|
</entry>
|
|
<entry>
|
|
<para>
|
|
O32
|
|
</para>
|
|
</entry>
|
|
</row>
|
|
<row>
|
|
<entry>
|
|
<para>
|
|
PowerPC (7400)
|
|
</para>
|
|
</entry>
|
|
<entry>
|
|
<para>
|
|
Debian GNU/Linux (Lenny)
|
|
</para>
|
|
</entry>
|
|
<entry>
|
|
<para>
|
|
GCC 4.3.2
|
|
</para>
|
|
</entry>
|
|
<entry>
|
|
<para>
|
|
SYSV
|
|
</para>
|
|
</entry>
|
|
</row>
|
|
<row>
|
|
<entry>
|
|
<para>
|
|
X86_64 (Intel Core2 Quad)
|
|
</para>
|
|
</entry>
|
|
<entry>
|
|
<para>
|
|
Ubuntu GNU/Linux (Lucid Lynx)
|
|
</para>
|
|
</entry>
|
|
<entry>
|
|
<para>
|
|
GCC 4.4.3
|
|
</para>
|
|
</entry>
|
|
<entry>
|
|
<para>
|
|
SYSV
|
|
</para>
|
|
</entry>
|
|
</row>
|
|
<row>
|
|
<entry>
|
|
<para>
|
|
X86_64
|
|
</para>
|
|
</entry>
|
|
<entry>
|
|
<para>
|
|
Windows 7
|
|
</para>
|
|
</entry>
|
|
<entry>
|
|
<para>
|
|
MS VC 10.0
|
|
</para>
|
|
</entry>
|
|
<entry>
|
|
<para>
|
|
PE
|
|
</para>
|
|
</entry>
|
|
</row>
|
|
<row>
|
|
<entry>
|
|
<para>
|
|
I386
|
|
</para>
|
|
</entry>
|
|
<entry>
|
|
<para>
|
|
Debian GNU/Linux (Lenny)
|
|
</para>
|
|
</entry>
|
|
<entry>
|
|
<para>
|
|
GCC 4.4.3
|
|
</para>
|
|
</entry>
|
|
<entry>
|
|
<para>
|
|
SYSV
|
|
</para>
|
|
</entry>
|
|
</row>
|
|
<row>
|
|
<entry>
|
|
<para>
|
|
I386
|
|
</para>
|
|
</entry>
|
|
<entry>
|
|
<para>
|
|
FreeBSD 8.0
|
|
</para>
|
|
</entry>
|
|
<entry>
|
|
<para>
|
|
GCC 4.2.1
|
|
</para>
|
|
</entry>
|
|
<entry>
|
|
<para>
|
|
SYSV
|
|
</para>
|
|
</entry>
|
|
</row>
|
|
<row>
|
|
<entry>
|
|
<para>
|
|
I386
|
|
</para>
|
|
</entry>
|
|
<entry>
|
|
<para>
|
|
OpenSolaris 2009.06
|
|
</para>
|
|
</entry>
|
|
<entry>
|
|
<para>
|
|
GCC 4.3.2
|
|
</para>
|
|
</entry>
|
|
<entry>
|
|
<para>
|
|
SYSV
|
|
</para>
|
|
</entry>
|
|
</row>
|
|
<row>
|
|
<entry>
|
|
<para>
|
|
I386
|
|
</para>
|
|
</entry>
|
|
<entry>
|
|
<para>
|
|
Windows XP
|
|
</para>
|
|
</entry>
|
|
<entry>
|
|
<para>
|
|
MSVC 9.0
|
|
</para>
|
|
</entry>
|
|
<entry>
|
|
<para>
|
|
PE
|
|
</para>
|
|
</entry>
|
|
</row>
|
|
</tbody>
|
|
</tgroup>
|
|
</informaltable>
|
|
</section>
|
|
<section id="context.rationale">
|
|
<title><link linkend="context.rationale">Rationale</link></title> <anchor id="context.rationale.nothrow_guarantee"/>
|
|
<bridgehead renderas="sect3">
|
|
<link linkend="context.rationale.nothrow_guarantee">NoThrow guarantee</link>
|
|
</bridgehead>
|
|
<para>
|
|
Member functions of <link linkend="context.context.context"><emphasis>context</emphasis></link>
|
|
do not thow exceptions but do require that certain preconditions are satisifed:
|
|
context jumps can only be made by instances which are not a <emphasis>not-a-context</emphasis>
|
|
and which are not complete.
|
|
</para>
|
|
<anchor id="context.rationale.pimpl_idiom"/>
|
|
<bridgehead renderas="sect3">
|
|
<link linkend="context.rationale.pimpl_idiom">Pimpl idiom</link>
|
|
</bridgehead>
|
|
<para>
|
|
In order to support move semantics and context switching operations, the use
|
|
of the Pimpl Idiom was necessary. A nice feature is that a <link linkend="context.context.context"><emphasis>context</emphasis></link>
|
|
has the size of a pointer, so it fits into a register.
|
|
</para>
|
|
<para>
|
|
With the current design the constructor accepts functors and its arguments
|
|
similiar to <emphasis>thread</emphasis>.
|
|
</para>
|
|
<para>
|
|
The Pimpl Idiom allows type-erasing the <emphasis>StackAllocator</emphasis>
|
|
type.
|
|
</para>
|
|
<anchor id="context.rationale.unwinding"/>
|
|
<bridgehead renderas="sect3">
|
|
<link linkend="context.rationale.unwinding">Unwinding</link>
|
|
</bridgehead>
|
|
<para>
|
|
In order to release resources allocated on the stack, unwinding the stack must
|
|
be supported. The current implementation throws a exception in order to unwind
|
|
the stack (jump back to invocation of <code><phrase role="identifier">suspend</phrase><phrase
|
|
role="special">()</phrase></code>). The special exception is caught inside
|
|
the trampoline function (first function on top of stack).
|
|
</para>
|
|
<anchor id="context.rationale.protecting_the_stack"/>
|
|
<bridgehead renderas="sect3">
|
|
<link linkend="context.rationale.protecting_the_stack">Protecting the stack</link>
|
|
</bridgehead>
|
|
<para>
|
|
Because the stack's size is fixed -- there is no support for split stacks --
|
|
it is important to protect against exceeding the stack's bounds. Otherwise,
|
|
in the best case, overrunning the stack's memory will result in a segmentation
|
|
fault or access violation and, in the worst case, the application's memory
|
|
will be overwritten. <code><phrase role="identifier">stack_allocator</phrase></code>
|
|
appends a guard page to the stack to help detect overruns. The guard page consumes
|
|
no physical memory, but generates a segmentation fault or access violation
|
|
on access to the virtual memory addresses within it.
|
|
</para>
|
|
<anchor id="context.rationale.fcontext_t"/>
|
|
<bridgehead renderas="sect3">
|
|
<link linkend="context.rationale.fcontext_t">fcontext_t</link>
|
|
</bridgehead>
|
|
<para>
|
|
<emphasis role="bold">Boost.Context</emphasis> provides the low leve lAPI boost_fcontext_t
|
|
which is implemented in assembler to provide context swapping operations. boost_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>
|
|
<section id="context.rationale.other_apis_">
|
|
<title><link linkend="context.rationale.other_apis_">Other APIs </link></title>
|
|
<anchor id="context.rationale.other_apis_.setjmp___longjmp__"/>
|
|
<bridgehead renderas="sect4">
|
|
<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>
|
|
<para>
|
|
<ulink url="boost:/libs/context/doc/pdf/iso_c99.pdf">ISO/IEC 9899:1999,
|
|
2005</ulink>, 7.13.2.1:2
|
|
</para>
|
|
</footnote>.
|
|
</para>
|
|
<anchor id="context.rationale.other_apis_.ucontext_t"/>
|
|
<bridgehead renderas="sect4">
|
|
<link linkend="context.rationale.other_apis_.ucontext_t">ucontext_t</link>
|
|
</bridgehead>
|
|
<para>
|
|
Since POSIX.1-2003 <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>
|
|
<para>
|
|
<ulink url="boost:/libs/context/doc/pdf/iso_c99.pdf">ISO/IEC 9899:1999,
|
|
2005</ulink>, 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 guarantied 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 involes system calls consuming a lot
|
|
of CPU cycles (ucontext_t is slower by perfomance_link[factor 13x] relative
|
|
to <code><phrase role="identifier">boost_fcontext_t</phrase></code>).
|
|
</para>
|
|
<anchor id="context.rationale.other_apis_.windows_fibers"/>
|
|
<bridgehead renderas="sect4">
|
|
<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>
|
|
<section id="context.reference">
|
|
<title><link linkend="context.reference">Reference</link></title> <anchor id="context.reference.arm"/>
|
|
<bridgehead renderas="sect3">
|
|
<link linkend="context.reference.arm">ARM</link>
|
|
</bridgehead>
|
|
<itemizedlist>
|
|
<listitem>
|
|
<simpara>
|
|
AAPCS ABI: <ulink url="boost:/libs/context/doc/pdf/arm-aapcs.pdf">Procedure
|
|
Call Standard for the ARM Architecture</ulink>
|
|
</simpara>
|
|
</listitem>
|
|
<listitem>
|
|
<simpara>
|
|
AAPCS/LINUX: <ulink url="boost:/libs/context/doc/pdf/arm-linux-aapcs.pdf">ARM
|
|
GNU/Linux Application Binary Interface Supplement</ulink>
|
|
</simpara>
|
|
</listitem>
|
|
</itemizedlist>
|
|
<anchor id="context.reference.mips"/>
|
|
<bridgehead renderas="sect3">
|
|
<link linkend="context.reference.mips">MIPS</link>
|
|
</bridgehead>
|
|
<itemizedlist>
|
|
<listitem>
|
|
<simpara>
|
|
O32 ABI: <ulink url="boost:/libs/context/doc/pdf/mips-o32.pdf">SYSTEM V
|
|
APPLICATION BINARY INTERFACE, MIPS RISC Processor Supplement</ulink>
|
|
</simpara>
|
|
</listitem>
|
|
</itemizedlist>
|
|
<anchor id="context.reference.powerpc32"/>
|
|
<bridgehead renderas="sect3">
|
|
<link linkend="context.reference.powerpc32">PowerPC32</link>
|
|
</bridgehead>
|
|
<itemizedlist>
|
|
<listitem>
|
|
<simpara>
|
|
SYSV ABI: <ulink url="boost:/libs/context/doc/pdf/ppc32-sysv.pdf">SYSTEM
|
|
V APPLICATION BINARY INTERFACE PowerPC Processor Supplement</ulink>
|
|
</simpara>
|
|
</listitem>
|
|
</itemizedlist>
|
|
<anchor id="context.reference.powerpc64"/>
|
|
<bridgehead renderas="sect3">
|
|
<link linkend="context.reference.powerpc64">PowerPC64</link>
|
|
</bridgehead>
|
|
<itemizedlist>
|
|
<listitem>
|
|
<simpara>
|
|
SYSV ABI: <ulink url="boost:/libs/context/doc/pdf/ppc64-sysv.pdf">PowerPC
|
|
User Instruction Set Architecture, Book I</ulink>
|
|
</simpara>
|
|
</listitem>
|
|
</itemizedlist>
|
|
<anchor id="context.reference.x86_32"/>
|
|
<bridgehead renderas="sect3">
|
|
<link linkend="context.reference.x86_32">X86-32</link>
|
|
</bridgehead>
|
|
<itemizedlist>
|
|
<listitem>
|
|
<simpara>
|
|
SYSV ABI: <ulink url="boost:/libs/context/doc/pdf/x86_32-sysv.pdf">SYSTEM
|
|
V APPLICATION BINARY INTERFACE, Intel386TM Architecture Processor Supplement</ulink>
|
|
</simpara>
|
|
</listitem>
|
|
<listitem>
|
|
<simpara>
|
|
MS PE: <ulink url="http://msdn.microsoft.com/en-us/library/k2b2ssfy.aspx">Calling
|
|
Conventions</ulink>
|
|
</simpara>
|
|
</listitem>
|
|
</itemizedlist>
|
|
<anchor id="context.reference.x86_64"/>
|
|
<bridgehead renderas="sect3">
|
|
<link linkend="context.reference.x86_64">X86-64</link>
|
|
</bridgehead>
|
|
<itemizedlist>
|
|
<listitem>
|
|
<simpara>
|
|
SYSV ABI: <ulink url="boost:/libs/context/doc/pdf/x86_64-sysv.pdf">System
|
|
V Application Binary Interface, AMD64 Architecture Processor Supplement</ulink>
|
|
</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.todo">
|
|
<title><link linkend="context.todo">Todo</link></title>
|
|
<itemizedlist>
|
|
<listitem>
|
|
<simpara>
|
|
provide support for SPARC
|
|
</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, Fernando Pelliccioni, Giovanni
|
|
Piero Deretta, Gordon Woodhull, Helge Bahmann, Holger Grund, Jeffrey Lee Hellrung
|
|
(Jr.), Keith Jeffery, Phil Endecott, Robert Stewart, Vicente J. Botet Escriba.
|
|
</para>
|
|
</section>
|
|
</article>
|