2
0
mirror of https://github.com/boostorg/context.git synced 2026-01-27 18:52:16 +00:00
Files
context/doc/context.xml
Oliver Kowalke b8fd549bac initial commit of boost.context
[SVN r76974]
2012-02-11 13:04:55 +00:00

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">&lt;</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">&gt;</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=&quot;-mips2&quot; 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">&lt;</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">&lt;&lt;</phrase> <phrase role="string">&quot;fn(): local variable i == &quot;</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="identifier">i</phrase> <phrase role="special">&lt;&lt;</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">&lt;&lt;</phrase> <phrase role="string">&quot;main() starts context ctx&quot;</phrase> <phrase role="special">&lt;&lt;</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">&lt;&lt;</phrase> <phrase role="string">&quot;main() calls context ctx&quot;</phrase> <phrase role="special">&lt;&lt;</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">&lt;&lt;</phrase> <phrase role="string">&quot;Done&quot;</phrase> <phrase role="special">&lt;&lt;</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">&lt;&lt;</phrase> <phrase role="string">&quot;fn(): local variable i == &quot;</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="identifier">i</phrase> <phrase role="special">&lt;&lt;</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">&lt;&lt;</phrase> <phrase role="string">&quot;transfered value: &quot;</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="identifier">j</phrase> <phrase role="special">&lt;&lt;</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">&lt;&lt;</phrase> <phrase role="string">&quot;main() calls context ctx&quot;</phrase> <phrase role="special">&lt;&lt;</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">&lt;&lt;</phrase> <phrase role="string">&quot;transfered value: &quot;</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="identifier">x</phrase> <phrase role="special">&lt;&lt;</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">&lt;&lt;</phrase> <phrase role="string">&quot;Done&quot;</phrase> <phrase role="special">&lt;&lt;</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">&lt;</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">&lt;&lt;</phrase> <phrase role="string">&quot;fn(): local variable i == &quot;</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="identifier">i</phrase> <phrase role="special">&lt;&lt;</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">&lt;&lt;</phrase> <phrase role="string">&quot;main() calls context ctx&quot;</phrase> <phrase role="special">&lt;&lt;</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">&lt;&lt;</phrase> <phrase role="string">&quot;Done&quot;</phrase> <phrase role="special">&lt;&lt;</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">&lt;</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">&lt;&lt;</phrase> <phrase role="string">&quot;fn(): local variable i == &quot;</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="identifier">i</phrase> <phrase role="special">&lt;&lt;</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">&lt;&lt;</phrase> <phrase role="string">&quot;main() calls context ctx&quot;</phrase> <phrase role="special">&lt;&lt;</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">&lt;&lt;</phrase> <phrase role="string">&quot;fn1(): when this function returns fn2() will be entered&quot;</phrase> <phrase role="special">&lt;&lt;</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">&lt;&lt;</phrase> <phrase role="string">&quot;fn2(): first time entered&quot;</phrase> <phrase role="special">&lt;&lt;</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">&lt;&lt;</phrase> <phrase role="string">&quot;fn2(): second time entered\n&quot;</phrase><phrase role="special">;</phrase>
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cout</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="string">&quot;fn2(): return to main()&quot;</phrase> <phrase role="special">&lt;&lt;</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">&lt;&lt;</phrase> <phrase role="string">&quot;Done&quot;</phrase> <phrase role="special">&lt;&lt;</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">&lt;&lt;</phrase> <phrase role="string">&quot;X()&quot;</phrase> <phrase role="special">&lt;&lt;</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">&lt;&lt;</phrase> <phrase role="string">&quot;~X()&quot;</phrase> <phrase role="special">&lt;&lt;</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">&lt;&lt;</phrase> <phrase role="string">&quot;fn(): &quot;</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="identifier">i</phrase> <phrase role="special">&lt;&lt;</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">&lt;</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">&lt;&lt;</phrase> <phrase role="string">&quot;ctx is complete: &quot;</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">boolalpha</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="identifier">ctx</phrase><phrase role="special">.</phrase><phrase role="identifier">is_complete</phrase><phrase role="special">()</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="string">&quot;\n&quot;</phrase><phrase role="special">;</phrase>
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cout</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="string">&quot;call ctx.unwind_stack()&quot;</phrase> <phrase role="special">&lt;&lt;</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">&lt;&lt;</phrase> <phrase role="string">&quot;ctx is complete: &quot;</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">boolalpha</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="identifier">ctx</phrase><phrase role="special">.</phrase><phrase role="identifier">is_complete</phrase><phrase role="special">()</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="string">&quot;\n&quot;</phrase><phrase role="special">;</phrase>
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cout</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="string">&quot;Done&quot;</phrase> <phrase role="special">&lt;&lt;</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">&lt;</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">&gt;</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">&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>
<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>
<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>
<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">Allocator</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">alloc</phrase><phrase role="special">);</phrase>
<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">&gt;</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">&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="keyword">typename</phrase> <phrase role="identifier">A9</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="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">&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">&gt;</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">&amp;</phrase> <phrase role="identifier">alloc</phrase><phrase role="special">);</phrase>
<phrase role="special">...</phrase>
<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="keyword">typename</phrase> <phrase role="identifier">A9</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="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">&amp;</phrase> <phrase role="identifier">alloc</phrase><phrase role="special">);</phrase>
<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">&gt;</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">&amp;</phrase> <phrase role="identifier">nxt</phrase><phrase role="special">);</phrase>
<phrase role="special">...</phrase>
<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="keyword">typename</phrase> <phrase role="identifier">A9</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="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">&amp;</phrase> <phrase role="identifier">nxt</phrase><phrase role="special">);</phrase>
<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">&gt;</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">&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>
<phrase role="special">...</phrase>
<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="keyword">typename</phrase> <phrase role="identifier">A9</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="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">&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>
<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="special">&amp;&amp;</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">&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="special">&amp;&amp;</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>
<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="special">&amp;&amp;</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="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="special">&amp;&amp;</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">Allocator</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</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">&amp;&amp;</phrase> <phrase role="identifier">other</phrase><phrase role="special">);</phrase>
<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>
<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">&amp;</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">&amp;</phrase> <phrase role="identifier">l</phrase><phrase role="special">,</phrase> <phrase role="identifier">context</phrase> <phrase role="special">&amp;</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">&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></link>
</bridgehead>
<variablelist>
<title></title>
<varlistentry>
<term>Preconditions:</term>
<listitem>
<para>
<code><phrase role="identifier">size</phrase></code> &gt; minimum_stacksize(),
<code><phrase role="identifier">size</phrase></code> &lt; 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">&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></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">&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></link>
</bridgehead>
<variablelist>
<title></title>
<varlistentry>
<term>Preconditions:</term>
<listitem>
<para>
<code><phrase role="identifier">size</phrase></code> &gt; minimum_stacksize(),
<code><phrase role="identifier">size</phrase></code> &lt; 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">&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></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">&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></link>
</bridgehead>
<variablelist>
<title></title>
<varlistentry>
<term>Preconditions:</term>
<listitem>
<para>
<code><phrase role="identifier">size</phrase></code> &gt; minimum_stacksize(),
<code><phrase role="identifier">size</phrase></code> &lt; 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">&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></link>
</bridgehead>
<variablelist>
<title></title>
<varlistentry>
<term>Preconditions:</term>
<listitem>
<para>
<code><phrase role="identifier">size</phrase></code> &gt; minimum_stacksize(),
<code><phrase role="identifier">size</phrase></code> &lt; 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">&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></link>
</bridgehead>
<variablelist>
<title></title>
<varlistentry>
<term>Preconditions:</term>
<listitem>
<para>
<code><phrase role="identifier">size</phrase></code> &gt; minimum_stacksize(),
<code><phrase role="identifier">size</phrase></code> &lt; 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">&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></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">&amp;&amp;</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">&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></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">&amp;</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">&amp;</phrase> <phrase role="identifier">l</phrase><phrase role="special">,</phrase> <phrase role="identifier">context</phrase> <phrase role="special">&amp;</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 &quot;C&quot;.
</para>
<programlisting><phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">cstdio</phrase><phrase role="special">&gt;</phrase>
<phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">cstdlib</phrase><phrase role="special">&gt;</phrase>
<phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">cstring</phrase><phrase role="special">&gt;</phrase>
<phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">vector</phrase><phrase role="special">&gt;</phrase>
<phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</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">&gt;</phrase>
<phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</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">&gt;</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">&quot;f1() started\n&quot;</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">&quot;f1: call boost_fcontext_jump( &amp; fc1, &amp; fc2, 0)\n&quot;</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">&amp;</phrase> <phrase role="identifier">fc1</phrase><phrase role="special">,</phrase> <phrase role="special">&amp;</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">&quot;f1() returns\n&quot;</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">&quot;f2() started\n&quot;</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">&quot;f2: call boost_fcontext_jump( &amp; fc2, &amp; fc1, 0)\n&quot;</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">&amp;</phrase> <phrase role="identifier">fc2</phrase><phrase role="special">,</phrase> <phrase role="special">&amp;</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">&quot;f2() returns\n&quot;</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">&lt;</phrase> <phrase role="keyword">char</phrase> <phrase role="special">*</phrase> <phrase role="special">&gt;(</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">&amp;</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">&amp;</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">&lt;</phrase> <phrase role="keyword">char</phrase> <phrase role="special">*</phrase> <phrase role="special">&gt;(</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">&amp;</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">&quot;main: call boost_fcontext_start( &amp; fcm, &amp; fc1)\n&quot;</phrase><phrase role="special">);</phrase>
<phrase role="identifier">boost_fcontext_start</phrase><phrase role="special">(</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">fcm</phrase><phrase role="special">,</phrase> <phrase role="special">&amp;</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">&quot;main() returns\n&quot;</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">&amp;</phrase> <phrase role="identifier">fcm</phrase><phrase role="special">,</phrase> <phrase role="special">&amp;</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">&amp;</phrase> <phrase role="identifier">fc1</phrase><phrase role="special">,</phrase> <phrase role="special">&amp;</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">&amp;</phrase> <phrase role="identifier">fc2</phrase><phrase role="special">,</phrase> <phrase role="special">&amp;</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">&lt;</phrase> <phrase role="identifier">platform</phrase> <phrase role="identifier">specific</phrase> <phrase role="special">&gt;</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">-&gt;</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">&amp;</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">&lt;&lt;</phrase> <phrase role="identifier">i</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="string">&quot; &quot;</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">&lt;&lt;</phrase> <phrase role="string">&quot;\nDone&quot;</phrase> <phrase role="special">&lt;&lt;</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">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">T</phrase> <phrase role="special">&gt;</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">-&gt;</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">&amp;</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">&lt;</phrase> <phrase role="identifier">intptr_t</phrase> <phrase role="special">&gt;(</phrase> <phrase role="special">&amp;</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">&amp;</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">&amp;&amp;</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">&amp;</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">&lt;</phrase> <phrase role="identifier">T</phrase> <phrase role="special">*</phrase> <phrase role="special">&gt;(</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">&lt;</phrase>
<phrase role="keyword">int</phrase> <phrase role="special">&gt;</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">&lt;</phrase> <phrase role="keyword">int</phrase> <phrase role="special">&gt;</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">&lt;</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">&lt;</phrase> <phrase role="keyword">void</phrase><phrase role="special">(</phrase> <phrase role="identifier">continuation</phrase> <phrase role="special">&amp;)</phrase> <phrase role="special">&gt;</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">&lt;</phrase> <phrase role="keyword">void</phrase><phrase role="special">(</phrase> <phrase role="identifier">continuation</phrase> <phrase role="special">&amp;)</phrase> <phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</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">&amp;</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">&amp;</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">&lt;&lt;</phrase> <phrase role="string">&quot;started first! &quot;</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">&lt;</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">&lt;&lt;</phrase> <phrase role="string">&quot;a&quot;</phrase> <phrase role="special">&lt;&lt;</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">&amp;</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">&lt;&lt;</phrase> <phrase role="string">&quot;started second! &quot;</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">&lt;</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">&lt;&lt;</phrase> <phrase role="string">&quot;b&quot;</phrase> <phrase role="special">&lt;&lt;</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">&amp;&amp;</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 -&gt; first()
</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cout</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="string">&quot; &quot;</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 -&gt; second()
</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cout</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="string">&quot; &quot;</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">&lt;&lt;</phrase> <phrase role="string">&quot;\nDone&quot;</phrase> <phrase role="special">&lt;&lt;</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">&lt;</phrase> <phrase role="keyword">void</phrase><phrase role="special">(</phrase> <phrase role="identifier">continuation</phrase> <phrase role="special">&amp;)</phrase> <phrase role="special">&gt;</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">&lt;</phrase> <phrase role="keyword">void</phrase><phrase role="special">(</phrase> <phrase role="identifier">continuation</phrase> <phrase role="special">&amp;)</phrase> <phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</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">&amp;</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">&lt;</phrase> <phrase role="identifier">server</phrase> <phrase role="special">&gt;,</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">&amp;</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">-&gt;</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">&lt;</phrase> <phrase role="keyword">char</phrase><phrase role="special">,</phrase> <phrase role="number">1024</phrase> <phrase role="special">&gt;</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">&amp;</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">-&gt;</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">&amp;</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">-&gt;</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">&amp;</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">&amp;</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">&lt;</phrase> <phrase role="identifier">server</phrase> <phrase role="special">&gt;</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">&amp;</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">&lt;&lt;</phrase> <phrase role="string">&quot;Usage: echo_server &lt;port&gt;\n&quot;</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">&amp;</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">&lt;</phrase> <phrase role="keyword">short</phrase> <phrase role="special">&gt;(</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">&lt;&lt;</phrase> <phrase role="string">&quot;Done&quot;</phrase> <phrase role="special">&lt;&lt;</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">&amp;</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">&lt;&lt;</phrase> <phrase role="string">&quot;Exception: &quot;</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="identifier">e</phrase><phrase role="special">.</phrase><phrase role="identifier">what</phrase><phrase role="special">()</phrase> <phrase role="special">&lt;&lt;</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">&gt;=</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">&gt;=</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>