2
0
mirror of https://github.com/boostorg/fiber.git synced 2026-02-16 01:12:29 +00:00
Files
fiber/doc/fibers.xml
2015-09-07 17:35:37 +02:00

11398 lines
827 KiB
XML

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
<library id="fiber" name="Fiber" dirname="fiber" last-revision="$Date: 2015/09/07 15:34:21 $"
xmlns:xi="http://www.w3.org/2001/XInclude">
<libraryinfo>
<authorgroup>
<author>
<firstname>Oliver</firstname> <surname>Kowalke</surname>
</author>
</authorgroup>
<copyright>
<year>2013</year> <holder>Oliver Kowalke</holder>
</copyright>
<legalnotice id="fiber.legal">
<para>
Distributed under the Boost Software License, Version 1.0. (See accompanying
file LICENSE_1_0.txt or copy at <ulink url="http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</ulink>)
</para>
</legalnotice>
<librarypurpose>
C++ Library to cooperatively schedule and synchronize micro-threads
</librarypurpose>
<librarycategory name="category:text"></librarycategory>
</libraryinfo>
<title>Fiber</title>
<section id="fiber.overview">
<title><link linkend="fiber.overview">Overview</link></title>
<para>
<emphasis role="bold">Boost.Fiber</emphasis> provides a framework for micro-/userland-threads
(fibers) scheduled cooperatively. The API contains classes and functions to
manage and synchronize fibers similiarly to <ulink url="http://www.boost.org/doc/libs/release/libs/thread/index.html">Boost.Thread</ulink>.
</para>
<para>
Each fiber has its own stack.
</para>
<para>
A fiber can save the current execution state, including all registers and CPU
flags, the instruction pointer, and the stack pointer and later restore this
state. The idea is to have multiple execution paths running on a single thread
using cooperative scheduling (versus threads, which are preemptively scheduled).
The running fiber decides explicitly when it should yield to allow another
fiber to run (context switching). <emphasis role="bold">Boost.Fiber</emphasis>
internally uses <ulink url="http://www.boost.org/doc/libs/release/libs/context/doc/html/context/econtext.html"><emphasis>execution_context</emphasis></ulink>
from <ulink url="http://www.boost.org/doc/libs/release/libs/context/index.html">Boost.Context</ulink>;
the classes in this library manage, schedule and, when needed, synchronize
those execution contexts. A context switch between threads usually costs thousands
of CPU cycles on x86, compared to a fiber switch with less than a hundred cycles.
A fiber can only run on a single thread at any point in time.
</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">fiber</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>
The namespaces used are:
</para>
<programlisting><phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase>
<phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">this_fiber</phrase>
</programlisting>
<bridgehead renderas="sect3" id="fiber.overview.h0">
<phrase id="fiber.overview.fibers_and_threads"/><link linkend="fiber.overview.fibers_and_threads">Fibers
and Threads</link>
</bridgehead>
<para>
Control is cooperatively passed between fibers launched on a given thread.
At a given moment, on a given thread, at most one fiber is running.
</para>
<para>
Spawning additional fibers on a given thread does not increase your program's
utilization of hardware cores.
</para>
<para>
On the other hand, a fiber may safely access any resource exclusively owned
by its parent thread without explicitly needing to defend that resource against
concurrent access by other fibers on the same thread. You are already guaranteed
that no other fiber on that thread is concurrently touching that resource.
This can be particularly important when introducing concurrency in legacy code.
You can safely spawn fibers running old code, using asynchronous I/O to interleave
execution.
</para>
<para>
In effect, fibers provide a natural way to organize concurrent code based on
asynchronous I/O. Instead of chaining together completion handlers, code running
on a fiber can make what looks like a normal blocking function call. That call
can cheaply suspend the calling fiber, allowing other fibers on the same thread
to run. When the operation has completed, the suspended fiber resumes, without
having to explicitly save or restore its state. Its local stack variables persist
across the call.
</para>
<para>
A fiber launched on a particular thread will always run on that thread. A fiber
can count on thread-local storage; however that storage will be shared among
all fibers running on the same thread.
</para>
<anchor id="cross_thread_sync"/>
<bridgehead renderas="sect3" id="fiber.overview.h1">
<phrase id="fiber.overview.boost_fibers_no_atomics"/><link linkend="fiber.overview.boost_fibers_no_atomics">BOOST_FIBERS_NO_ATOMICS</link>
</bridgehead>
<para>
The fiber synchronization objects provided by this library will, by default,
safely synchronize fibers running on different threads. However, this level
of synchronization can be removed (for performance) by building the library
with <emphasis role="bold"><code><phrase role="identifier">BOOST_FIBERS_NO_ATOMICS</phrase></code></emphasis>
defined. When the library is built with that macro, you must ensure that all
the fibers referencing a particular synchronization object are running in the
same thread. Please see <link linkend="synchronization">Synchronization</link>.
</para>
<para>
For fiber-local storage, please see <link linkend="class_fiber_specific_ptr"> <code>fiber_specific_ptr</code></link>.
</para>
<anchor id="blocking"/>
<bridgehead renderas="sect3" id="fiber.overview.h2">
<phrase id="fiber.overview.blocking"/><link linkend="fiber.overview.blocking">Blocking</link>
</bridgehead>
<para>
Normally, when this documentation states that a particular fiber <emphasis>blocks</emphasis>
(or equivalently, <emphasis>suspends),</emphasis> it means that it yields control,
allowing other fibers on the same thread to run. The synchronization mechanisms
provided by <emphasis role="bold">Boost.Fiber</emphasis> have this behavior.
</para>
<para>
A fiber may, of course, use normal thread synchronization mechanisms; however
a fiber that invokes any of these mechanisms will block its entire thread,
preventing any other fiber from running on that thread in the meantime. For
instance, when a fiber wants to wait for a value from another fiber in the
same thread, using <code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase
role="identifier">future</phrase></code> would be unfortunate: <code><phrase
role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">future</phrase><phrase
role="special">::</phrase><phrase role="identifier">get</phrase><phrase role="special">()</phrase></code>
would block the whole thread, preventing the other fiber from delivering its
value. Use <link linkend="class_future"> <code>future&lt;&gt;</code></link> instead.
</para>
<para>
Similarly, a fiber that invokes a normal blocking I/O operation will block
its entire thread. Fiber authors are encouraged to consistently use asynchronous
I/O. <ulink url="http://www.boost.org/doc/libs/release/libs/asio/index.html">Boost.Asio</ulink>
and other asynchronous I/O operations can straightforwardly be adapted for
<emphasis role="bold">Boost.Fiber</emphasis>: see <link linkend="callbacks">Integrating
Fibers with Asynchronous Callbacks</link>.
</para>
<warning>
<para>
This library is <emphasis>not</emphasis> an official Boost library.
</para>
</warning>
<para>
<emphasis role="bold">Boost.Fiber</emphasis> depends upon <ulink url="http://www.boost.org/doc/libs/release/libs/context/index.html">Boost.Context</ulink>.
Boost version 1.58.0 or greater is required.
</para>
<note>
<para>
This library is C++14-only!
</para>
</note>
</section>
<section id="fiber.rationale">
<title><link linkend="fiber.rationale">Rationale</link></title>
<bridgehead renderas="sect3" id="fiber.rationale.h0">
<phrase id="fiber.rationale.distinction_between_coroutines_and_fibers"/><link
linkend="fiber.rationale.distinction_between_coroutines_and_fibers">distinction
between coroutines and fibers</link>
</bridgehead>
<para>
The fiber library extends the coroutine library by adding a scheduler and synchronization
mechanisms.
</para>
<itemizedlist>
<listitem>
<simpara>
a coroutine yields
</simpara>
</listitem>
<listitem>
<simpara>
a fiber blocks
</simpara>
</listitem>
</itemizedlist>
<para>
When a coroutine yields, it passes control directly to its caller (or, in the
case of symmetric coroutines, a designated other coroutine). When a fiber blocks,
it implicitly passes control to the fiber scheduler. Coroutines have no scheduler
because they need no scheduler. <footnote id="fiber.rationale.f0">
<para>
<ulink url="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4024.pdf">'N4024:
Distinguishing coroutines and fibers'</ulink>
</para>
</footnote>.
</para>
<bridgehead renderas="sect3" id="fiber.rationale.h1">
<phrase id="fiber.rationale.what_about_transactional_memory"/><link linkend="fiber.rationale.what_about_transactional_memory">what
about transactional memory</link>
</bridgehead>
<para>
GCC supports transactional memory since version 4.7. Unfortunately tests show
that transactional memory is slower (ca. 4x) than spinlocks using atomics.
Once transactional memory is improved (supporting hybrid tm), spinlocks will
be replaced by __transaction_atomic{} statements surrounding the critical sections.
</para>
<bridgehead renderas="sect3" id="fiber.rationale.h2">
<phrase id="fiber.rationale.synchronization_between_fibers_running_in_different_threads"/><link
linkend="fiber.rationale.synchronization_between_fibers_running_in_different_threads">synchronization
between fibers running in different threads</link>
</bridgehead>
<para>
Synchronization classes from <ulink url="http://www.boost.org/doc/libs/release/libs/thread/index.html">Boost.Thread</ulink>
block the entire thread. In contrast, the synchronization classes from <emphasis
role="bold">Boost.Fiber</emphasis> block only specific fibers, so that the
scheduler can still keep the thread busy running other fibers in the meantime.
The synchronization classes from <emphasis role="bold">Boost.Fiber</emphasis>
are designed to be thread-safe, i.e. it is possible to synchronize fibers running
in different threads as well as fibers running in the same thread. (However,
there is a build option to disable cross-thread fiber synchronization support;
see <link linkend="cross_thread_sync">this description</link>.)
</para>
<bridgehead renderas="sect3" id="fiber.rationale.h3">
<phrase id="fiber.rationale.migrating_fibers_between_threads"/><link linkend="fiber.rationale.migrating_fibers_between_threads">migrating
fibers between threads</link>
</bridgehead>
<para>
Support for migrating fibers between threads was removed. Especially in the
case of NUMA-architectures, it is not always advisable to migrate data between
threads. Suppose fiber <emphasis>f</emphasis> is running on logical CPU <emphasis>cpu0</emphasis>
which belongs to NUMA node <emphasis>node0</emphasis>. The data of <emphasis>f</emphasis>
are allocated on the physical memory located at <emphasis>node0</emphasis>.
Migrating the fiber from <emphasis>cpu0</emphasis> to another logical CPU
<emphasis>cpuX</emphasis> which is part of a different NUMA node <emphasis>nodeX</emphasis>
will reduce the performance of the application because of increased latency
of memory access.
</para>
<para>
A more <emphasis role="bold">important</emphasis> aspect is the problem with
thread-local-storage (<emphasis role="bold">TLS</emphasis>). Instead of recomputing
the address of a TLS variable, a compiler might, as an optimization, cache
its previously-computed address in various function stack frames.<footnote
id="fiber.rationale.f1">
<para>
dicussed in <ulink url="http://www.crystalclearsoftware.com/soc/coroutine/coroutine/coroutine_thread.html">'Interaction
between coroutines and threads' by Giovanni P. Deretta, <ulink url="https://groups.google.com/a/isocpp.org/forum/#!topic/std-proposals/3g6ZIWedGJ8">'A
proposal to add coroutines to C++'</ulink></ulink>
</para>
</footnote> If a fiber was running on thread <emphasis>t0</emphasis> and then
migrated to thread <emphasis>t1</emphasis>, the cached TLS variable address(es)
would continue pointing to the TLS for thread <emphasis>t0</emphasis>. Bad
things would ensue.
</para>
<bridgehead renderas="sect3" id="fiber.rationale.h4">
<phrase id="fiber.rationale.support_for_boost_asio"/><link linkend="fiber.rationale.support_for_boost_asio">support
for Boost.Asio</link>
</bridgehead>
<para>
Support for <ulink url="http://www.boost.org/doc/libs/release/libs/asio/index.html">Boost.Asio</ulink>'s
<emphasis>async-result</emphasis> is not part of the official API. However,
to integrate with a <code><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase
role="identifier">asio</phrase><phrase role="special">::</phrase><phrase role="identifier">io_service</phrase></code>,
see <link linkend="integration">Sharing a Thread with Another Main Loop</link>.
To interface smoothly with an arbitrary Asio async I/O operation, see <link
linkend="callbacks_asio">Then There's <ulink url="http://www.boost.org/doc/libs/release/libs/asio/index.html">Boost.Asio</ulink></link>.
</para>
<bridgehead renderas="sect3" id="fiber.rationale.h5">
<phrase id="fiber.rationale.tested_compilers"/><link linkend="fiber.rationale.tested_compilers">tested
compilers</link>
</bridgehead>
<para>
The library was tested with GCC-4.9.2, GCC-5.1.1, Clang-3.6.0 and MSVC-14.0
in c++14-mode.
</para>
<bridgehead renderas="sect3" id="fiber.rationale.h6">
<phrase id="fiber.rationale.supported_architectures"/><link linkend="fiber.rationale.supported_architectures">supported
architectures</link>
</bridgehead>
<para>
<emphasis role="bold">Boost.Fiber</emphasis> depends on <ulink url="http://www.boost.org/doc/libs/release/libs/context/index.html">Boost.Context</ulink>
- the list of supported architectures can be found <ulink url="http://www.boost.org/doc/libs/release/libs/context/doc/html/context/architectures.html">here</ulink>.
</para>
</section>
<section id="fiber.fiber_mgmt">
<title><link linkend="fiber.fiber_mgmt">Fiber management</link></title>
<bridgehead renderas="sect3" id="fiber.fiber_mgmt.h0">
<phrase id="fiber.fiber_mgmt.synopsis"/><link linkend="fiber.fiber_mgmt.synopsis">Synopsis</link>
</bridgehead>
<programlisting><phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">fiber</phrase><phrase role="special">/</phrase><phrase role="identifier">all</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase>
<phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase>
<phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase>
<phrase role="keyword">class</phrase> <phrase role="identifier">fiber</phrase><phrase role="special">;</phrase>
<phrase role="keyword">bool</phrase> <phrase role="keyword">operator</phrase><phrase role="special">&lt;(</phrase> <phrase role="identifier">fiber</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">l</phrase><phrase role="special">,</phrase> <phrase role="identifier">fiber</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">r</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
<phrase role="keyword">void</phrase> <phrase role="identifier">swap</phrase><phrase role="special">(</phrase> <phrase role="identifier">fiber</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">l</phrase><phrase role="special">,</phrase> <phrase role="identifier">fiber</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">r</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
<phrase role="keyword">struct</phrase> <phrase role="identifier">sched_algorithm</phrase><phrase role="special">;</phrase>
<phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">PROPS</phrase> <phrase role="special">&gt;</phrase>
<phrase role="keyword">struct</phrase> <phrase role="identifier">sched_algorithm_with_properties</phrase><phrase role="special">;</phrase>
<phrase role="keyword">class</phrase> <phrase role="identifier">round_robin</phrase><phrase role="special">;</phrase>
<phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">SchedAlgo</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="special">...</phrase> <phrase role="identifier">Args</phrase> <phrase role="special">&gt;</phrase>
<phrase role="keyword">void</phrase> <phrase role="identifier">use_scheduling_algorithm</phrase><phrase role="special">(</phrase> <phrase role="identifier">Args</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="special">...</phrase> <phrase role="identifier">args</phrase><phrase role="special">);</phrase>
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">ready_fibers</phrase><phrase role="special">();</phrase>
<phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Rep</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Period</phrase> <phrase role="special">&gt;</phrase>
<phrase role="keyword">void</phrase> <phrase role="identifier">wait_interval</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">duration</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Rep</phrase><phrase role="special">,</phrase> <phrase role="identifier">Period</phrase> <phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">wait_interval</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
<phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Rep</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Period</phrase> <phrase role="special">&gt;</phrase>
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">duration</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Rep</phrase><phrase role="special">,</phrase> <phrase role="identifier">Period</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">wait_interval</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
<phrase role="special">}</phrase>
<phrase role="keyword">namespace</phrase> <phrase role="identifier">this_fiber</phrase> <phrase role="special">{</phrase>
<phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">id</phrase> <phrase role="identifier">get_id</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
<phrase role="keyword">void</phrase> <phrase role="identifier">yield</phrase><phrase role="special">();</phrase>
<phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Clock</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Duration</phrase> <phrase role="special">&gt;</phrase>
<phrase role="keyword">void</phrase> <phrase role="identifier">sleep_until</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">time_point</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Clock</phrase><phrase role="special">,</phrase> <phrase role="identifier">Duration</phrase> <phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">sleep_time</phrase><phrase role="special">)</phrase>
<phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Rep</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Period</phrase> <phrase role="special">&gt;</phrase>
<phrase role="keyword">void</phrase> <phrase role="identifier">sleep_for</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">duration</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Rep</phrase><phrase role="special">,</phrase> <phrase role="identifier">Period</phrase> <phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">timeout_duration</phrase><phrase role="special">);</phrase>
<phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">PROPS</phrase> <phrase role="special">&gt;</phrase>
<phrase role="identifier">PROPS</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">properties</phrase><phrase role="special">();</phrase>
<phrase role="keyword">void</phrase> <phrase role="identifier">interruption_point</phrase><phrase role="special">();</phrase>
<phrase role="keyword">bool</phrase> <phrase role="identifier">interruption_requested</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
<phrase role="keyword">bool</phrase> <phrase role="identifier">interruption_enabled</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
<phrase role="keyword">class</phrase> <phrase role="identifier">disable_interruption</phrase><phrase role="special">;</phrase>
<phrase role="keyword">class</phrase> <phrase role="identifier">restore_interruption</phrase><phrase role="special">;</phrase>
<phrase role="special">}}</phrase>
</programlisting>
<bridgehead renderas="sect3" id="fiber.fiber_mgmt.h1">
<phrase id="fiber.fiber_mgmt.tutorial"/><link linkend="fiber.fiber_mgmt.tutorial">Tutorial</link>
</bridgehead>
<para>
Each <link linkend="class_fiber"> <code>fiber</code></link> represents a micro-thread which will be launched and managed
cooperatively by a scheduler. Objects of type <link linkend="class_fiber"> <code>fiber</code></link> are move-only.
</para>
<programlisting><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">fiber</phrase> <phrase role="identifier">f1</phrase><phrase role="special">;</phrase> <phrase role="comment">// not-a-fiber</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">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">fiber</phrase> <phrase role="identifier">f2</phrase><phrase role="special">(</phrase> <phrase role="identifier">some_fn</phrase><phrase role="special">);</phrase>
<phrase role="identifier">f1</phrase> <phrase role="special">=</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">move</phrase><phrase role="special">(</phrase> <phrase role="identifier">f2</phrase><phrase role="special">);</phrase> <phrase role="comment">// f2 moved to f1</phrase>
<phrase role="special">}</phrase>
</programlisting>
<bridgehead renderas="sect3" id="fiber.fiber_mgmt.h2">
<phrase id="fiber.fiber_mgmt.launching"/><link linkend="fiber.fiber_mgmt.launching">Launching</link>
</bridgehead>
<para>
A new fiber is launched by passing an object of a callable type that can be
invoked with no parameters. If the object must not be copied or moved, then
<emphasis>std::ref</emphasis> can be used to pass in a reference to the function
object. In this case, the user must ensure that the referenced object outlives
the newly-created fiber.
</para>
<programlisting><phrase role="keyword">struct</phrase> <phrase role="identifier">callable</phrase> <phrase role="special">{</phrase>
<phrase role="keyword">void</phrase> <phrase role="keyword">operator</phrase><phrase role="special">()();</phrase>
<phrase role="special">};</phrase>
<phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">fiber</phrase> <phrase role="identifier">copies_are_safe</phrase><phrase role="special">()</phrase> <phrase role="special">{</phrase>
<phrase role="identifier">callable</phrase> <phrase role="identifier">x</phrase><phrase role="special">;</phrase>
<phrase role="keyword">return</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">fiber</phrase><phrase role="special">(</phrase> <phrase role="identifier">x</phrase><phrase role="special">);</phrase>
<phrase role="special">}</phrase> <phrase role="comment">// x is destroyed, but the newly-created fiber has a copy, so this is OK</phrase>
<phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">fiber</phrase> <phrase role="identifier">oops</phrase><phrase role="special">()</phrase> <phrase role="special">{</phrase>
<phrase role="identifier">callable</phrase> <phrase role="identifier">x</phrase><phrase role="special">;</phrase>
<phrase role="keyword">return</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">fiber</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">ref</phrase><phrase role="special">(</phrase> <phrase role="identifier">x</phrase><phrase role="special">)</phrase> <phrase role="special">);</phrase>
<phrase role="special">}</phrase> <phrase role="comment">// x is destroyed, but the newly-created fiber still has a reference</phrase>
<phrase role="comment">// this leads to undefined behaviour</phrase>
</programlisting>
<para>
The spawned <link linkend="class_fiber"> <code>fiber</code></link> does not immediately start running. It is enqueued
in the list of ready-to-run fibers, and will run when the scheduler gets around
to it.
</para>
<anchor id="exceptions"/>
<bridgehead renderas="sect3" id="fiber.fiber_mgmt.h3">
<phrase id="fiber.fiber_mgmt.exceptions"/><link linkend="fiber.fiber_mgmt.exceptions">Exceptions</link>
</bridgehead>
<para>
An exception escaping from the function or callable object passed to the <link linkend="class_fiber"> <code>fiber</code></link>
constructor
calls <code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase
role="identifier">terminate</phrase><phrase role="special">()</phrase></code>.
If you need to know which exception was thrown, use <link linkend="class_future"> <code>future&lt;&gt;</code></link> and
<link linkend="class_packaged_task"> <code>packaged_task&lt;&gt;</code></link>.
</para>
<bridgehead renderas="sect3" id="fiber.fiber_mgmt.h4">
<phrase id="fiber.fiber_mgmt.detaching"/><link linkend="fiber.fiber_mgmt.detaching">Detaching</link>
</bridgehead>
<para>
A <link linkend="class_fiber"> <code>fiber</code></link> can be detached by explicitly invoking the <link linkend="fiber_detach"> <code>fiber::detach()</code></link> member
function. After <link linkend="fiber_detach"> <code>fiber::detach()</code></link> is called on a fiber object, that
object represents <emphasis>not-a-fiber</emphasis>. The fiber object may then
safely be destroyed.
</para>
<programlisting><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">fiber</phrase><phrase role="special">(</phrase> <phrase role="identifier">some_fn</phrase><phrase role="special">).</phrase><phrase role="identifier">detach</phrase><phrase role="special">();</phrase>
</programlisting>
<para>
<emphasis role="bold">Boost.Fiber</emphasis> provides a number of ways to wait
for a running fiber to complete. You can coordinate even with a detached fiber
using a <link linkend="class_mutex"> <code>mutex</code></link>, or <link linkend="class_condition_variable"> <code>condition_variable</code></link>, or
any of the other <link linkend="synchronization">synchronization objects</link>
provided by the library.
</para>
<para>
If a detached fiber is still running when the thread's main fiber terminates,
that fiber will be <link linkend="interruption">interrupted</link> and shut
down.<footnote id="fiber.fiber_mgmt.f0">
<para>
This treatment of detached fibers depends on a detached fiber eventually
either terminating or reaching one of the specified <link linkend="interruption"><emphasis>interruption-points</emphasis></link>.
Note that since <link linkend="this_fiber_yield"> <code>this_fiber::yield()</code></link> is <emphasis>not</emphasis>
an interruption point, a detached fiber whose only interaction with the Fiber
library is <code><phrase role="identifier">yield</phrase><phrase role="special">()</phrase></code>
cannot cleanly be terminated.
</para>
</footnote>
</para>
<bridgehead renderas="sect3" id="fiber.fiber_mgmt.h5">
<phrase id="fiber.fiber_mgmt.joining"/><link linkend="fiber.fiber_mgmt.joining">Joining</link>
</bridgehead>
<para>
In order to wait for a fiber to finish, the <link linkend="fiber_join"> <code>fiber::join()</code></link> member function
of the <link linkend="class_fiber"> <code>fiber</code></link> object can be used. <link linkend="fiber_join"> <code>fiber::join()</code></link> will block
until the <link linkend="class_fiber"> <code>fiber</code></link> object has completed. If the <link linkend="class_fiber"> <code>fiber</code></link> has
already completed then <link linkend="fiber_join"> <code>fiber::join()</code></link> returns immediately.
</para>
<programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">some_fn</phrase><phrase role="special">()</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">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">fiber</phrase> <phrase role="identifier">f</phrase><phrase role="special">(</phrase> <phrase role="identifier">some_fn</phrase><phrase role="special">);</phrase>
<phrase role="special">...</phrase>
<phrase role="identifier">f</phrase><phrase role="special">.</phrase><phrase role="identifier">join</phrase><phrase role="special">();</phrase>
</programlisting>
<para>
If the fiber has already completed, then <link linkend="fiber_join"> <code>fiber::join()</code></link> returns immediately
and the joined <link linkend="class_fiber"> <code>fiber</code></link> object becomes <emphasis>not-a-fiber</emphasis>.
</para>
<bridgehead renderas="sect3" id="fiber.fiber_mgmt.h6">
<phrase id="fiber.fiber_mgmt.destruction"/><link linkend="fiber.fiber_mgmt.destruction">Destruction</link>
</bridgehead>
<para>
When a <link linkend="class_fiber"> <code>fiber</code></link> object representing a valid execution context (the fiber
is <link linkend="fiber_joinable"> <code>fiber::joinable()</code></link>) is destroyed, the program terminates. If
you intend the fiber to outlive the <link linkend="class_fiber"> <code>fiber</code></link> object that launched it,
use the <link linkend="fiber_detach"> <code>fiber::detach()</code></link> method.
</para>
<programlisting><phrase role="special">{</phrase>
<phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">fiber</phrase> <phrase role="identifier">f</phrase><phrase role="special">(</phrase> <phrase role="identifier">some_fn</phrase><phrase role="special">);</phrase>
<phrase role="special">}</phrase> <phrase role="comment">// std::terminate() will be called</phrase>
<phrase role="special">{</phrase>
<phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">fiber</phrase> <phrase role="identifier">f</phrase><phrase role="special">(</phrase><phrase role="identifier">some_fn</phrase><phrase role="special">);</phrase>
<phrase role="identifier">f</phrase><phrase role="special">.</phrase><phrase role="identifier">detach</phrase><phrase role="special">();</phrase>
<phrase role="special">}</phrase> <phrase role="comment">// okay, program continues</phrase>
</programlisting>
<anchor id="interruption"/>
<bridgehead renderas="sect3" id="fiber.fiber_mgmt.h7">
<phrase id="fiber.fiber_mgmt.interruption"/><link linkend="fiber.fiber_mgmt.interruption">Interruption</link>
</bridgehead>
<para>
A valid fiber can be interrupted by invoking its <link linkend="fiber_interrupt"> <code>fiber::interrupt()</code></link> member
function. The next time that fiber executes one of the specific <link linkend="interruption"><emphasis>interruption-points</emphasis></link>
with interruption enabled, a <code><phrase role="identifier">fiber_interrupted</phrase></code>
exception will be thrown. If this exception is not caught, the fiber will be
terminated, its stack unwound, its stack objects properly destroyed.
</para>
<para>
With <link linkend="class_disable_interruption"> <code>disable_interruption</code></link> a fiber can avoid being
interrupted.
</para>
<programlisting><phrase role="comment">// interruption enabled at this point</phrase>
<phrase role="special">{</phrase>
<phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">this_fiber</phrase><phrase role="special">::</phrase><phrase role="identifier">disable_interruption</phrase> <phrase role="identifier">di1</phrase><phrase role="special">;</phrase>
<phrase role="comment">// interruption disabled</phrase>
<phrase role="special">{</phrase>
<phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="keyword">this</phrase><phrase role="special">::</phrase><phrase role="identifier">fiber</phrase><phrase role="special">::</phrase><phrase role="identifier">disable_interruption</phrase> <phrase role="identifier">di2</phrase><phrase role="special">;</phrase>
<phrase role="comment">// interruption still disabled</phrase>
<phrase role="special">}</phrase> <phrase role="comment">// di2 destroyed; interruption state restored</phrase>
<phrase role="comment">// interruption still disabled</phrase>
<phrase role="special">}</phrase> <phrase role="comment">// di destroyed; interruption state restored</phrase>
<phrase role="comment">// interruption enabled</phrase>
</programlisting>
<para>
At any point, the interruption state for the current thread can be queried
by calling <link linkend="this_fiber_interruption_enabled"> <code>this_fiber::interruption_enabled()</code></link>.
The following <link linkend="interruption"><emphasis>interruption-points</emphasis></link>
are defined and will throw <code><phrase role="identifier">fiber_interrupted</phrase></code>
if <link linkend="this_fiber_interruption_requested"> <code>this_fiber::interruption_requested()</code></link> and
<link linkend="this_fiber_interruption_enabled"> <code>this_fiber::interruption_enabled()</code></link>.
</para>
<itemizedlist>
<listitem>
<simpara>
<link linkend="fiber_join"> <code>fiber::join()</code></link>
</simpara>
</listitem>
<listitem>
<simpara>
<link linkend="barrier_wait"> <code>barrier::wait()</code></link>
</simpara>
</listitem>
<listitem>
<simpara>
<link linkend="condition_variable_wait"> <code>condition_variable::wait()</code></link>
</simpara>
</listitem>
<listitem>
<simpara>
<link linkend="condition_variable_wait_for"> <code>condition_variable::wait_for()</code></link>
</simpara>
</listitem>
<listitem>
<simpara>
<link linkend="condition_variable_wait_until"> <code>condition_variable::wait_until()</code></link>
</simpara>
</listitem>
<listitem>
<simpara>
<link linkend="mutex_lock"> <code>mutex::lock()</code></link> ( <link linkend="class_recursive_mutex"> <code>recursive_mutex</code></link>, <link linkend="class_recursive_timed_mutex"> <code>recursive_timed_mutex</code></link>,
<link linkend="class_timed_mutex"> <code>timed_mutex</code></link>)
</simpara>
</listitem>
<listitem>
<simpara>
<link linkend="mutex_try_lock"> <code>mutex::try_lock()</code></link> ( <link linkend="class_recursive_mutex"> <code>recursive_mutex</code></link>,
<link linkend="class_recursive_timed_mutex"> <code>recursive_timed_mutex</code></link>, <link linkend="class_timed_mutex"> <code>timed_mutex</code></link>)
</simpara>
</listitem>
<listitem>
<simpara>
<link linkend="this_fiber_sleep_for"> <code>this_fiber::sleep_for()</code></link>
</simpara>
</listitem>
<listitem>
<simpara>
<link linkend="this_fiber_sleep_until"> <code>this_fiber::sleep_until()</code></link>
</simpara>
</listitem>
<listitem>
<simpara>
<link linkend="this_fiber_interruption_point"> <code>this_fiber::interruption_point()</code></link>
</simpara>
</listitem>
<listitem>
<simpara>
<link linkend="bounded_channel_push"> <code>bounded_channel::push()</code></link>
</simpara>
</listitem>
<listitem>
<simpara>
<link linkend="bounded_channel_try_push"> <code>bounded_channel::try_push()</code></link>
</simpara>
</listitem>
<listitem>
<simpara>
<link linkend="bounded_channel_push_wait_for"> <code>bounded_channel::push_wait_for()</code></link>
</simpara>
</listitem>
<listitem>
<simpara>
<link linkend="bounded_channel_push_wait_until"> <code>bounded_channel::push_wait_until()</code></link>
</simpara>
</listitem>
<listitem>
<simpara>
<link linkend="bounded_channel_pop"> <code>bounded_channel::pop()</code></link>
</simpara>
</listitem>
<listitem>
<simpara>
<link linkend="bounded_channel_try_pop"> <code>bounded_channel::try_pop()</code></link>
</simpara>
</listitem>
<listitem>
<simpara>
<link linkend="bounded_channel_value_pop"> <code>bounded_channel::value_pop()</code></link>
</simpara>
</listitem>
<listitem>
<simpara>
<link linkend="bounded_channel_pop_wait_for"> <code>bounded_channel::pop_wait_for()</code></link>
</simpara>
</listitem>
<listitem>
<simpara>
<link linkend="bounded_channel_pop_wait_until"> <code>bounded_channel::pop_wait_until()</code></link>
</simpara>
</listitem>
<listitem>
<simpara>
<link linkend="unbounded_channel_push"> <code>unbounded_channel::push()</code></link>
</simpara>
</listitem>
<listitem>
<simpara>
<link linkend="unbounded_channel_pop"> <code>unbounded_channel::pop()</code></link>
</simpara>
</listitem>
<listitem>
<simpara>
<link linkend="unbounded_channel_try_pop"> <code>unbounded_channel::try_pop()</code></link>
</simpara>
</listitem>
<listitem>
<simpara>
<link linkend="unbounded_channel_value_pop"> <code>unbounded_channel::value_pop()</code></link>
</simpara>
</listitem>
<listitem>
<simpara>
<link linkend="unbounded_channel_pop_wait_for"> <code>unbounded_channel::pop_wait_for()</code></link>
</simpara>
</listitem>
<listitem>
<simpara>
<link linkend="unbounded_channel_pop_wait_until"> <code>unbounded_channel::pop_wait_until()</code></link>
</simpara>
</listitem>
<listitem>
<simpara>
<link linkend="future_wait"> <code>future::wait()</code></link>
</simpara>
</listitem>
<listitem>
<simpara>
<link linkend="future_get"> <code>future::get()</code></link>
</simpara>
</listitem>
<listitem>
<simpara>
<link linkend="future_get_exception_ptr"> <code>future::get_exception_ptr()</code></link>
</simpara>
</listitem>
<listitem>
<simpara>
<link linkend="shared_future_wait"> <code>shared_future::wait()</code></link>
</simpara>
</listitem>
<listitem>
<simpara>
<link linkend="shared_future_get"> <code>shared_future::get()</code></link>
</simpara>
</listitem>
<listitem>
<simpara>
<link linkend="shared_future_get_exception_ptr"> <code>shared_future::get_exception_ptr()</code></link>
</simpara>
</listitem>
</itemizedlist>
<anchor id="class_fiber_id"/>
<bridgehead renderas="sect3" id="fiber.fiber_mgmt.h8">
<phrase id="fiber.fiber_mgmt.fiber_ids"/><link linkend="fiber.fiber_mgmt.fiber_ids">Fiber
IDs</link>
</bridgehead>
<para>
Objects of class <link linkend="class_fiber_id"><code><phrase role="identifier">fiber</phrase><phrase
role="special">::</phrase><phrase role="identifier">id</phrase></code></link> can be
used to identify fibers. Each running <link linkend="class_fiber"> <code>fiber</code></link> has a unique <link linkend="class_fiber_id"><code><phrase
role="identifier">fiber</phrase><phrase role="special">::</phrase><phrase role="identifier">id</phrase></code></link> obtainable
from the corresponding <link linkend="class_fiber"> <code>fiber</code></link>
by calling the <link linkend="fiber_get_id"> <code>fiber::get_id()</code></link> member
function. Objects of class <link linkend="class_fiber_id"><code><phrase role="identifier">fiber</phrase><phrase
role="special">::</phrase><phrase role="identifier">id</phrase></code></link> can be
copied, and used as keys in associative containers: the full range of comparison
operators is provided. They can also be written to an output stream using the
stream insertion operator, though the output format is unspecified.
</para>
<para>
Each instance of <link linkend="class_fiber_id"><code><phrase role="identifier">fiber</phrase><phrase
role="special">::</phrase><phrase role="identifier">id</phrase></code></link> either
refers to some fiber, or <emphasis>not-a-fiber</emphasis>. Instances that refer
to <emphasis>not-a-fiber</emphasis> compare equal to each other, but not equal
to any instances that refer to an actual fiber. The comparison operators on
<link linkend="class_fiber_id"><code><phrase role="identifier">fiber</phrase><phrase role="special">::</phrase><phrase
role="identifier">id</phrase></code></link> yield a total order for every non-equal
<link linkend="class_fiber_id"><code><phrase role="identifier">fiber</phrase><phrase role="special">::</phrase><phrase
role="identifier">id</phrase></code></link>.
</para>
<section id="fiber.fiber_mgmt.fiber">
<title><anchor id="class_fiber"/><link linkend="fiber.fiber_mgmt.fiber">Class
<code><phrase role="identifier">fiber</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">fiber</phrase><phrase role="special">/</phrase><phrase role="identifier">fiber</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase>
<phrase role="keyword">class</phrase> <phrase role="identifier">fiber</phrase> <phrase role="special">{</phrase>
<phrase role="keyword">public</phrase><phrase role="special">:</phrase>
<phrase role="keyword">class</phrase> <phrase role="identifier">id</phrase><phrase role="special">;</phrase>
<phrase role="identifier">fiber</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
<phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Fn</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="special">...</phrase> <phrase role="identifier">Args</phrase> <phrase role="special">&gt;</phrase>
<phrase role="keyword">explicit</phrase> <phrase role="identifier">fiber</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">Args</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="special">...</phrase> <phrase role="identifier">args</phrase><phrase role="special">);</phrase>
<phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">StackAllocator</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Fn</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="special">...</phrase> <phrase role="identifier">Args</phrase> <phrase role="special">&gt;</phrase>
<phrase role="keyword">explicit</phrase> <phrase role="identifier">fiber</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">allocator_arg_t</phrase><phrase role="special">,</phrase> <phrase role="identifier">StackAllocator</phrase> <phrase role="identifier">salloc</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">Args</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="special">...</phrase> <phrase role="identifier">args</phrase><phrase role="special">);</phrase>
<phrase role="special">~</phrase><phrase role="identifier">fiber</phrase><phrase role="special">();</phrase>
<phrase role="identifier">fiber</phrase><phrase role="special">(</phrase> <phrase role="identifier">fiber</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="special">=</phrase> <phrase role="keyword">delete</phrase><phrase role="special">;</phrase>
<phrase role="identifier">fiber</phrase> <phrase role="special">&amp;</phrase> <phrase role="keyword">operator</phrase><phrase role="special">=(</phrase> <phrase role="identifier">fiber</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="special">=</phrase> <phrase role="keyword">delete</phrase><phrase role="special">;</phrase>
<phrase role="identifier">fiber</phrase><phrase role="special">(</phrase> <phrase role="identifier">fiber</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
<phrase role="identifier">fiber</phrase> <phrase role="special">&amp;</phrase> <phrase role="keyword">operator</phrase><phrase role="special">=(</phrase> <phrase role="identifier">fiber</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
<phrase role="keyword">explicit</phrase> <phrase role="keyword">operator</phrase> <phrase role="keyword">bool</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
<phrase role="keyword">bool</phrase> <phrase role="keyword">operator</phrase><phrase role="special">!()</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
<phrase role="keyword">void</phrase> <phrase role="identifier">swap</phrase><phrase role="special">(</phrase> <phrase role="identifier">fiber</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
<phrase role="keyword">bool</phrase> <phrase role="identifier">joinable</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
<phrase role="identifier">id</phrase> <phrase role="identifier">get_id</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
<phrase role="keyword">void</phrase> <phrase role="identifier">detach</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
<phrase role="keyword">void</phrase> <phrase role="identifier">join</phrase><phrase role="special">();</phrase>
<phrase role="keyword">void</phrase> <phrase role="identifier">interrupt</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
<phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">PROPS</phrase> <phrase role="special">&gt;</phrase>
<phrase role="identifier">PROPS</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">properties</phrase><phrase role="special">();</phrase>
<phrase role="special">};</phrase>
<phrase role="keyword">bool</phrase> <phrase role="keyword">operator</phrase><phrase role="special">&lt;(</phrase> <phrase role="identifier">fiber</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">l</phrase><phrase role="special">,</phrase> <phrase role="identifier">fiber</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">r</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
<phrase role="keyword">void</phrase> <phrase role="identifier">swap</phrase><phrase role="special">(</phrase> <phrase role="identifier">fiber</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">l</phrase><phrase role="special">,</phrase> <phrase role="identifier">fiber</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">r</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
<phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">SchedAlgo</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="special">...</phrase> <phrase role="identifier">Args</phrase> <phrase role="special">&gt;</phrase>
<phrase role="keyword">void</phrase> <phrase role="identifier">use_scheduling_algorithm</phrase><phrase role="special">(</phrase> <phrase role="identifier">Args</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="special">...</phrase> <phrase role="identifier">args</phrase><phrase role="special">);</phrase>
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">ready_fibers</phrase><phrase role="special">();</phrase>
<phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Rep</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Period</phrase> <phrase role="special">&gt;</phrase>
<phrase role="keyword">void</phrase> <phrase role="identifier">wait_interval</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">duration</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Rep</phrase><phrase role="special">,</phrase> <phrase role="identifier">Period</phrase> <phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">wait_interval</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
<phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Rep</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Period</phrase> <phrase role="special">&gt;</phrase>
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">duration</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Rep</phrase><phrase role="special">,</phrase> <phrase role="identifier">Period</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">wait_interval</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
</programlisting>
<bridgehead renderas="sect4" id="fiber.fiber_mgmt.fiber.h0">
<phrase id="fiber.fiber_mgmt.fiber.default_constructor"/><link linkend="fiber.fiber_mgmt.fiber.default_constructor">Default
constructor</link>
</bridgehead>
<programlisting><phrase role="identifier">fiber</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
</programlisting>
<variablelist>
<title></title>
<varlistentry>
<term>Effects:</term>
<listitem>
<para>
Constructs a <link linkend="class_fiber"> <code>fiber</code></link> instance that refers to <emphasis>not-a-fiber</emphasis>.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Postconditions:</term>
<listitem>
<para>
<code><phrase role="keyword">this</phrase><phrase role="special">-&gt;</phrase><phrase
role="identifier">get_id</phrase><phrase role="special">()</phrase>
<phrase role="special">==</phrase> <phrase role="identifier">fiber</phrase><phrase
role="special">::</phrase><phrase role="identifier">id</phrase><phrase
role="special">()</phrase></code>
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Throws:</term>
<listitem>
<para>
Nothing
</para>
</listitem>
</varlistentry>
</variablelist>
<anchor id="fiber_fiber"/>
<bridgehead renderas="sect4" id="fiber.fiber_mgmt.fiber.h1">
<phrase id="fiber.fiber_mgmt.fiber.constructor"/><link linkend="fiber.fiber_mgmt.fiber.constructor">Constructor</link>
</bridgehead>
<programlisting><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="special">...</phrase> <phrase role="identifier">Args</phrase> <phrase role="special">&gt;</phrase>
<phrase role="keyword">explicit</phrase> <phrase role="identifier">fiber</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">Args</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="special">...</phrase> <phrase role="identifier">args</phrase><phrase role="special">);</phrase>
<phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">StackAllocator</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Fn</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="special">...</phrase> <phrase role="identifier">Args</phrase> <phrase role="special">&gt;</phrase>
<phrase role="keyword">explicit</phrase> <phrase role="identifier">fiber</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">allocator_arg_t</phrase><phrase role="special">,</phrase> <phrase role="identifier">StackAllocator</phrase> <phrase role="identifier">salloc</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">Args</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="special">...</phrase> <phrase role="identifier">args</phrase><phrase role="special">);</phrase>
</programlisting>
<variablelist>
<title></title>
<varlistentry>
<term>Preconditions:</term>
<listitem>
<para>
<code><phrase role="identifier">Fn</phrase></code> must be copyable
or movable.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Effects:</term>
<listitem>
<para>
<code><phrase role="identifier">fn</phrase></code> is copied or moved
into internal storage for access by the new fiber.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Postconditions:</term>
<listitem>
<para>
<code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>
refers to the newly created fiber of execution.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Throws:</term>
<listitem>
<para>
<code><phrase role="identifier">fiber_exception</phrase></code> if
an error occurs.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Note:</term>
<listitem>
<para>
StackAllocator is required to allocate a stack for the internal <ulink
url="http://www.boost.org/doc/libs/release/libs/context/doc/html/context/econtext.html"><emphasis>execution_context</emphasis></ulink>.
If StackAllocator is not explicitly passed, a <link linkend="class_fixedsize_stack"> <code>fixedsize_stack</code></link> is
used by default.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>See also:</term>
<listitem>
<para>
<ulink url="http://en.cppreference.com/w/cpp/memory/allocator_arg_t"><code><phrase
role="identifier">std</phrase><phrase role="special">::</phrase><phrase
role="identifier">allocator_arg_t</phrase></code></ulink>, <link linkend="stack">Stack
allocation</link>
</para>
</listitem>
</varlistentry>
</variablelist>
<bridgehead renderas="sect4" id="fiber.fiber_mgmt.fiber.h2">
<phrase id="fiber.fiber_mgmt.fiber.move_constructor"/><link linkend="fiber.fiber_mgmt.fiber.move_constructor">Move
constructor</link>
</bridgehead>
<programlisting><phrase role="identifier">fiber</phrase><phrase role="special">(</phrase> <phrase role="identifier">fiber</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
</programlisting>
<variablelist>
<title></title>
<varlistentry>
<term>Effects:</term>
<listitem>
<para>
Transfers ownership of the fiber managed by <code><phrase role="identifier">other</phrase></code>
to the newly constructed <link linkend="class_fiber"> <code>fiber</code></link> instance.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Postconditions:</term>
<listitem>
<para>
<code><phrase role="identifier">other</phrase><phrase role="special">.</phrase><phrase
role="identifier">get_id</phrase><phrase role="special">()</phrase>
<phrase role="special">==</phrase> <phrase role="identifier">fiber</phrase><phrase
role="special">::</phrase><phrase role="identifier">id</phrase><phrase
role="special">()</phrase></code> and <code><phrase role="identifier">get_id</phrase><phrase
role="special">()</phrase></code> returns the value of <code><phrase
role="identifier">other</phrase><phrase role="special">.</phrase><phrase
role="identifier">get_id</phrase><phrase role="special">()</phrase></code>
prior to the construction
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Throws:</term>
<listitem>
<para>
Nothing
</para>
</listitem>
</varlistentry>
</variablelist>
<bridgehead renderas="sect4" id="fiber.fiber_mgmt.fiber.h3">
<phrase id="fiber.fiber_mgmt.fiber.move_assignment_operator"/><link linkend="fiber.fiber_mgmt.fiber.move_assignment_operator">Move
assignment operator</link>
</bridgehead>
<programlisting><phrase role="identifier">fiber</phrase> <phrase role="special">&amp;</phrase> <phrase role="keyword">operator</phrase><phrase role="special">=(</phrase> <phrase role="identifier">fiber</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
</programlisting>
<variablelist>
<title></title>
<varlistentry>
<term>Effects:</term>
<listitem>
<para>
Transfers ownership of the fiber managed by <code><phrase role="identifier">other</phrase></code>
(if any) to <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Postconditions:</term>
<listitem>
<para>
<code><phrase role="identifier">other</phrase><phrase role="special">-&gt;</phrase><phrase
role="identifier">get_id</phrase><phrase role="special">()</phrase>
<phrase role="special">==</phrase> <phrase role="identifier">fiber</phrase><phrase
role="special">::</phrase><phrase role="identifier">id</phrase><phrase
role="special">()</phrase></code> and <code><phrase role="identifier">get_id</phrase><phrase
role="special">()</phrase></code> returns the value of <code><phrase
role="identifier">other</phrase><phrase role="special">.</phrase><phrase
role="identifier">get_id</phrase><phrase role="special">()</phrase></code>
prior to the assignment.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Throws:</term>
<listitem>
<para>
Nothing
</para>
</listitem>
</varlistentry>
</variablelist>
<bridgehead renderas="sect4" id="fiber.fiber_mgmt.fiber.h4">
<phrase id="fiber.fiber_mgmt.fiber.destructor"/><link linkend="fiber.fiber_mgmt.fiber.destructor">Destructor</link>
</bridgehead>
<programlisting><phrase role="special">~</phrase><phrase role="identifier">fiber</phrase><phrase role="special">();</phrase>
</programlisting>
<variablelist>
<title></title>
<varlistentry>
<term>Effects:</term>
<listitem>
<para>
If the fiber is <link linkend="fiber_joinable"> <code>fiber::joinable()</code></link>, calls std::terminate.
Destroys <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Throws:</term>
<listitem>
<para>
Nothing.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Note:</term>
<listitem>
<para>
The programmer must ensure that the destructor is never executed while
the fiber is still <link linkend="fiber_joinable"> <code>fiber::joinable()</code></link>. Even if you know
(by calling <link linkend="fiber_operator bool"> <code>fiber::operator bool()</code></link>) that the fiber
has completed, you must still call either <link linkend="fiber_join"> <code>fiber::join()</code></link> or
<link linkend="fiber_detach"> <code>fiber::detach()</code></link> before destroying the <code><phrase role="identifier">fiber</phrase></code>
object.
</para>
</listitem>
</varlistentry>
</variablelist>
<para>
<bridgehead renderas="sect4" id="fiber_joinable_bridgehead">
<phrase id="fiber_joinable"/>
<link linkend="fiber_joinable">Member function <code>joinable</code>()</link>
</bridgehead>
</para>
<programlisting><phrase role="keyword">bool</phrase> <phrase role="identifier">joinable</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
</programlisting>
<variablelist>
<title></title>
<varlistentry>
<term>Returns:</term>
<listitem>
<para>
<code><phrase role="keyword">true</phrase></code> if <code><phrase
role="special">*</phrase><phrase role="keyword">this</phrase></code>
refers to a fiber of execution, which may or may not have completed;
otherwise <code><phrase role="keyword">false</phrase></code>.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Throws:</term>
<listitem>
<para>
Nothing
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>See also:</term>
<listitem>
<para>
<link linkend="fiber_operator bool"> <code>fiber::operator bool()</code></link>
</para>
</listitem>
</varlistentry>
</variablelist>
<para>
<bridgehead renderas="sect4" id="fiber_join_bridgehead">
<phrase id="fiber_join"/>
<link linkend="fiber_join">Member function <code>join</code>()</link>
</bridgehead>
</para>
<programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">join</phrase><phrase role="special">();</phrase>
</programlisting>
<variablelist>
<title></title>
<varlistentry>
<term>Preconditions:</term>
<listitem>
<para>
the fiber is <link linkend="fiber_joinable"> <code>fiber::joinable()</code></link>.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Effects:</term>
<listitem>
<para>
Waits for the referenced fiber of execution to complete.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Postconditions:</term>
<listitem>
<para>
The fiber of execution referenced on entry has completed. <code><phrase
role="special">*</phrase><phrase role="keyword">this</phrase></code>
no longer refers to any fiber of execution.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Throws:</term>
<listitem>
<para>
<code><phrase role="identifier">fiber_interrupted</phrase></code> if
the current fiber is interrupted or <code><phrase role="identifier">system_error</phrase></code>
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Error Conditions:</term>
<listitem>
<para>
<emphasis role="bold">resource_deadlock_would_occur</emphasis>: if
<code><phrase role="keyword">this</phrase><phrase role="special">-&gt;</phrase><phrase
role="identifier">get_id</phrase><phrase role="special">()</phrase>
<phrase role="special">==</phrase> <phrase role="identifier">boost</phrase><phrase
role="special">::</phrase><phrase role="identifier">this_fiber</phrase><phrase
role="special">::</phrase><phrase role="identifier">get_id</phrase><phrase
role="special">()</phrase></code>. <emphasis role="bold">invalid_argument</emphasis>:
if the fiber is not <link linkend="fiber_joinable"> <code>fiber::joinable()</code></link>.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Notes:</term>
<listitem>
<para>
<code><phrase role="identifier">join</phrase><phrase role="special">()</phrase></code>
is one of the predefined <link linkend="interruption"><emphasis>interruption-points</emphasis></link>.
</para>
</listitem>
</varlistentry>
</variablelist>
<para>
<bridgehead renderas="sect4" id="fiber_detach_bridgehead">
<phrase id="fiber_detach"/>
<link linkend="fiber_detach">Member function <code>detach</code>()</link>
</bridgehead>
</para>
<programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">detach</phrase><phrase role="special">();</phrase>
</programlisting>
<variablelist>
<title></title>
<varlistentry>
<term>Preconditions:</term>
<listitem>
<para>
the fiber is <link linkend="fiber_joinable"> <code>fiber::joinable()</code></link>.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Effects:</term>
<listitem>
<para>
The fiber of execution becomes detached, and no longer has an associated
<link linkend="class_fiber"> <code>fiber</code></link> object.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Postconditions:</term>
<listitem>
<para>
<code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>
no longer refers to any fiber of execution.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Throws:</term>
<listitem>
<para>
<code><phrase role="identifier">system_error</phrase></code>
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Error Conditions:</term>
<listitem>
<para>
<emphasis role="bold">invalid_argument</emphasis>: if the fiber is
not <link linkend="fiber_joinable"> <code>fiber::joinable()</code></link>.
</para>
</listitem>
</varlistentry>
</variablelist>
<para>
<bridgehead renderas="sect4" id="fiber_get_id_bridgehead">
<phrase id="fiber_get_id"/>
<link linkend="fiber_get_id">Member function <code>get_id</code>()</link>
</bridgehead>
</para>
<programlisting><phrase role="identifier">fiber</phrase><phrase role="special">::</phrase><phrase role="identifier">id</phrase> <phrase role="identifier">get_id</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
</programlisting>
<variablelist>
<title></title>
<varlistentry>
<term>Returns:</term>
<listitem>
<para>
If <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>
refers to a fiber of execution, an instance of <link linkend="class_fiber_id"><code><phrase
role="identifier">fiber</phrase><phrase role="special">::</phrase><phrase
role="identifier">id</phrase></code></link> that represents that fiber. Otherwise
returns a default-constructed <link linkend="class_fiber_id"><code><phrase role="identifier">fiber</phrase><phrase
role="special">::</phrase><phrase role="identifier">id</phrase></code></link>.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Throws:</term>
<listitem>
<para>
Nothing
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>See also:</term>
<listitem>
<para>
<link linkend="this_fiber_get_id"> <code>this_fiber::get_id()</code></link>
</para>
</listitem>
</varlistentry>
</variablelist>
<para>
<bridgehead renderas="sect4" id="fiber_interrupt_bridgehead">
<phrase id="fiber_interrupt"/>
<link linkend="fiber_interrupt">Member function <code>interrupt</code>()</link>
</bridgehead>
</para>
<programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">interrupt</phrase><phrase role="special">();</phrase>
</programlisting>
<variablelist>
<title></title>
<varlistentry>
<term>Effects:</term>
<listitem>
<para>
If <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>
refers to a fiber of execution, request that the fiber will be interrupted
the next time it enters one of the predefined <link linkend="interruption"><emphasis>interruption-points</emphasis></link>
with interruption enabled, or if it is currently <link linkend="blocking"><emphasis>blocked</emphasis></link>
in a call to one of the predefined <link linkend="interruption"><emphasis>interruption-points</emphasis></link>
with interruption enabled.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Throws:</term>
<listitem>
<para>
Nothing
</para>
</listitem>
</varlistentry>
</variablelist>
<para>
<bridgehead renderas="sect4" id="fiber_properties_bridgehead">
<phrase id="fiber_properties"/>
<link linkend="fiber_properties">Templated member
function <code>properties</code>()</link>
</bridgehead>
</para>
<programlisting><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">PROPS</phrase> <phrase role="special">&gt;</phrase>
<phrase role="identifier">PROPS</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">properties</phrase><phrase role="special">();</phrase>
</programlisting>
<variablelist>
<title></title>
<varlistentry>
<term>Preconditions:</term>
<listitem>
<para>
<code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>
refers to a fiber of execution. <link linkend="use_scheduling_algorithm"> <code>use_scheduling_algorithm()</code></link> has
been called from this thread with a subclass of <link linkend="class_sched_algorithm_with_properties"> <code>sched_algorithm_with_properties&lt;&gt;</code></link> with
the same template argument <code><phrase role="identifier">PROPS</phrase></code>.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Returns:</term>
<listitem>
<para>
a reference to the scheduler properties instance for <code><phrase
role="special">*</phrase><phrase role="keyword">this</phrase></code>.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Throws:</term>
<listitem>
<para>
<code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase
role="identifier">bad_cast</phrase></code> if <code><phrase role="identifier">use_scheduling_algorithm</phrase><phrase
role="special">()</phrase></code> was called with a <code><phrase role="identifier">sched_algorithm_with_properties</phrase></code>
subclass with some other template parameter than <code><phrase role="identifier">PROPS</phrase></code>.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Note:</term>
<listitem>
<para>
<link linkend="class_sched_algorithm_with_properties"> <code>sched_algorithm_with_properties&lt;&gt;</code></link> provides
a way for a user-coded scheduler to associate extended properties,
such as priority, with a fiber instance. This method allows access
to those user-provided properties.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>See also:</term>
<listitem>
<para>
<link linkend="custom">Customization</link>
</para>
</listitem>
</varlistentry>
</variablelist>
<para>
<bridgehead renderas="sect4" id="fiber_operator bool_bridgehead">
<phrase id="fiber_operator bool"/>
<link linkend="fiber_operator bool">Member
function <code>operator bool</code>()</link>
</bridgehead>
</para>
<programlisting><phrase role="keyword">explicit</phrase> <phrase role="keyword">operator</phrase> <phrase role="keyword">bool</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
</programlisting>
<variablelist>
<title></title>
<varlistentry>
<term>Returns:</term>
<listitem>
<para>
<code><phrase role="keyword">true</phrase></code> if <code><phrase
role="special">*</phrase><phrase role="keyword">this</phrase></code>
refers to a fiber of execution which has not yet terminated, <code><phrase
role="keyword">false</phrase></code> otherwise. Compare to <link linkend="fiber_joinable"> <code>fiber::joinable()</code></link>,
which does not distinguish whether the referenced fiber of execution
is still running.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Throws:</term>
<listitem>
<para>
Nothing
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>See also:</term>
<listitem>
<para>
<link linkend="fiber_joinable"> <code>fiber::joinable()</code></link>
</para>
</listitem>
</varlistentry>
</variablelist>
<para>
<bridgehead renderas="sect4" id="fiber_operator_not_bridgehead">
<phrase id="fiber_operator_not"/>
<link linkend="fiber_operator_not">Member function
<code>operator!</code>()</link>
</bridgehead>
</para>
<programlisting><phrase role="keyword">bool</phrase> <phrase role="keyword">operator</phrase><phrase role="special">!()</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
</programlisting>
<variablelist>
<title></title>
<varlistentry>
<term>Returns:</term>
<listitem>
<para>
<code><phrase role="keyword">true</phrase></code> if <code><phrase
role="special">*</phrase><phrase role="keyword">this</phrase></code>
does not refer to a fiber of execution or if its fiber of execution
has terminated, <code><phrase role="keyword">false</phrase></code>
otherwise.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Throws:</term>
<listitem>
<para>
Nothing
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>See also:</term>
<listitem>
<para>
<link linkend="fiber_operator bool"> <code>fiber::operator bool()</code></link>, <link linkend="fiber_joinable"> <code>fiber::joinable()</code></link>
</para>
</listitem>
</varlistentry>
</variablelist>
<para>
<bridgehead renderas="sect4" id="fiber_swap_bridgehead">
<phrase id="fiber_swap"/>
<link linkend="fiber_swap">Member function <code>swap</code>()</link>
</bridgehead>
</para>
<programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">swap</phrase><phrase role="special">(</phrase> <phrase role="identifier">fiber</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
</programlisting>
<variablelist>
<title></title>
<varlistentry>
<term>Effects:</term>
<listitem>
<para>
Exchanges the fiber of execution associated with <code><phrase role="special">*</phrase><phrase
role="keyword">this</phrase></code> and <code><phrase role="identifier">other</phrase></code>,
so <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>
becomes associated with the fiber formerly associated with <code><phrase
role="identifier">other</phrase></code>, and vice-versa.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Postconditions:</term>
<listitem>
<para>
<code><phrase role="keyword">this</phrase><phrase role="special">-&gt;</phrase><phrase
role="identifier">get_id</phrase><phrase role="special">()</phrase></code>
returns the same value as <code><phrase role="identifier">other</phrase><phrase
role="special">.</phrase><phrase role="identifier">get_id</phrase><phrase
role="special">()</phrase></code> prior to the call. <code><phrase
role="identifier">other</phrase><phrase role="special">.</phrase><phrase
role="identifier">get_id</phrase><phrase role="special">()</phrase></code>
returns the same value as <code><phrase role="keyword">this</phrase><phrase
role="special">-&gt;</phrase><phrase role="identifier">get_id</phrase><phrase
role="special">()</phrase></code> prior to the call.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Throws:</term>
<listitem>
<para>
Nothing
</para>
</listitem>
</varlistentry>
</variablelist>
<para>
<bridgehead renderas="sect4" id="swap_bridgehead">
<phrase id="swap"/>
<link linkend="swap">Non-member function <code>swap()</code></link>
</bridgehead>
</para>
<programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">swap</phrase><phrase role="special">(</phrase> <phrase role="identifier">fiber</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">l</phrase><phrase role="special">,</phrase> <phrase role="identifier">fiber</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">r</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
</programlisting>
<variablelist>
<title></title>
<varlistentry>
<term>Effects:</term>
<listitem>
<para>
Same as <code><phrase role="identifier">l</phrase><phrase role="special">.</phrase><phrase
role="identifier">swap</phrase><phrase role="special">(</phrase> <phrase
role="identifier">r</phrase><phrase role="special">)</phrase></code>.
</para>
</listitem>
</varlistentry>
</variablelist>
<para>
<bridgehead renderas="sect4" id="use_scheduling_algorithm_bridgehead">
<phrase id="use_scheduling_algorithm"/>
<link linkend="use_scheduling_algorithm">Non-member
function <code>use_scheduling_algorithm()</code></link>
</bridgehead>
</para>
<programlisting><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">SchedAlgo</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="special">...</phrase> <phrase role="identifier">Args</phrase> <phrase role="special">&gt;</phrase>
<phrase role="keyword">void</phrase> <phrase role="identifier">use_scheduling_algorithm</phrase><phrase role="special">(</phrase> <phrase role="identifier">Args</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="special">...</phrase> <phrase role="identifier">args</phrase><phrase role="special">);</phrase>
</programlisting>
<variablelist>
<title></title>
<varlistentry>
<term>Effects:</term>
<listitem>
<para>
Directs <emphasis role="bold">Boost.Fiber</emphasis> to use <code><phrase
role="identifier">SchedAlgo</phrase></code>, which must be a concrete
subclass of <link linkend="class_sched_algorithm"> <code>sched_algorithm</code></link>, as the scheduling
algorithm for all fibers in the current thread. Pass any required
<code><phrase role="identifier">SchedAlgo</phrase></code> constructor
arguments as <code><phrase role="identifier">args</phrase></code>.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Note:</term>
<listitem>
<para>
If you want a given thread to use a non-default scheduling algorithm,
make that thread call <code><phrase role="identifier">use_scheduling_algorithm</phrase><phrase
role="special">()</phrase></code> before any other <emphasis role="bold">Boost.Fiber</emphasis>
entry point. If no scheduler has been set for the current thread by
the time <emphasis role="bold">Boost.Fiber</emphasis> needs to use
it, the library will create a default <link linkend="class_round_robin"> <code>round_robin</code></link> instance
for this thread.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Throws:</term>
<listitem>
<para>
Nothing
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>See also:</term>
<listitem>
<para>
<link linkend="scheduling">Scheduling</link>, <link linkend="custom">Customization</link>
</para>
</listitem>
</varlistentry>
</variablelist>
<para>
<bridgehead renderas="sect4" id="ready_fibers_bridgehead">
<phrase id="ready_fibers"/>
<link linkend="ready_fibers">Non-member function <code>ready_fibers()</code></link>
</bridgehead>
</para>
<programlisting><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">ready_fibers</phrase><phrase role="special">();</phrase>
</programlisting>
<variablelist>
<title></title>
<varlistentry>
<term>Returns:</term>
<listitem>
<para>
the number of fibers ready to run.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Throws:</term>
<listitem>
<para>
Nothing
</para>
</listitem>
</varlistentry>
</variablelist>
<para>
<bridgehead renderas="sect4" id="wait_interval_bridgehead">
<phrase id="wait_interval"/>
<link linkend="wait_interval">Non-member function <code>wait_interval()</code></link>
</bridgehead>
</para>
<programlisting><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Rep</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Period</phrase> <phrase role="special">&gt;</phrase>
<phrase role="keyword">void</phrase> <phrase role="identifier">wait_interval</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">duration</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Rep</phrase><phrase role="special">,</phrase> <phrase role="identifier">Period</phrase> <phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">wait_interval</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
<phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Rep</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Period</phrase> <phrase role="special">&gt;</phrase>
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">duration</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Rep</phrase><phrase role="special">,</phrase> <phrase role="identifier">Period</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">wait_interval</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
</programlisting>
<variablelist>
<title></title>
<varlistentry>
<term>Returns:</term>
<listitem>
<para>
Sets/returns the wait interval used to suspend the thread if no fibers
are ready to run.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Throws:</term>
<listitem>
<para>
Nothing
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Notes:</term>
<listitem>
<para>
This setting can be used to adjust the &quot;niceness&quot; of an idle
thread: a thread whose fibers are all currently blocked for various
reasons. The default for each thread, if not specified, is <code><phrase
role="identifier">std</phrase><phrase role="special">::</phrase><phrase
role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase
role="identifier">milliseconds</phrase><phrase role="special">(</phrase><phrase
role="number">10</phrase><phrase role="special">)</phrase></code>.
A longer <code><phrase role="identifier">wait_interval</phrase><phrase
role="special">()</phrase></code> causes an idle thread to use less
CPU. A shorter <code><phrase role="identifier">wait_interval</phrase><phrase
role="special">()</phrase></code> is more responsive to fibers becoming
ready. When a fiber becomes ready to resume, e.g. a mutex on which
it is blocked becomes available, control is not immediately passed
to that fiber; instead it is marked &quot;ready to run.&quot; It won't
actually resume until the fiber manager wakes up to consult the scheduler.
It could take as long as <code><phrase role="identifier">wait_interval</phrase><phrase
role="special">()</phrase></code> before the fiber manager notices
the fiber's readiness. It is likely that the optimal setting for <code><phrase
role="identifier">wait_interval</phrase><phrase role="special">()</phrase></code>
is application-specific.
</para>
</listitem>
</varlistentry>
</variablelist>
</section>
<section id="fiber.fiber_mgmt.id">
<title><anchor id="class_id"/><link linkend="fiber.fiber_mgmt.id">Class fiber::id</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">fiber</phrase><phrase role="special">/</phrase><phrase role="identifier">fiber</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase>
<phrase role="keyword">class</phrase> <phrase role="identifier">id</phrase> <phrase role="special">{</phrase>
<phrase role="keyword">public</phrase><phrase role="special">:</phrase>
<phrase role="identifier">id</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
<phrase role="keyword">bool</phrase> <phrase role="keyword">operator</phrase><phrase role="special">==(</phrase> <phrase role="identifier">id</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
<phrase role="keyword">bool</phrase> <phrase role="keyword">operator</phrase><phrase role="special">!=(</phrase> <phrase role="identifier">id</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
<phrase role="keyword">bool</phrase> <phrase role="keyword">operator</phrase><phrase role="special">&lt;(</phrase> <phrase role="identifier">id</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
<phrase role="keyword">bool</phrase> <phrase role="keyword">operator</phrase><phrase role="special">&gt;(</phrase> <phrase role="identifier">id</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
<phrase role="keyword">bool</phrase> <phrase role="keyword">operator</phrase><phrase role="special">&lt;=(</phrase> <phrase role="identifier">id</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
<phrase role="keyword">bool</phrase> <phrase role="keyword">operator</phrase><phrase role="special">&gt;=(</phrase> <phrase role="identifier">id</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
<phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">charT</phrase><phrase role="special">,</phrase> <phrase role="keyword">class</phrase> <phrase role="identifier">traitsT</phrase> <phrase role="special">&gt;</phrase>
<phrase role="keyword">friend</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">basic_ostream</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">charT</phrase><phrase role="special">,</phrase> <phrase role="identifier">traitsT</phrase> <phrase role="special">&gt;</phrase> <phrase role="special">&amp;</phrase>
<phrase role="keyword">operator</phrase><phrase role="special">&lt;&lt;(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">basic_ostream</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">charT</phrase><phrase role="special">,</phrase> <phrase role="identifier">traitsT</phrase> <phrase role="special">&gt;</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">os</phrase><phrase role="special">,</phrase> <phrase role="identifier">id</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">other</phrase><phrase role="special">);</phrase>
<phrase role="special">};</phrase>
</programlisting>
<bridgehead renderas="sect4" id="fiber.fiber_mgmt.id.h0">
<phrase id="fiber.fiber_mgmt.id.constructor"/><link linkend="fiber.fiber_mgmt.id.constructor">Constructor</link>
</bridgehead>
<programlisting><phrase role="identifier">id</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
</programlisting>
<variablelist>
<title></title>
<varlistentry>
<term>Effects:</term>
<listitem>
<para>
Represents an instance of <emphasis>not-a-fiber</emphasis>.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Throws:</term>
<listitem>
<para>
Nothing.
</para>
</listitem>
</varlistentry>
</variablelist>
<para>
<bridgehead renderas="sect4" id="id_operator_equal_bridgehead">
<phrase id="id_operator_equal"/>
<link linkend="id_operator_equal">Member function
<code>operator==</code>()</link>
</bridgehead>
</para>
<programlisting><phrase role="keyword">bool</phrase> <phrase role="keyword">operator</phrase><phrase role="special">==(</phrase> <phrase role="identifier">id</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
</programlisting>
<variablelist>
<title></title>
<varlistentry>
<term>Returns:</term>
<listitem>
<para>
<code><phrase role="keyword">true</phrase></code> if <code><phrase
role="special">*</phrase><phrase role="keyword">this</phrase></code>
and <code><phrase role="identifier">other</phrase></code> represent
the same fiber, or both represent <emphasis>not-a-fiber</emphasis>,
<code><phrase role="keyword">false</phrase></code> otherwise.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Throws:</term>
<listitem>
<para>
Nothing.
</para>
</listitem>
</varlistentry>
</variablelist>
<para>
<bridgehead renderas="sect4" id="id_operator_not_equal_bridgehead">
<phrase id="id_operator_not_equal"/>
<link linkend="id_operator_not_equal">Member
function <code>operator!=</code>()</link>
</bridgehead>
</para>
<programlisting><phrase role="keyword">bool</phrase> <phrase role="keyword">operator</phrase><phrase role="special">!=(</phrase> <phrase role="identifier">id</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
</programlisting>
<variablelist>
<title></title>
<varlistentry>
<term>Returns:</term>
<listitem>
<para>
<code>! (other == * this)</code>
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Throws:</term>
<listitem>
<para>
Nothing.
</para>
</listitem>
</varlistentry>
</variablelist>
<para>
<bridgehead renderas="sect4" id="id_operator_less_bridgehead">
<phrase id="id_operator_less"/>
<link linkend="id_operator_less">Member function
<code>operator&lt;</code>()</link>
</bridgehead>
</para>
<programlisting><phrase role="keyword">bool</phrase> <phrase role="keyword">operator</phrase><phrase role="special">&lt;(</phrase> <phrase role="identifier">id</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
</programlisting>
<variablelist>
<title></title>
<varlistentry>
<term>Returns:</term>
<listitem>
<para>
<code><phrase role="keyword">true</phrase></code> if <code><phrase
role="special">*</phrase><phrase role="keyword">this</phrase> <phrase
role="special">!=</phrase> <phrase role="identifier">other</phrase></code>
is true and the implementation-defined total order of <code><phrase
role="identifier">fiber</phrase><phrase role="special">::</phrase><phrase
role="identifier">id</phrase></code> values places <code><phrase role="special">*</phrase><phrase
role="keyword">this</phrase></code> before <code><phrase role="identifier">other</phrase></code>,
false otherwise.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Throws:</term>
<listitem>
<para>
Nothing.
</para>
</listitem>
</varlistentry>
</variablelist>
<para>
<bridgehead renderas="sect4" id="id_operator_greater_bridgehead">
<phrase id="id_operator_greater"/>
<link linkend="id_operator_greater">Member
function <code>operator&gt;</code>()</link>
</bridgehead>
</para>
<programlisting><phrase role="keyword">bool</phrase> <phrase role="keyword">operator</phrase><phrase role="special">&gt;(</phrase> <phrase role="identifier">id</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
</programlisting>
<variablelist>
<title></title>
<varlistentry>
<term>Returns:</term>
<listitem>
<para>
<code><phrase role="identifier">other</phrase> <phrase role="special">&lt;</phrase>
<phrase role="special">*</phrase> <phrase role="keyword">this</phrase></code>
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Throws:</term>
<listitem>
<para>
Nothing.
</para>
</listitem>
</varlistentry>
</variablelist>
<para>
<bridgehead renderas="sect4" id="id_operator_less_equal_bridgehead">
<phrase id="id_operator_less_equal"/>
<link linkend="id_operator_less_equal">Member
function <code>operator&lt;=</code>()</link>
</bridgehead>
</para>
<programlisting><phrase role="keyword">bool</phrase> <phrase role="keyword">operator</phrase><phrase role="special">&lt;=(</phrase> <phrase role="identifier">id</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
</programlisting>
<variablelist>
<title></title>
<varlistentry>
<term>Returns:</term>
<listitem>
<para>
<code><phrase role="special">!</phrase> <phrase role="special">(</phrase><phrase
role="identifier">other</phrase> <phrase role="special">&lt;</phrase>
<phrase role="special">*</phrase> <phrase role="keyword">this</phrase><phrase
role="special">)</phrase></code>
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Throws:</term>
<listitem>
<para>
Nothing.
</para>
</listitem>
</varlistentry>
</variablelist>
<para>
<bridgehead renderas="sect4" id="id_operator_greater_equal_bridgehead">
<phrase id="id_operator_greater_equal"/>
<link linkend="id_operator_greater_equal">Member
function <code>operator&gt;=</code>()</link>
</bridgehead>
</para>
<programlisting><phrase role="keyword">bool</phrase> <phrase role="keyword">operator</phrase><phrase role="special">&gt;=(</phrase> <phrase role="identifier">id</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
</programlisting>
<variablelist>
<title></title>
<varlistentry>
<term>Returns:</term>
<listitem>
<para>
<code><phrase role="special">!</phrase> <phrase role="special">(*</phrase>
<phrase role="keyword">this</phrase> <phrase role="special">&lt;</phrase>
<phrase role="identifier">other</phrase><phrase role="special">)</phrase></code>
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Throws:</term>
<listitem>
<para>
Nothing.
</para>
</listitem>
</varlistentry>
</variablelist>
<bridgehead renderas="sect4" id="fiber.fiber_mgmt.id.h1">
<phrase id="fiber.fiber_mgmt.id.operator_lt__lt_"/><link linkend="fiber.fiber_mgmt.id.operator_lt__lt_">operator&lt;&lt;</link>
</bridgehead>
<programlisting><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">charT</phrase><phrase role="special">,</phrase> <phrase role="keyword">class</phrase> <phrase role="identifier">traitsT</phrase> <phrase role="special">&gt;</phrase>
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">basic_ostream</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">charT</phrase><phrase role="special">,</phrase> <phrase role="identifier">traitsT</phrase> <phrase role="special">&gt;</phrase> <phrase role="special">&amp;</phrase>
<phrase role="keyword">operator</phrase><phrase role="special">&lt;&lt;(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">basic_ostream</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">charT</phrase><phrase role="special">,</phrase> <phrase role="identifier">traitsT</phrase> <phrase role="special">&gt;</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">os</phrase><phrase role="special">,</phrase> <phrase role="identifier">id</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">other</phrase><phrase role="special">);</phrase>
</programlisting>
<variablelist>
<title></title>
<varlistentry>
<term>Efects:</term>
<listitem>
<para>
Writes the representation of <code><phrase role="identifier">other</phrase></code>
to stream <code><phrase role="identifier">os</phrase></code>.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Returns:</term>
<listitem>
<para>
<code><phrase role="identifier">os</phrase></code>
</para>
</listitem>
</varlistentry>
</variablelist>
</section>
<section id="fiber.fiber_mgmt.this_fiber">
<title><link linkend="fiber.fiber_mgmt.this_fiber">Namespace this_fiber</link></title>
<programlisting><phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase>
<phrase role="keyword">namespace</phrase> <phrase role="identifier">this_fiber</phrase> <phrase role="special">{</phrase>
<phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">fiber</phrase><phrase role="special">::</phrase><phrase role="identifier">id</phrase> <phrase role="identifier">get_id</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
<phrase role="keyword">void</phrase> <phrase role="identifier">yield</phrase><phrase role="special">();</phrase>
<phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Clock</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Duration</phrase> <phrase role="special">&gt;</phrase>
<phrase role="keyword">void</phrase> <phrase role="identifier">sleep_until</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">time_point</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Clock</phrase><phrase role="special">,</phrase> <phrase role="identifier">Duration</phrase> <phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">abs_time</phrase><phrase role="special">)</phrase>
<phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Rep</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Period</phrase> <phrase role="special">&gt;</phrase>
<phrase role="keyword">void</phrase> <phrase role="identifier">sleep_for</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">duration</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Rep</phrase><phrase role="special">,</phrase> <phrase role="identifier">Period</phrase> <phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">timeout_duration</phrase><phrase role="special">);</phrase>
<phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">PROPS</phrase> <phrase role="special">&gt;</phrase>
<phrase role="identifier">PROPS</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">properties</phrase><phrase role="special">();</phrase>
<phrase role="keyword">void</phrase> <phrase role="identifier">interruption_point</phrase><phrase role="special">();</phrase>
<phrase role="keyword">bool</phrase> <phrase role="identifier">interruption_requested</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
<phrase role="keyword">bool</phrase> <phrase role="identifier">interruption_enabled</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
<phrase role="keyword">class</phrase> <phrase role="identifier">disable_interruption</phrase><phrase role="special">;</phrase>
<phrase role="keyword">class</phrase> <phrase role="identifier">restore_interruption</phrase><phrase role="special">;</phrase>
<phrase role="special">}}</phrase>
</programlisting>
<para>
<bridgehead renderas="sect4" id="this_fiber_get_id_bridgehead">
<phrase id="this_fiber_get_id"/>
<link linkend="this_fiber_get_id">Non-member
function <code>this_fiber::get_id()</code></link>
</bridgehead>
</para>
<programlisting><phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">fiber</phrase><phrase role="special">/</phrase><phrase role="identifier">operations</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase>
<phrase role="identifier">fiber</phrase><phrase role="special">::</phrase><phrase role="identifier">id</phrase> <phrase role="identifier">get_id</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
</programlisting>
<variablelist>
<title></title>
<varlistentry>
<term>Returns:</term>
<listitem>
<para>
An instance of <link linkend="class_fiber_id"><code><phrase role="identifier">fiber</phrase><phrase
role="special">::</phrase><phrase role="identifier">id</phrase></code></link> that
represents the currently executing fiber.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Throws:</term>
<listitem>
<para>
Nothing.
</para>
</listitem>
</varlistentry>
</variablelist>
<para>
<bridgehead renderas="sect4" id="this_fiber_sleep_until_bridgehead">
<phrase id="this_fiber_sleep_until"/>
<link linkend="this_fiber_sleep_until">Non-member
function <code>this_fiber::sleep_until()</code></link>
</bridgehead>
</para>
<programlisting><phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">fiber</phrase><phrase role="special">/</phrase><phrase role="identifier">operations</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase>
<phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Clock</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Duration</phrase> <phrase role="special">&gt;</phrase>
<phrase role="keyword">void</phrase> <phrase role="identifier">sleep_until</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">time_point</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Clock</phrase><phrase role="special">,</phrase> <phrase role="identifier">Duration</phrase> <phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">abs_time</phrase><phrase role="special">)</phrase>
</programlisting>
<variablelist>
<title></title>
<varlistentry>
<term>Effects:</term>
<listitem>
<para>
Suspends the current fiber until the time point specified by <code><phrase
role="identifier">abs_time</phrase></code> has been reached.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Throws:</term>
<listitem>
<para>
<code><phrase role="identifier">fiber_interrupted</phrase></code> if
the current fiber is interrupted.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Note:</term>
<listitem>
<para>
<code><phrase role="identifier">sleep_until</phrase><phrase role="special">()</phrase></code>
is one of the predefined <link linkend="interruption"><emphasis>interruption-points</emphasis></link>.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Note:</term>
<listitem>
<para>
The current fiber will not resume before <code><phrase role="identifier">abs_time</phrase></code>,
but there are no guarantees about how soon after <code><phrase role="identifier">abs_time</phrase></code>
it might resume.
</para>
</listitem>
</varlistentry>
</variablelist>
<para>
<bridgehead renderas="sect4" id="this_fiber_sleep_for_bridgehead">
<phrase id="this_fiber_sleep_for"/>
<link linkend="this_fiber_sleep_for">Non-member
function <code>this_fiber::sleep_for()</code></link>
</bridgehead>
</para>
<programlisting><phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">fiber</phrase><phrase role="special">/</phrase><phrase role="identifier">operations</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase>
<phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">class</phrase> <phrase role="identifier">Rep</phrase><phrase role="special">,</phrase> <phrase role="keyword">class</phrase> <phrase role="identifier">Period</phrase> <phrase role="special">&gt;</phrase>
<phrase role="keyword">void</phrase> <phrase role="identifier">sleep_for</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">duration</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Rep</phrase><phrase role="special">,</phrase> <phrase role="identifier">Period</phrase> <phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">rel_time</phrase><phrase role="special">);</phrase>
</programlisting>
<variablelist>
<title></title>
<varlistentry>
<term>Effects:</term>
<listitem>
<para>
Suspends the current fiber until the time duration specified by <code><phrase
role="identifier">rel_time</phrase></code> has elapsed.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Throws:</term>
<listitem>
<para>
Any exceptions thrown by operations of <code><phrase role="identifier">std</phrase><phrase
role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase
role="special">::</phrase><phrase role="identifier">duration</phrase><phrase
role="special">&lt;</phrase><phrase role="identifier">Rep</phrase><phrase
role="special">,</phrase> <phrase role="identifier">Period</phrase><phrase
role="special">&gt;</phrase></code>. <code><phrase role="identifier">fiber_interrupted</phrase></code>
if the current fiber is interrupted.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Note:</term>
<listitem>
<para>
<code><phrase role="identifier">sleep_for</phrase><phrase role="special">()</phrase></code>
is one of the predefined <link linkend="interruption"><emphasis>interruption-points</emphasis></link>.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Note:</term>
<listitem>
<para>
The current fiber will not resume before <code><phrase role="identifier">rel_time</phrase></code>
has elapsed, but there are no guarantees about how soon after that
it might resume.
</para>
</listitem>
</varlistentry>
</variablelist>
<para>
<bridgehead renderas="sect4" id="this_fiber_yield_bridgehead">
<phrase id="this_fiber_yield"/>
<link linkend="this_fiber_yield">Non-member function
<code>this_fiber::yield()</code></link>
</bridgehead>
</para>
<programlisting><phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">fiber</phrase><phrase role="special">/</phrase><phrase role="identifier">operations</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase>
<phrase role="keyword">void</phrase> <phrase role="identifier">yield</phrase><phrase role="special">();</phrase>
</programlisting>
<variablelist>
<title></title>
<varlistentry>
<term>Effects:</term>
<listitem>
<para>
Reliquishes execution control, allowing other fibers to run.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Throws:</term>
<listitem>
<para>
<code><phrase role="identifier">fiber_resource_error</phrase></code>
if an error occurs.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Note:</term>
<listitem>
<para>
<code><phrase role="identifier">yield</phrase><phrase role="special">()</phrase></code>
is <emphasis>not</emphasis> an interruption point. A fiber that calls
<code><phrase role="identifier">yield</phrase><phrase role="special">()</phrase></code>
is not suspended: it is immediately passed to the scheduler as ready
to run.
</para>
</listitem>
</varlistentry>
</variablelist>
<para>
<bridgehead renderas="sect4" id="this_fiber_properties_bridgehead">
<phrase id="this_fiber_properties"/>
<link linkend="this_fiber_properties">Non-member
function <code>this_fiber::properties()</code></link>
</bridgehead>
</para>
<programlisting><phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">fiber</phrase><phrase role="special">/</phrase><phrase role="identifier">operations</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase>
<phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">PROPS</phrase> <phrase role="special">&gt;</phrase>
<phrase role="identifier">PROPS</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">properties</phrase><phrase role="special">();</phrase>
</programlisting>
<variablelist>
<title></title>
<varlistentry>
<term>Preconditions:</term>
<listitem>
<para>
<link linkend="use_scheduling_algorithm"> <code>use_scheduling_algorithm()</code></link> has been called from
this thread with a subclass of <link linkend="class_sched_algorithm_with_properties"> <code>sched_algorithm_with_properties&lt;&gt;</code></link> with
the same template argument <code><phrase role="identifier">PROPS</phrase></code>.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Returns:</term>
<listitem>
<para>
a reference to the scheduler properties instance for the currently
running fiber.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Throws:</term>
<listitem>
<para>
<code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase
role="identifier">bad_cast</phrase></code> if <code><phrase role="identifier">use_scheduling_algorithm</phrase><phrase
role="special">()</phrase></code> was called with a <code><phrase role="identifier">sched_algorithm_with_properties</phrase></code>
subclass with some other template parameter than <code><phrase role="identifier">PROPS</phrase></code>.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Note:</term>
<listitem>
<para>
<link linkend="class_sched_algorithm_with_properties"> <code>sched_algorithm_with_properties&lt;&gt;</code></link> provides
a way for a user-coded scheduler to associate extended properties,
such as priority, with a fiber instance. This function allows access
to those user-provided properties.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Note:</term>
<listitem>
<para>
The first time this function is called from the main fiber of a thread,
it may internally yield, permitting other fibers to run.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>See also:</term>
<listitem>
<para>
<link linkend="custom">Customization</link>
</para>
</listitem>
</varlistentry>
</variablelist>
<para>
<bridgehead renderas="sect4" id="this_fiber_interruption_point_bridgehead">
<phrase id="this_fiber_interruption_point"/>
<link linkend="this_fiber_interruption_point">Non-member
function <code>this_fiber::interruption_point()</code></link>
</bridgehead>
</para>
<programlisting><phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">fiber</phrase><phrase role="special">/</phrase><phrase role="identifier">interruption</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase>
<phrase role="keyword">void</phrase> <phrase role="identifier">interruption_point</phrase><phrase role="special">();</phrase>
</programlisting>
<variablelist>
<title></title>
<varlistentry>
<term>Effects:</term>
<listitem>
<para>
Check to see if the current fiber has been interrupted.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Throws:</term>
<listitem>
<para>
<code><phrase role="identifier">fiber_interrupted</phrase></code> if
<link linkend="this_fiber_interruption_enabled"> <code>this_fiber::interruption_enabled()</code></link> and
<link linkend="this_fiber_interruption_requested"> <code>this_fiber::interruption_requested()</code></link> both
return <code><phrase role="keyword">true</phrase></code>.
</para>
</listitem>
</varlistentry>
</variablelist>
<para>
<bridgehead renderas="sect4" id="this_fiber_interruption_requested_bridgehead">
<phrase id="this_fiber_interruption_requested"/>
<link linkend="this_fiber_interruption_requested">Non-member
function <code>this_fiber::interruption_requested()</code></link>
</bridgehead>
</para>
<programlisting><phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">fiber</phrase><phrase role="special">/</phrase><phrase role="identifier">interruption</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase>
<phrase role="keyword">bool</phrase> <phrase role="identifier">interruption_requested</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
</programlisting>
<variablelist>
<title></title>
<varlistentry>
<term>Returns:</term>
<listitem>
<para>
<code><phrase role="keyword">true</phrase></code> if interruption has
been requested for the current fiber, <code><phrase role="keyword">false</phrase></code>
otherwise.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Throws:</term>
<listitem>
<para>
Nothing.
</para>
</listitem>
</varlistentry>
</variablelist>
<para>
<bridgehead renderas="sect4" id="this_fiber_interruption_enabled_bridgehead">
<phrase id="this_fiber_interruption_enabled"/>
<link linkend="this_fiber_interruption_enabled">Non-member
function <code>this_fiber::interruption_enabled()</code></link>
</bridgehead>
</para>
<programlisting><phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">fiber</phrase><phrase role="special">/</phrase><phrase role="identifier">interruption</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase>
<phrase role="keyword">bool</phrase> <phrase role="identifier">interruption_enabled</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
</programlisting>
<variablelist>
<title></title>
<varlistentry>
<term>Returns:</term>
<listitem>
<para>
<code><phrase role="keyword">true</phrase></code> if interruption is
enabled for the current fiber, <code><phrase role="keyword">false</phrase></code>
otherwise.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Throws:</term>
<listitem>
<para>
Nothing.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Note:</term>
<listitem>
<para>
Interruption is enabled by default.
</para>
</listitem>
</varlistentry>
</variablelist>
<para>
<bridgehead renderas="sect4" id="class_disable_interruption_bridgehead">
<phrase id="class_disable_interruption"/>
<link linkend="class_disable_interruption">Class
<code>disable_interruption</code></link>
</bridgehead>
</para>
<programlisting><phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">fiber</phrase><phrase role="special">/</phrase><phrase role="identifier">interruption</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase>
<phrase role="keyword">class</phrase> <phrase role="identifier">disable_interruption</phrase> <phrase role="special">{</phrase>
<phrase role="keyword">public</phrase><phrase role="special">:</phrase>
<phrase role="identifier">disable_interruption</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
<phrase role="special">~</phrase><phrase role="identifier">disable_interruption</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
<phrase role="identifier">disable_interruption</phrase><phrase role="special">(</phrase><phrase role="keyword">const</phrase> <phrase role="identifier">disable_interruption</phrase><phrase role="special">&amp;)</phrase> <phrase role="special">=</phrase> <phrase role="keyword">delete</phrase><phrase role="special">;</phrase>
<phrase role="identifier">disable_interruption</phrase><phrase role="special">&amp;</phrase> <phrase role="keyword">operator</phrase><phrase role="special">=(</phrase><phrase role="keyword">const</phrase> <phrase role="identifier">disable_interruption</phrase><phrase role="special">&amp;)</phrase> <phrase role="special">=</phrase> <phrase role="keyword">delete</phrase><phrase role="special">;</phrase>
<phrase role="special">};</phrase>
</programlisting>
<bridgehead renderas="sect4" id="fiber.fiber_mgmt.this_fiber.h0">
<phrase id="fiber.fiber_mgmt.this_fiber.constructor"/><link linkend="fiber.fiber_mgmt.this_fiber.constructor">Constructor</link>
</bridgehead>
<programlisting><phrase role="identifier">disable_interruption</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
</programlisting>
<variablelist>
<title></title>
<varlistentry>
<term>Effects:</term>
<listitem>
<para>
Stores the current state of <link linkend="this_fiber_interruption_enabled"> <code>this_fiber::interruption_enabled()</code></link> and
disables interruption for the current fiber.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Postconditions:</term>
<listitem>
<para>
<link linkend="this_fiber_interruption_enabled"> <code>this_fiber::interruption_enabled()</code></link> returns
<code><phrase role="keyword">false</phrase></code> for the current
fiber.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Throws:</term>
<listitem>
<para>
Nothing.
</para>
</listitem>
</varlistentry>
</variablelist>
<bridgehead renderas="sect4" id="fiber.fiber_mgmt.this_fiber.h1">
<phrase id="fiber.fiber_mgmt.this_fiber.destructor"/><link linkend="fiber.fiber_mgmt.this_fiber.destructor">Destructor</link>
</bridgehead>
<programlisting><phrase role="special">~</phrase><phrase role="identifier">disable_interruption</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
</programlisting>
<variablelist>
<title></title>
<varlistentry>
<term>Preconditions:</term>
<listitem>
<para>
Must be called from the same fiber on which <code><phrase role="special">*</phrase><phrase
role="keyword">this</phrase></code> was constructed.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Effects:</term>
<listitem>
<para>
Restores the state of <link linkend="this_fiber_interruption_enabled"> <code>this_fiber::interruption_enabled()</code></link> for
the current fiber to the state saved at construction of <code><phrase
role="special">*</phrase><phrase role="keyword">this</phrase></code>.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Postconditions:</term>
<listitem>
<para>
<link linkend="this_fiber_interruption_enabled"> <code>this_fiber::interruption_enabled()</code></link> for
the current fiber returns the value stored by 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>
<para>
<bridgehead renderas="sect4" id="class_restore_interruption_bridgehead">
<phrase id="class_restore_interruption"/>
<link linkend="class_restore_interruption">Class
<code>restore_interruption</code></link>
</bridgehead>
</para>
<programlisting><phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">fiber</phrase><phrase role="special">/</phrase><phrase role="identifier">interruption</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase>
<phrase role="keyword">class</phrase> <phrase role="identifier">restore_interruption</phrase> <phrase role="special">{</phrase>
<phrase role="keyword">public</phrase><phrase role="special">:</phrase>
<phrase role="keyword">explicit</phrase> <phrase role="identifier">restore_interruption</phrase><phrase role="special">(</phrase><phrase role="identifier">disable_interruption</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">disabler</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
<phrase role="special">~</phrase><phrase role="identifier">restore_interruption</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
<phrase role="identifier">restore_interruption</phrase><phrase role="special">(</phrase><phrase role="keyword">const</phrase> <phrase role="identifier">restore_interruption</phrase><phrase role="special">&amp;)</phrase> <phrase role="special">=</phrase> <phrase role="keyword">delete</phrase><phrase role="special">;</phrase>
<phrase role="identifier">restore_interruption</phrase><phrase role="special">&amp;</phrase> <phrase role="keyword">operator</phrase><phrase role="special">=(</phrase><phrase role="keyword">const</phrase> <phrase role="identifier">restore_interruption</phrase><phrase role="special">&amp;)</phrase> <phrase role="special">=</phrase> <phrase role="keyword">delete</phrase><phrase role="special">;</phrase>
<phrase role="special">};</phrase>
</programlisting>
<bridgehead renderas="sect4" id="fiber.fiber_mgmt.this_fiber.h2">
<phrase id="fiber.fiber_mgmt.this_fiber.constructor0"/><link linkend="fiber.fiber_mgmt.this_fiber.constructor0">Constructor</link>
</bridgehead>
<programlisting><phrase role="keyword">explicit</phrase> <phrase role="identifier">restore_interruption</phrase><phrase role="special">(</phrase><phrase role="identifier">disable_interruption</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">disabler</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
</programlisting>
<variablelist>
<title></title>
<varlistentry>
<term>Preconditions:</term>
<listitem>
<para>
Must be called from the same fiber on which <code><phrase role="identifier">disabler</phrase></code>
was constructed.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Effects:</term>
<listitem>
<para>
Restores the current state of <link linkend="this_fiber_interruption_enabled"> <code>this_fiber::interruption_enabled()</code></link> for
the current fiber to that saved in <code><phrase role="identifier">disabler</phrase></code>.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Postconditions:</term>
<listitem>
<para>
<link linkend="this_fiber_interruption_enabled"> <code>this_fiber::interruption_enabled()</code></link> for
the current fiber returns the value stored in the constructor of <code><phrase
role="identifier">disabler</phrase></code>.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Throws:</term>
<listitem>
<para>
Nothing.
</para>
</listitem>
</varlistentry>
</variablelist>
<bridgehead renderas="sect4" id="fiber.fiber_mgmt.this_fiber.h3">
<phrase id="fiber.fiber_mgmt.this_fiber.destructor0"/><link linkend="fiber.fiber_mgmt.this_fiber.destructor0">Destructor</link>
</bridgehead>
<programlisting><phrase role="special">~</phrase><phrase role="identifier">restore_interruption</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
</programlisting>
<variablelist>
<title></title>
<varlistentry>
<term>Preconditions:</term>
<listitem>
<para>
Must be called from the same fiber on which <code><phrase role="special">*</phrase><phrase
role="keyword">this</phrase></code> was constructed.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Effects:</term>
<listitem>
<para>
Disables interruption for the current fiber.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Postconditions:</term>
<listitem>
<para>
<link linkend="this_fiber_interruption_enabled"> <code>this_fiber::interruption_enabled()</code></link> for
the current fiber returns <code><phrase role="keyword">false</phrase></code>.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Throws:</term>
<listitem>
<para>
Nothing.
</para>
</listitem>
</varlistentry>
</variablelist>
<programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">foo</phrase><phrase role="special">()</phrase> <phrase role="special">{</phrase>
<phrase role="comment">// interruption is enabled</phrase>
<phrase role="special">{</phrase>
<phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">this_fiber</phrase><phrase role="special">::</phrase><phrase role="identifier">disable_interruption</phrase> <phrase role="identifier">di</phrase><phrase role="special">;</phrase>
<phrase role="comment">// interruption is disabled</phrase>
<phrase role="special">{</phrase>
<phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">this_fiber</phrase><phrase role="special">::</phrase><phrase role="identifier">restore_interruption</phrase> <phrase role="identifier">ri</phrase><phrase role="special">(</phrase> <phrase role="identifier">di</phrase><phrase role="special">);</phrase>
<phrase role="comment">// interruption now enabled</phrase>
<phrase role="special">}</phrase> <phrase role="comment">// ri destroyed, interruption disable again</phrase>
<phrase role="special">}</phrase> <phrase role="comment">// di destructed, interruption state restored</phrase>
<phrase role="comment">// interruption now enabled</phrase>
<phrase role="special">}</phrase>
</programlisting>
</section>
<section id="fiber.fiber_mgmt.winfibers">
<title><link linkend="fiber.fiber_mgmt.winfibers">Using WinFiber-API</link></title>
<para>
Because the TIB (thread information block) is not fully described in the
MSDN, it might be possible that not all required TIB-parts are swapped. With
compiler flag <code><phrase role="identifier">BOOST_USE_WINFIBERS</phrase></code>
<code><phrase role="identifier">fiber</phrase></code> uses internally the
Windows Fiber API (see also <ulink url="http://www.boost.org/doc/libs/release/libs/context/doc/html/context/econtext/winfibers.html">Boost.Context
WinFiber support</ulink>).
</para>
</section>
</section>
<section id="fiber.scheduling">
<title><anchor id="scheduling"/><link linkend="fiber.scheduling">Scheduling</link></title>
<para>
The fibers in a thread are coordinated by a fiber manager. Fibers trade control
cooperatively, rather than preemptively: the currently-running fiber retains
control until it invokes some operation that passes control to the manager.
Each time a fiber suspends (or yields), the fiber manager consults a scheduler
to determine which fiber will run next.
</para>
<para>
<emphasis role="bold">Boost.Fiber</emphasis> provides the fiber manager, but
the scheduler is a customization point. (See <link linkend="custom">Customization</link>.)
</para>
<para>
Each thread has its own scheduler. By default, <emphasis role="bold">Boost.Fiber</emphasis>
implicitly instantiates <link linkend="class_round_robin"> <code>round_robin</code></link> as the scheduler for each
thread.
</para>
<para>
You are explicitly permitted to code your own <link linkend="class_sched_algorithm"> <code>sched_algorithm</code></link> subclass,
and to specify it to <link linkend="use_scheduling_algorithm"> <code>use_scheduling_algorithm()</code></link>.
</para>
<programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">thread_fn</phrase><phrase role="special">()</phrase> <phrase role="special">{</phrase>
<phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">use_scheduling_algorithm</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">my_fiber_scheduler</phrase><phrase role="special">&gt;();</phrase>
<phrase role="special">...</phrase>
<phrase role="special">}</phrase>
</programlisting>
<para>
A scheduler class must implement interface <link linkend="class_sched_algorithm"> <code>sched_algorithm</code></link>.
<emphasis role="bold">Boost.Fiber</emphasis> provides one scheduler: <link linkend="class_round_robin"> <code>round_robin</code></link>.
</para>
<para>
<bridgehead renderas="sect4" id="class_sched_algorithm_bridgehead">
<phrase id="class_sched_algorithm"/>
<link linkend="class_sched_algorithm">Class
<code>sched_algorithm</code></link>
</bridgehead>
</para>
<para>
<code><phrase role="identifier">sched_algorithm</phrase></code> is the abstract
base class defining the interface that a fiber scheduler must implement.
</para>
<programlisting><phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">fiber</phrase><phrase role="special">/</phrase><phrase role="identifier">algorithm</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase>
<phrase role="keyword">struct</phrase> <phrase role="identifier">sched_algorithm</phrase> <phrase role="special">{</phrase>
<phrase role="keyword">virtual</phrase> <phrase role="special">~</phrase><phrase role="identifier">sched_algorithm</phrase><phrase role="special">()</phrase> <phrase role="special">{}</phrase>
<phrase role="keyword">virtual</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">awakened</phrase><phrase role="special">(</phrase> <phrase role="identifier">context</phrase> <phrase role="special">*)</phrase> <phrase role="special">=</phrase> <phrase role="number">0</phrase><phrase role="special">;</phrase>
<phrase role="keyword">virtual</phrase> <phrase role="identifier">context</phrase> <phrase role="special">*</phrase> <phrase role="identifier">pick_next</phrase><phrase role="special">()</phrase> <phrase role="special">=</phrase> <phrase role="number">0</phrase><phrase role="special">;</phrase>
<phrase role="keyword">virtual</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">ready_fibers</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase> <phrase role="special">=</phrase> <phrase role="number">0</phrase><phrase role="special">;</phrase>
<phrase role="special">};</phrase>
</programlisting>
<para>
<bridgehead renderas="sect4" id="sched_algorithm_awakened_bridgehead">
<phrase id="sched_algorithm_awakened"/>
<link linkend="sched_algorithm_awakened">Member
function <code>awakened</code>()</link>
</bridgehead>
</para>
<programlisting><phrase role="keyword">virtual</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">awakened</phrase><phrase role="special">(</phrase> <phrase role="identifier">context</phrase> <phrase role="special">*</phrase> <phrase role="identifier">f</phrase><phrase role="special">)</phrase> <phrase role="special">=</phrase> <phrase role="number">0</phrase><phrase role="special">;</phrase>
</programlisting>
<variablelist>
<title></title>
<varlistentry>
<term>Effects:</term>
<listitem>
<para>
Informs the scheduler that fiber <code><phrase role="identifier">f</phrase></code>
is ready to run. Fiber <code><phrase role="identifier">f</phrase></code>
might be newly launched, or it might have been blocked but has just been
awakened, or it might have called <link linkend="this_fiber_yield"> <code>this_fiber::yield()</code></link>.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Note:</term>
<listitem>
<para>
This method advises the scheduler to add fiber <code><phrase role="identifier">f</phrase></code>
to its collection of fibers ready to run. A typical scheduler implementation
places <code><phrase role="identifier">f</phrase></code> into a queue.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>See also:</term>
<listitem>
<para>
<link linkend="class_round_robin"> <code>round_robin</code></link>
</para>
</listitem>
</varlistentry>
</variablelist>
<para>
<bridgehead renderas="sect4" id="sched_algorithm_pick_next_bridgehead">
<phrase id="sched_algorithm_pick_next"/>
<link linkend="sched_algorithm_pick_next">Member
function <code>pick_next</code>()</link>
</bridgehead>
</para>
<programlisting><phrase role="keyword">virtual</phrase> <phrase role="identifier">context</phrase> <phrase role="special">*</phrase> <phrase role="identifier">pick_next</phrase><phrase role="special">()</phrase> <phrase role="special">=</phrase> <phrase role="number">0</phrase><phrase role="special">;</phrase>
</programlisting>
<variablelist>
<title></title>
<varlistentry>
<term>Returns:</term>
<listitem>
<para>
the fiber which is to be resumed next, or <code><phrase role="keyword">nullptr</phrase></code>
if there is no ready fiber.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Note:</term>
<listitem>
<para>
This is where the scheduler actually specifies the fiber which is to
run next. A typical scheduler implementation chooses the head of the
ready queue.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>See also:</term>
<listitem>
<para>
<link linkend="class_round_robin"> <code>round_robin</code></link>
</para>
</listitem>
</varlistentry>
</variablelist>
<para>
<bridgehead renderas="sect4" id="sched_algorithm_ready_fibers_bridgehead">
<phrase id="sched_algorithm_ready_fibers"/>
<link linkend="sched_algorithm_ready_fibers">Member
function <code>ready_fibers</code>()</link>
</bridgehead>
</para>
<programlisting><phrase role="keyword">virtual</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">ready_fibers</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase> <phrase role="special">=</phrase> <phrase role="number">0</phrase><phrase role="special">;</phrase>
</programlisting>
<variablelist>
<title></title>
<varlistentry>
<term>Returns:</term>
<listitem>
<para>
the number of fibers ready to run.
</para>
</listitem>
</varlistentry>
</variablelist>
<para>
<bridgehead renderas="sect4" id="class_round_robin_bridgehead">
<phrase id="class_round_robin"/>
<link linkend="class_round_robin">Class <code>round_robin</code></link>
</bridgehead>
</para>
<para>
This class implements <link linkend="class_sched_algorithm"> <code>sched_algorithm</code></link>, scheduling fibers
in round-robin fashion.
</para>
<programlisting><phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">fiber</phrase><phrase role="special">/</phrase><phrase role="identifier">round_robin</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase>
<phrase role="keyword">class</phrase> <phrase role="identifier">round_robin</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <phrase role="identifier">sched_algorithm</phrase> <phrase role="special">{</phrase>
<phrase role="keyword">virtual</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">awakened</phrase><phrase role="special">(</phrase> <phrase role="identifier">context</phrase> <phrase role="special">*);</phrase>
<phrase role="keyword">virtual</phrase> <phrase role="identifier">context</phrase> <phrase role="special">*</phrase> <phrase role="identifier">pick_next</phrase><phrase role="special">();</phrase>
<phrase role="keyword">virtual</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">ready_fibers</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
<phrase role="special">};</phrase>
</programlisting>
<para>
<bridgehead renderas="sect4" id="round_robin_awakened_bridgehead">
<phrase id="round_robin_awakened"/>
<link linkend="round_robin_awakened">Member
function <code>awakened</code>()</link>
</bridgehead>
</para>
<programlisting><phrase role="keyword">virtual</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">awakened</phrase><phrase role="special">(</phrase> <phrase role="identifier">context</phrase> <phrase role="special">*</phrase> <phrase role="identifier">f</phrase><phrase role="special">);</phrase>
</programlisting>
<variablelist>
<title></title>
<varlistentry>
<term>Effects:</term>
<listitem>
<para>
Enqueues fiber <code><phrase role="identifier">f</phrase></code> onto
a ready queue.
</para>
</listitem>
</varlistentry>
</variablelist>
<para>
<bridgehead renderas="sect4" id="round_robin_pick_next_bridgehead">
<phrase id="round_robin_pick_next"/>
<link linkend="round_robin_pick_next">Member
function <code>pick_next</code>()</link>
</bridgehead>
</para>
<programlisting><phrase role="keyword">virtual</phrase> <phrase role="identifier">context</phrase> <phrase role="special">*</phrase> <phrase role="identifier">pick_next</phrase><phrase role="special">();</phrase>
</programlisting>
<variablelist>
<title></title>
<varlistentry>
<term>Returns:</term>
<listitem>
<para>
the fiber at the head of the ready queue, or 0 if the queue is empty.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Note:</term>
<listitem>
<para>
Placing ready fibers onto a queue, and returning them from the head of
that queue, shares the thread between ready fibers in round-robin fashion.
</para>
</listitem>
</varlistentry>
</variablelist>
<para>
<bridgehead renderas="sect4" id="round_robin_ready_fibers_bridgehead">
<phrase id="round_robin_ready_fibers"/>
<link linkend="round_robin_ready_fibers">Member
function <code>ready_fibers</code>()</link>
</bridgehead>
</para>
<programlisting><phrase role="keyword">virtual</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">ready_fibers</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
</programlisting>
<variablelist>
<title></title>
<varlistentry>
<term>Returns:</term>
<listitem>
<para>
the number of fibers ready to run.
</para>
</listitem>
</varlistentry>
</variablelist>
<bridgehead renderas="sect3" id="fiber.scheduling.h0">
<phrase id="fiber.scheduling.custom_scheduler_fiber_properties"/><link linkend="fiber.scheduling.custom_scheduler_fiber_properties">Custom
Scheduler Fiber Properties</link>
</bridgehead>
<para>
A scheduler class directly derived from <link linkend="class_sched_algorithm"> <code>sched_algorithm</code></link> can
use any information available from <link linkend="class_context"> <code>context</code></link> to implement the <code><phrase
role="identifier">sched_algorithm</phrase></code> interface. But a custom scheduler
might need to track additional properties for a fiber. For instance, a priority-based
scheduler would need to track a fiber's priority.
</para>
<para>
<emphasis role="bold">Boost.Fiber</emphasis> provides a mechanism by which
your custom scheduler can associate custom properties with each fiber.
</para>
<para>
<bridgehead renderas="sect4" id="class_fiber_properties_bridgehead">
<phrase id="class_fiber_properties"/>
<link linkend="class_fiber_properties">Class
<code>fiber_properties</code></link>
</bridgehead>
</para>
<para>
A custom fiber properties class must be derived from <code><phrase role="identifier">fiber_properties</phrase></code>.
</para>
<programlisting><phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">fiber</phrase><phrase role="special">/</phrase><phrase role="identifier">properties</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase>
<phrase role="keyword">class</phrase> <phrase role="identifier">fiber_properties</phrase> <phrase role="special">{</phrase>
<phrase role="keyword">public</phrase><phrase role="special">:</phrase>
<phrase role="identifier">fiber_properties</phrase><phrase role="special">(</phrase> <phrase role="identifier">context</phrase><phrase role="special">*</phrase> <phrase role="identifier">f</phrase><phrase role="special">);</phrase>
<phrase role="keyword">virtual</phrase> <phrase role="special">~</phrase><phrase role="identifier">fiber_properties</phrase><phrase role="special">()</phrase> <phrase role="special">{}</phrase>
<phrase role="keyword">protected</phrase><phrase role="special">:</phrase>
<phrase role="keyword">void</phrase> <phrase role="identifier">notify</phrase><phrase role="special">();</phrase>
<phrase role="special">};</phrase>
</programlisting>
<bridgehead renderas="sect3" id="fiber.scheduling.h1">
<phrase id="fiber.scheduling.constructor"/><link linkend="fiber.scheduling.constructor">Constructor</link>
</bridgehead>
<programlisting><phrase role="identifier">fiber_properties</phrase><phrase role="special">(</phrase> <phrase role="identifier">context</phrase><phrase role="special">*</phrase> <phrase role="identifier">f</phrase><phrase role="special">);</phrase>
</programlisting>
<variablelist>
<title></title>
<varlistentry>
<term>Effects:</term>
<listitem>
<para>
Constructs base-class component of custom subclass.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Note:</term>
<listitem>
<para>
Your subclass constructor must accept a <code><phrase role="identifier">context</phrase><phrase
role="special">*</phrase></code> and pass it to the base-class <code><phrase
role="identifier">fiber_properties</phrase></code> constructor.
</para>
</listitem>
</varlistentry>
</variablelist>
<para>
<bridgehead renderas="sect4" id="fiber_properties_notify_bridgehead">
<phrase id="fiber_properties_notify"/>
<link linkend="fiber_properties_notify">Member
function <code>notify</code>()</link>
</bridgehead>
</para>
<programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">notify</phrase><phrase role="special">();</phrase>
</programlisting>
<variablelist>
<title></title>
<varlistentry>
<term>Effects:</term>
<listitem>
<para>
Pass control to the custom <link linkend="class_sched_algorithm_with_properties"> <code>sched_algorithm_with_properties&lt;&gt;</code></link> subclass's
<link linkend="sched_algorithm_with_properties_property_change"> <code>sched_algorithm_with_properties::property_change()</code></link> method.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Note:</term>
<listitem>
<para>
A custom scheduler's <link linkend="sched_algorithm_with_properties_pick_next"> <code>sched_algorithm_with_properties::pick_next()</code></link> method
might dynamically select from the ready fibers, or <link linkend="sched_algorithm_with_properties_awakened"> <code>sched_algorithm_with_properties::awakened()</code></link> might
instead insert each ready fiber into some form of ready queue for <code><phrase
role="identifier">pick_next</phrase><phrase role="special">()</phrase></code>.
In the latter case, if application code modifies a fiber property (e.g.
priority) that should affect that fiber's relationship to other ready
fibers, the custom scheduler must be given the opportunity to reorder
its ready queue. The custom property subclass should implement an access
method to modify such a property; that access method should call <code><phrase
role="identifier">notify</phrase><phrase role="special">()</phrase></code>
once the new property value has been stored. This passes control to the
custom scheduler's <code><phrase role="identifier">property_change</phrase><phrase
role="special">()</phrase></code> method, allowing the custom scheduler
to reorder its ready queue appropriately. Use at your discretion. Of
course, if you define a property which does not affect the behavior of
the <code><phrase role="identifier">pick_next</phrase><phrase role="special">()</phrase></code>
method, you need not call <code><phrase role="identifier">notify</phrase><phrase
role="special">()</phrase></code> when that property is modified.
</para>
</listitem>
</varlistentry>
</variablelist>
<para>
<bridgehead renderas="sect4" id="class_sched_algorithm_with_properties_bridgehead">
<phrase id="class_sched_algorithm_with_properties"/>
<link linkend="class_sched_algorithm_with_properties">Template
<code>sched_algorithm_with_properties&lt;&gt;</code></link>
</bridgehead>
</para>
<para>
A custom scheduler that depends on a custom properties class <code><phrase
role="identifier">PROPS</phrase></code> should be derived from <code><phrase
role="identifier">sched_algorithm_with_properties</phrase><phrase role="special">&lt;</phrase><phrase
role="identifier">PROPS</phrase><phrase role="special">&gt;</phrase></code>.
<code><phrase role="identifier">PROPS</phrase></code> should be derived from
<link linkend="class_fiber_properties"> <code>fiber_properties</code></link>.
</para>
<programlisting><phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">fiber</phrase><phrase role="special">/</phrase><phrase role="identifier">algorithm</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase>
<phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">PROPS</phrase> <phrase role="special">&gt;</phrase>
<phrase role="keyword">struct</phrase> <phrase role="identifier">sched_algorithm_with_properties</phrase> <phrase role="special">{</phrase>
<phrase role="comment">// override this method instead of sched_algorithm::awakened()</phrase>
<phrase role="keyword">virtual</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">awakened</phrase><phrase role="special">(</phrase> <phrase role="identifier">context</phrase> <phrase role="special">*</phrase> <phrase role="identifier">f</phrase><phrase role="special">,</phrase> <phrase role="identifier">PROPS</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">properties</phrase><phrase role="special">)</phrase> <phrase role="special">=</phrase> <phrase role="number">0</phrase><phrase role="special">;</phrase>
<phrase role="keyword">virtual</phrase> <phrase role="identifier">context</phrase> <phrase role="special">*</phrase> <phrase role="identifier">pick_next</phrase><phrase role="special">();</phrase>
<phrase role="keyword">virtual</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">ready_fibers</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
<phrase role="comment">// obtain f's associated PROPS instance</phrase>
<phrase role="identifier">PROPS</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">properties</phrase><phrase role="special">(</phrase> <phrase role="identifier">context</phrase> <phrase role="special">*</phrase> <phrase role="identifier">f</phrase><phrase role="special">);</phrase>
<phrase role="comment">// override this to be notified by PROPS::notify()</phrase>
<phrase role="keyword">virtual</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">property_change</phrase><phrase role="special">(</phrase> <phrase role="identifier">context</phrase> <phrase role="special">*</phrase> <phrase role="identifier">f</phrase><phrase role="special">,</phrase> <phrase role="identifier">PROPS</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">properties</phrase><phrase role="special">);</phrase>
<phrase role="comment">// Override this to customize instantiation of PROPS, e.g. use a different</phrase>
<phrase role="comment">// allocator. Each PROPS instance is associated with a particular</phrase>
<phrase role="comment">// context.</phrase>
<phrase role="keyword">virtual</phrase> <phrase role="identifier">fiber_properties</phrase> <phrase role="special">*</phrase> <phrase role="identifier">new_properties</phrase><phrase role="special">(</phrase> <phrase role="identifier">context</phrase> <phrase role="special">*</phrase> <phrase role="identifier">f</phrase><phrase role="special">);</phrase>
<phrase role="special">};</phrase>
</programlisting>
<para>
<bridgehead renderas="sect4" id="sched_algorithm_with_properties_awakened_bridgehead">
<phrase id="sched_algorithm_with_properties_awakened"/>
<link linkend="sched_algorithm_with_properties_awakened">Member
function <code>awakened</code>()</link>
</bridgehead>
</para>
<programlisting><phrase role="keyword">virtual</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">awakened</phrase><phrase role="special">(</phrase> <phrase role="identifier">context</phrase> <phrase role="special">*</phrase> <phrase role="identifier">f</phrase><phrase role="special">,</phrase> <phrase role="identifier">PROPS</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">properties</phrase><phrase role="special">);</phrase>
</programlisting>
<variablelist>
<title></title>
<varlistentry>
<term>Effects:</term>
<listitem>
<para>
Informs the scheduler that fiber <code><phrase role="identifier">f</phrase></code>
is ready to run, like <link linkend="sched_algorithm_awakened"> <code>sched_algorithm::awakened()</code></link>.
Passes the fiber's associated <code><phrase role="identifier">PROPS</phrase></code>
instance.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Note:</term>
<listitem>
<para>
A <code><phrase role="identifier">sched_algorithm_with_properties</phrase><phrase
role="special">&lt;&gt;</phrase></code> subclass must override this method
instead of <code><phrase role="identifier">sched_algorithm</phrase><phrase
role="special">::</phrase><phrase role="identifier">awakened</phrase><phrase
role="special">()</phrase></code>.
</para>
</listitem>
</varlistentry>
</variablelist>
<para>
<bridgehead renderas="sect4" id="sched_algorithm_with_properties_pick_next_bridgehead">
<phrase id="sched_algorithm_with_properties_pick_next"/>
<link linkend="sched_algorithm_with_properties_pick_next">Member
function <code>pick_next</code>()</link>
</bridgehead>
</para>
<programlisting><phrase role="keyword">virtual</phrase> <phrase role="identifier">context</phrase> <phrase role="special">*</phrase> <phrase role="identifier">pick_next</phrase><phrase role="special">();</phrase>
</programlisting>
<variablelist>
<title></title>
<varlistentry>
<term>Returns:</term>
<listitem>
<para>
the fiber which is to be resumed next, or <code><phrase role="keyword">nullptr</phrase></code>
if there is no ready fiber.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Note:</term>
<listitem>
<para>
same as <link linkend="sched_algorithm_pick_next"> <code>sched_algorithm::pick_next()</code></link>
</para>
</listitem>
</varlistentry>
</variablelist>
<para>
<bridgehead renderas="sect4" id="sched_algorithm_with_properties_ready_fibers_bridgehead">
<phrase id="sched_algorithm_with_properties_ready_fibers"/>
<link linkend="sched_algorithm_with_properties_ready_fibers">Member
function <code>ready_fibers</code>()</link>
</bridgehead>
</para>
<programlisting><phrase role="keyword">virtual</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">ready_fibers</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
</programlisting>
<variablelist>
<title></title>
<varlistentry>
<term>Returns:</term>
<listitem>
<para>
the number of fibers ready to run.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Note:</term>
<listitem>
<para>
same as <link linkend="sched_algorithm_ready_fibers"> <code>sched_algorithm::ready_fibers()</code></link>
</para>
</listitem>
</varlistentry>
</variablelist>
<para>
<bridgehead renderas="sect4" id="sched_algorithm_with_properties_properties_bridgehead">
<phrase id="sched_algorithm_with_properties_properties"/>
<link linkend="sched_algorithm_with_properties_properties">Member
function <code>properties</code>()</link>
</bridgehead>
</para>
<programlisting><phrase role="identifier">PROPS</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">properties</phrase><phrase role="special">(</phrase> <phrase role="identifier">context</phrase> <phrase role="special">*</phrase> <phrase role="identifier">f</phrase><phrase role="special">);</phrase>
</programlisting>
<variablelist>
<title></title>
<varlistentry>
<term>Returns:</term>
<listitem>
<para>
the <code><phrase role="identifier">PROPS</phrase></code> instance associated
with fiber <code><phrase role="identifier">f</phrase></code>.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Note:</term>
<listitem>
<para>
The fiber's associated <code><phrase role="identifier">PROPS</phrase></code>
instance is already passed to <link linkend="sched_algorithm_with_properties_awakened"> <code>sched_algorithm_with_properties::awakened()</code></link> and
<link linkend="sched_algorithm_with_properties_property_change"> <code>sched_algorithm_with_properties::property_change()</code></link>.
However, every <link linkend="class_sched_algorithm"> <code>sched_algorithm</code></link> subclass is expected
to track a collection of ready <link linkend="class_context"> <code>context</code></link> instances. This method
allows your custom scheduler to retrieve the <link linkend="class_fiber_properties"> <code>fiber_properties</code></link> subclass
instance for any <code><phrase role="identifier">context</phrase></code>
in its collection.
</para>
</listitem>
</varlistentry>
</variablelist>
<para>
<bridgehead renderas="sect4" id="sched_algorithm_with_properties_property_change_bridgehead">
<phrase id="sched_algorithm_with_properties_property_change"/>
<link linkend="sched_algorithm_with_properties_property_change">Member
function <code>property_change</code>()</link>
</bridgehead>
</para>
<programlisting><phrase role="keyword">virtual</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">property_change</phrase><phrase role="special">(</phrase> <phrase role="identifier">context</phrase> <phrase role="special">*</phrase> <phrase role="identifier">f</phrase><phrase role="special">,</phrase> <phrase role="identifier">PROPS</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">properties</phrase><phrase role="special">);</phrase>
</programlisting>
<variablelist>
<title></title>
<varlistentry>
<term>Effects:</term>
<listitem>
<para>
Notify the custom scheduler of a possibly-relevant change to a property
belonging to fiber <code><phrase role="identifier">f</phrase></code>.
<code><phrase role="identifier">properties</phrase></code> contains the
new values of all relevant properties.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Note:</term>
<listitem>
<para>
This method is only called when a custom <link linkend="class_fiber_properties"> <code>fiber_properties</code></link> subclass
explicitly calls <link linkend="fiber_properties_notify"> <code>fiber_properties::notify()</code></link>.
</para>
</listitem>
</varlistentry>
</variablelist>
<para>
<bridgehead renderas="sect4" id="sched_algorithm_with_properties_new_properties_bridgehead">
<phrase id="sched_algorithm_with_properties_new_properties"/>
<link linkend="sched_algorithm_with_properties_new_properties">Member
function <code>new_properties</code>()</link>
</bridgehead>
</para>
<programlisting><phrase role="keyword">virtual</phrase> <phrase role="identifier">fiber_properties</phrase> <phrase role="special">*</phrase> <phrase role="identifier">new_properties</phrase><phrase role="special">(</phrase> <phrase role="identifier">context</phrase> <phrase role="special">*</phrase> <phrase role="identifier">f</phrase><phrase role="special">);</phrase>
</programlisting>
<variablelist>
<title></title>
<varlistentry>
<term>Returns:</term>
<listitem>
<para>
A new instance of <link linkend="class_fiber_properties"> <code>fiber_properties</code></link> subclass <code><phrase
role="identifier">PROPS</phrase></code>.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Note:</term>
<listitem>
<para>
By default, <code><phrase role="identifier">sched_algorithm_with_properties</phrase><phrase
role="special">&lt;&gt;::</phrase><phrase role="identifier">new_properties</phrase><phrase
role="special">()</phrase></code> simply returns <code><phrase role="keyword">new</phrase>
<phrase role="identifier">PROPS</phrase><phrase role="special">(</phrase><phrase
role="identifier">f</phrase><phrase role="special">)</phrase></code>,
placing the <code><phrase role="identifier">PROPS</phrase></code> instance
on the heap. Override this method to allocate <code><phrase role="identifier">PROPS</phrase></code>
some other way. The returned <code><phrase role="identifier">fiber_properties</phrase></code>
pointer must point to the <code><phrase role="identifier">PROPS</phrase></code>
instance to be associated with fiber <code><phrase role="identifier">f</phrase></code>.
</para>
</listitem>
</varlistentry>
</variablelist>
<para>
<bridgehead renderas="sect4" id="class_context_bridgehead">
<phrase id="class_context"/>
<link linkend="class_context">Class <code>context</code></link>
</bridgehead>
</para>
<para>
While you are free to treat <code><phrase role="identifier">context</phrase><phrase
role="special">*</phrase></code> as an opaque token, certain <code><phrase
role="identifier">context</phrase></code> members may be useful to a custom
scheduler implementation.
</para>
<para>
(Most <code><phrase role="identifier">context</phrase></code> members are implementation
details; most of interest are implementations of <link linkend="class_fiber"> <code>fiber</code></link> methods.)
</para>
<programlisting><phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">fiber</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="identifier">nxt</phrase><phrase role="special">;</phrase>
<phrase role="keyword">static</phrase> <phrase role="identifier">context</phrase> <phrase role="special">*</phrase> <phrase role="identifier">main_fiber</phrase><phrase role="special">();</phrase>
<phrase role="special">};</phrase>
</programlisting>
<para>
<bridgehead renderas="sect4" id="context_nxt_bridgehead">
<phrase id="context_nxt"/>
<link linkend="context_nxt">Data member <code>nxt</code></link>
</bridgehead>
</para>
<programlisting><phrase role="identifier">context</phrase> <phrase role="special">*</phrase> <phrase role="identifier">nxt</phrase><phrase role="special">;</phrase>
</programlisting>
<variablelist>
<title></title>
<varlistentry>
<term>Note:</term>
<listitem>
<para>
This link pointer may be used to help implement a custom scheduler's
ready queue. It is overwritten by the fiber manager every time this
<code><phrase role="identifier">context</phrase></code> is returned by
<link linkend="sched_algorithm_pick_next"> <code>sched_algorithm::pick_next()</code></link>, but between the
time the fiber manager passes this <code><phrase role="identifier">context</phrase></code>
to <link linkend="sched_algorithm_awakened"> <code>sched_algorithm::awakened()</code></link> (or <link linkend="sched_algorithm_with_properties_awakened"> <code>sched_algorithm_with_properties::awakened()</code></link>)
and the time your <code><phrase role="identifier">pick_next</phrase><phrase
role="special">()</phrase></code> returns it to the fiber manager, it
is available for use by your custom scheduler.
</para>
</listitem>
</varlistentry>
</variablelist>
<para>
<bridgehead renderas="sect4" id="context_main_fiber_bridgehead">
<phrase id="context_main_fiber"/>
<link linkend="context_main_fiber">Static member
function <code>main_fiber</code>()</link>
</bridgehead>
</para>
<programlisting><phrase role="keyword">static</phrase> <phrase role="identifier">context</phrase> <phrase role="special">*</phrase> <phrase role="identifier">main_fiber</phrase><phrase role="special">();</phrase>
</programlisting>
<variablelist>
<title></title>
<varlistentry>
<term>Returns:</term>
<listitem>
<para>
the <code><phrase role="identifier">context</phrase></code> associated
with the &quot;main&quot; fiber of the thread: the one implicitly created
by the thread itself, rather than one explicitly created by <emphasis
role="bold">Boost.Fiber</emphasis>.
</para>
</listitem>
</varlistentry>
</variablelist>
</section>
<section id="fiber.stack">
<title><anchor id="stack"/><link linkend="fiber.stack">Stack allocation</link></title>
<para>
A <link linkend="class_fiber"> <code>fiber</code></link> uses internally a <ulink url="http://www.boost.org/doc/libs/release/libs/context/doc/html/context/econtext.html"><emphasis>execution_context</emphasis></ulink>
which manages a set of registers and a stack. The memory used by the stack
is allocated/deallocated via a <emphasis>stack_allocator</emphasis> which is
required to model a <link linkend="stack_allocator_concept"><emphasis>stack-allocator
concept</emphasis></link>.
</para>
<para>
A <emphasis>stack_allocator</emphasis> can be passed to <link linkend="fiber_fiber"><code><phrase
role="identifier">fiber</phrase><phrase role="special">::</phrase><phrase role="identifier">fiber</phrase><phrase
role="special">()</phrase></code></link> or to <link linkend="fibers_async"> <code>fibers::async()</code></link>.
</para>
<anchor id="stack_allocator_concept"/>
<bridgehead renderas="sect3" id="fiber.stack.h0">
<phrase id="fiber.stack._link_linkend__stack_allocator_concept___emphasis_stack_allocator_concept__emphasis___link_"/><link
linkend="fiber.stack._link_linkend__stack_allocator_concept___emphasis_stack_allocator_concept__emphasis___link_"><link
linkend="stack_allocator_concept"><emphasis>stack-allocator concept</emphasis></link></link>
</bridgehead>
<para>
A <emphasis>stack_allocator</emphasis> must satisfy the <link linkend="stack_allocator_concept"><emphasis>stack-allocator
concept</emphasis></link> requirements shown in the following table, in which
<code><phrase role="identifier">a</phrase></code> is an object of a <emphasis>stack_allocator</emphasis>
type, <code><phrase role="identifier">sctx</phrase></code> is a <ulink url="http://www.boost.org/doc/libs/release/libs/context/doc/html/context/stack/stack_context.html"><code><phrase
role="identifier">stack_context</phrase></code></ulink>, and <code><phrase
role="identifier">size</phrase></code> is a <code><phrase role="identifier">std</phrase><phrase
role="special">::</phrase><phrase role="identifier">size_t</phrase></code>:
</para>
<informaltable frame="all">
<tgroup cols="3">
<thead>
<row>
<entry>
<para>
expression
</para>
</entry>
<entry>
<para>
return type
</para>
</entry>
<entry>
<para>
notes
</para>
</entry>
</row>
</thead>
<tbody>
<row>
<entry>
<para>
<code><phrase role="identifier">a</phrase><phrase role="special">(</phrase><phrase
role="identifier">size</phrase><phrase role="special">)</phrase></code>
</para>
</entry>
<entry>
</entry>
<entry>
<para>
creates a stack allocator
</para>
</entry>
</row>
<row>
<entry>
<para>
<code><phrase role="identifier">a</phrase><phrase role="special">.</phrase><phrase
role="identifier">allocate</phrase><phrase role="special">()</phrase></code>
</para>
</entry>
<entry>
<para>
<ulink url="http://www.boost.org/doc/libs/release/libs/context/doc/html/context/stack/stack_context.html"><code><phrase
role="identifier">stack_context</phrase></code></ulink>
</para>
</entry>
<entry>
<para>
creates a stack
</para>
</entry>
</row>
<row>
<entry>
<para>
<code><phrase role="identifier">a</phrase><phrase role="special">.</phrase><phrase
role="identifier">deallocate</phrase><phrase role="special">(</phrase>
<phrase role="identifier">sctx</phrase><phrase role="special">)</phrase></code>
</para>
</entry>
<entry>
<para>
<code><phrase role="keyword">void</phrase></code>
</para>
</entry>
<entry>
<para>
deallocates the stack created by <code><phrase role="identifier">a</phrase><phrase
role="special">.</phrase><phrase role="identifier">allocate</phrase><phrase
role="special">()</phrase></code>
</para>
</entry>
</row>
</tbody>
</tgroup>
</informaltable>
<important>
<para>
The implementation of <code><phrase role="identifier">allocate</phrase><phrase
role="special">()</phrase></code> might include logic to protect against
exceeding the context's available stack size rather than leaving it as undefined
behaviour.
</para>
</important>
<important>
<para>
Calling <code><phrase role="identifier">deallocate</phrase><phrase role="special">()</phrase></code>
with a <ulink url="http://www.boost.org/doc/libs/release/libs/context/doc/html/context/stack/stack_context.html"><code><phrase
role="identifier">stack_context</phrase></code></ulink> not obtained from
<code><phrase role="identifier">allocate</phrase><phrase role="special">()</phrase></code>
results in undefined behaviour.
</para>
</important>
<note>
<para>
The memory for the stack is not required to be aligned; alignment takes place
inside <ulink url="http://www.boost.org/doc/libs/release/libs/context/doc/html/context/econtext.html"><emphasis>execution_context</emphasis></ulink>.
</para>
</note>
<para>
See also <ulink url="http://www.boost.org/doc/libs/release/libs/context/doc/html/context/stack.html">Boost.Context
stack allocation</ulink>.
</para>
<para>
<bridgehead renderas="sect4" id="class_protected_fixedsize_stack_bridgehead">
<phrase id="class_protected_fixedsize_stack"/>
<link linkend="class_protected_fixedsize_stack">Class
<code>protected_fixedsize_stack</code></link>
</bridgehead>
</para>
<para>
<emphasis role="bold">Boost.Fiber</emphasis> provides the class <link linkend="class_protected_fixedsize_stack"> <code>protected_fixedsize_stack</code></link> which
models the <link linkend="stack_allocator_concept"><emphasis>stack-allocator
concept</emphasis></link>. It appends a guard page at the end of each stack
to protect against exceeding the stack. If the guard page is accessed (read
or write operation) a segmentation fault/access violation is generated by the
operating system.
</para>
<important>
<para>
Using <link linkend="class_protected_fixedsize_stack"> <code>protected_fixedsize_stack</code></link> is expensive.
Launching a new fiber with a stack of this type incurs the overhead of setting
the memory protection; once allocated, this stack is just as efficient to
use as <link linkend="class_fixedsize_stack"> <code>fixedsize_stack</code></link>.
</para>
</important>
<note>
<para>
The appended <code><phrase role="identifier">guard</phrase> <phrase role="identifier">page</phrase></code>
is <emphasis role="bold">not</emphasis> mapped to physical memory, only virtual
addresses are used.
</para>
</note>
<para>
<bridgehead renderas="sect4" id="class_fixedsize_stack_bridgehead">
<phrase id="class_fixedsize_stack"/>
<link linkend="class_fixedsize_stack">Class
<code>fixedsize_stack</code></link>
</bridgehead>
</para>
<para>
<emphasis role="bold">Boost.Fiber</emphasis> provides the class <link linkend="class_fixedsize_stack"> <code>fixedsize_stack</code></link> which
models the <link linkend="stack_allocator_concept"><emphasis>stack-allocator
concept</emphasis></link>. In contrast to <link linkend="class_protected_fixedsize_stack"> <code>protected_fixedsize_stack</code></link> it
does not append a guard page at the end of each stack. The memory is simply
managed by <code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase
role="identifier">malloc</phrase><phrase role="special">()</phrase></code>
and <code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase
role="identifier">free</phrase><phrase role="special">()</phrase></code>.
</para>
<para>
<bridgehead renderas="sect4" id="class_segmented_stack_bridgehead">
<phrase id="class_segmented_stack"/>
<link linkend="class_segmented_stack">Class
<code>segmented_stack</code></link>
</bridgehead>
</para>
<para>
<emphasis role="bold">Boost.Fiber</emphasis> supports usage of a <link linkend="class_segmented_stack"> <code>segmented_stack</code></link>,
i.e. the stack grows on demand. The fiber is created with a minimal stack size
which will be increased as required. Class <link linkend="class_segmented_stack"> <code>segmented_stack</code></link> models
the <link linkend="stack_allocator_concept"><emphasis>stack-allocator concept</emphasis></link>.
In contrast to <link linkend="class_protected_fixedsize_stack"> <code>protected_fixedsize_stack</code></link> and
<link linkend="class_fixedsize_stack"> <code>fixedsize_stack</code></link> it creates a stack which grows on demand.
</para>
<note>
<para>
Segmented stacks are currently only supported by <emphasis role="bold">gcc</emphasis>
from version <emphasis role="bold">4.7</emphasis> and <emphasis role="bold">clang</emphasis>
from version <emphasis role="bold">3.4</emphasis> onwards. In order to use
a <link linkend="class_segmented_stack"> <code>segmented_stack</code></link>, <emphasis role="bold">Boost.Fiber</emphasis>
must be built with property <code><phrase role="identifier">segmented</phrase><phrase
role="special">-</phrase><phrase role="identifier">stacks</phrase></code>,
e.g. <emphasis role="bold">toolset=gcc segmented-stacks=on</emphasis> at
b2/bjam command line.
</para>
</note>
</section>
<section id="fiber.synchronization">
<title><anchor id="synchronization"/><link linkend="fiber.synchronization">Synchronization</link></title>
<para>
In general, <emphasis role="bold">Boost.Fiber</emphasis> synchronization objects
can neither be moved nor copied. A synchronization object acts as a mutually-agreed
rendezvous point between different fibers. If such an object were copied somewhere
else, the new copy would have no consumers. If such an object were <emphasis>moved</emphasis>
somewhere else, leaving the original instance in an unspecified state, existing
consumers would behave strangely.
</para>
<para>
The fiber synchronization objects provided by this library will, by default,
safely synchronize fibers running on different threads. However, this level
of synchronization can be removed (for performance) by building the library
with <emphasis role="bold"><code><phrase role="identifier">BOOST_FIBERS_NO_ATOMICS</phrase></code></emphasis>
defined. When the library is built with that macro, you must ensure that all
the fibers referencing a particular synchronization object are running in the
same thread.
</para>
<section id="fiber.synchronization.mutex_types">
<title><link linkend="fiber.synchronization.mutex_types">Mutex Types</link></title>
<para>
<bridgehead renderas="sect4" id="class_mutex_bridgehead">
<phrase id="class_mutex"/>
<link linkend="class_mutex">Class <code>mutex</code></link>
</bridgehead>
</para>
<programlisting><phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">fiber</phrase><phrase role="special">/</phrase><phrase role="identifier">mutex</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase>
<phrase role="keyword">class</phrase> <phrase role="identifier">mutex</phrase> <phrase role="special">{</phrase>
<phrase role="keyword">public</phrase><phrase role="special">:</phrase>
<phrase role="identifier">mutex</phrase><phrase role="special">();</phrase>
<phrase role="special">~</phrase><phrase role="identifier">mutex</phrase><phrase role="special">();</phrase>
<phrase role="identifier">mutex</phrase><phrase role="special">(</phrase> <phrase role="identifier">mutex</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="special">=</phrase> <phrase role="keyword">delete</phrase><phrase role="special">;</phrase>
<phrase role="identifier">mutex</phrase> <phrase role="special">&amp;</phrase> <phrase role="keyword">operator</phrase><phrase role="special">=(</phrase> <phrase role="identifier">mutex</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="special">=</phrase> <phrase role="keyword">delete</phrase><phrase role="special">;</phrase>
<phrase role="keyword">void</phrase> <phrase role="identifier">lock</phrase><phrase role="special">();</phrase>
<phrase role="keyword">bool</phrase> <phrase role="identifier">try_lock</phrase><phrase role="special">();</phrase>
<phrase role="keyword">void</phrase> <phrase role="identifier">unlock</phrase><phrase role="special">();</phrase>
<phrase role="special">};</phrase>
</programlisting>
<para>
<link linkend="class_mutex"> <code>mutex</code></link> provides an exclusive-ownership mutex. At most one fiber
can own the lock on a given instance of <link linkend="class_mutex"> <code>mutex</code></link> at any time. Multiple
concurrent calls to <code><phrase role="identifier">lock</phrase><phrase
role="special">()</phrase></code>, <code><phrase role="identifier">try_lock</phrase><phrase
role="special">()</phrase></code> and <code><phrase role="identifier">unlock</phrase><phrase
role="special">()</phrase></code> shall be permitted.
</para>
<para>
Any fiber blocked in <code><phrase role="identifier">lock</phrase><phrase
role="special">()</phrase></code> is suspended until the owning fiber releases
the lock by calling <code><phrase role="identifier">unlock</phrase><phrase
role="special">()</phrase></code>.
</para>
<para>
<bridgehead renderas="sect4" id="mutex_lock_bridgehead">
<phrase id="mutex_lock"/>
<link linkend="mutex_lock">Member function <code>lock</code>()</link>
</bridgehead>
</para>
<programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">lock</phrase><phrase role="special">();</phrase>
</programlisting>
<variablelist>
<title></title>
<varlistentry>
<term>Precondition:</term>
<listitem>
<para>
The calling fiber doesn't own the mutex.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Effects:</term>
<listitem>
<para>
The current fiber blocks until ownership can be obtained.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Throws:</term>
<listitem>
<para>
<code><phrase role="identifier">fiber_interrupted</phrase></code>
</para>
</listitem>
</varlistentry>
</variablelist>
<para>
<bridgehead renderas="sect4" id="mutex_try_lock_bridgehead">
<phrase id="mutex_try_lock"/>
<link linkend="mutex_try_lock">Member function <code>try_lock</code>()</link>
</bridgehead>
</para>
<programlisting><phrase role="keyword">bool</phrase> <phrase role="identifier">try_lock</phrase><phrase role="special">();</phrase>
</programlisting>
<variablelist>
<title></title>
<varlistentry>
<term>Precondition:</term>
<listitem>
<para>
The calling fiber doesn't own the mutex.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Effects:</term>
<listitem>
<para>
Attempt to obtain ownership for the current fiber without blocking.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Returns:</term>
<listitem>
<para>
<code><phrase role="keyword">true</phrase></code> if ownership was
obtained for the current fiber, <code><phrase role="keyword">false</phrase></code>
otherwise.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Throws:</term>
<listitem>
<para>
Nothing.
</para>
</listitem>
</varlistentry>
</variablelist>
<para>
<bridgehead renderas="sect4" id="mutex_unlock_bridgehead">
<phrase id="mutex_unlock"/>
<link linkend="mutex_unlock">Member function <code>unlock</code>()</link>
</bridgehead>
</para>
<programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">unlock</phrase><phrase role="special">();</phrase>
</programlisting>
<variablelist>
<title></title>
<varlistentry>
<term>Precondition:</term>
<listitem>
<para>
The current fiber owns <code><phrase role="special">*</phrase><phrase
role="keyword">this</phrase></code>.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Effects:</term>
<listitem>
<para>
Releases a lock on <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>
by the current fiber.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Throws:</term>
<listitem>
<para>
Nothing.
</para>
</listitem>
</varlistentry>
</variablelist>
<para>
<bridgehead renderas="sect4" id="class_timed_mutex_bridgehead">
<phrase id="class_timed_mutex"/>
<link linkend="class_timed_mutex">Class <code>timed_mutex</code></link>
</bridgehead>
</para>
<programlisting><phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">fiber</phrase><phrase role="special">/</phrase><phrase role="identifier">timed_mutex</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase>
<phrase role="keyword">class</phrase> <phrase role="identifier">timed_mutex</phrase> <phrase role="special">{</phrase>
<phrase role="keyword">public</phrase><phrase role="special">:</phrase>
<phrase role="identifier">timed_mutex</phrase><phrase role="special">();</phrase>
<phrase role="special">~</phrase><phrase role="identifier">timed_mutex</phrase><phrase role="special">();</phrase>
<phrase role="identifier">timed_mutex</phrase><phrase role="special">(</phrase> <phrase role="identifier">timed_mutex</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="special">=</phrase> <phrase role="keyword">delete</phrase><phrase role="special">;</phrase>
<phrase role="identifier">timed_mutex</phrase> <phrase role="special">&amp;</phrase> <phrase role="keyword">operator</phrase><phrase role="special">=(</phrase> <phrase role="identifier">timed_mutex</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="special">=</phrase> <phrase role="keyword">delete</phrase><phrase role="special">;</phrase>
<phrase role="keyword">void</phrase> <phrase role="identifier">lock</phrase><phrase role="special">();</phrase>
<phrase role="keyword">void</phrase> <phrase role="identifier">unlock</phrase><phrase role="special">();</phrase>
<phrase role="keyword">bool</phrase> <phrase role="identifier">try_lock</phrase><phrase role="special">();</phrase>
<phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Clock</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Duration</phrase> <phrase role="special">&gt;</phrase>
<phrase role="keyword">bool</phrase> <phrase role="identifier">try_lock_until</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">time_point</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Clock</phrase><phrase role="special">,</phrase> <phrase role="identifier">Duration</phrase> <phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">timeout_time</phrase><phrase role="special">)</phrase>
<phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Rep</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Period</phrase> <phrase role="special">&gt;</phrase>
<phrase role="keyword">bool</phrase> <phrase role="identifier">try_lock_for</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">duration</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Rep</phrase><phrase role="special">,</phrase> <phrase role="identifier">Period</phrase> <phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">timeout_duration</phrase><phrase role="special">)</phrase>
<phrase role="special">};</phrase>
</programlisting>
<para>
<link linkend="class_timed_mutex"> <code>timed_mutex</code></link> provides an exclusive-ownership mutex. At most
one fiber can own the lock on a given instance of <link linkend="class_timed_mutex"> <code>timed_mutex</code></link> at
any time. Multiple concurrent calls to <code><phrase role="identifier">lock</phrase><phrase
role="special">()</phrase></code>, <code><phrase role="identifier">try_lock</phrase><phrase
role="special">()</phrase></code>, <code><phrase role="identifier">try_lock_until</phrase><phrase
role="special">()</phrase></code>, <code><phrase role="identifier">try_lock_for</phrase><phrase
role="special">()</phrase></code> and <code><phrase role="identifier">unlock</phrase><phrase
role="special">()</phrase></code> shall be permitted.
</para>
<para>
<bridgehead renderas="sect4" id="timed_mutex_lock_bridgehead">
<phrase id="timed_mutex_lock"/>
<link linkend="timed_mutex_lock">Member function
<code>lock</code>()</link>
</bridgehead>
</para>
<programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">lock</phrase><phrase role="special">();</phrase>
</programlisting>
<variablelist>
<title></title>
<varlistentry>
<term>Precondition:</term>
<listitem>
<para>
The calling fiber doesn't own the mutex.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Effects:</term>
<listitem>
<para>
The current fiber blocks until ownership can be obtained.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Throws:</term>
<listitem>
<para>
<code><phrase role="identifier">fiber_interrupted</phrase></code>
</para>
</listitem>
</varlistentry>
</variablelist>
<para>
<bridgehead renderas="sect4" id="timed_mutex_try_lock_bridgehead">
<phrase id="timed_mutex_try_lock"/>
<link linkend="timed_mutex_try_lock">Member
function <code>try_lock</code>()</link>
</bridgehead>
</para>
<programlisting><phrase role="keyword">bool</phrase> <phrase role="identifier">try_lock</phrase><phrase role="special">();</phrase>
</programlisting>
<variablelist>
<title></title>
<varlistentry>
<term>Precondition:</term>
<listitem>
<para>
The calling fiber doesn't own the mutex.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Effects:</term>
<listitem>
<para>
Attempt to obtain ownership for the current fiber without blocking.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Returns:</term>
<listitem>
<para>
<code><phrase role="keyword">true</phrase></code> if ownership was
obtained for the current fiber, <code><phrase role="keyword">false</phrase></code>
otherwise.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Throws:</term>
<listitem>
<para>
Nothing.
</para>
</listitem>
</varlistentry>
</variablelist>
<para>
<bridgehead renderas="sect4" id="timed_mutex_unlock_bridgehead">
<phrase id="timed_mutex_unlock"/>
<link linkend="timed_mutex_unlock">Member function
<code>unlock</code>()</link>
</bridgehead>
</para>
<programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">unlock</phrase><phrase role="special">();</phrase>
</programlisting>
<variablelist>
<title></title>
<varlistentry>
<term>Precondition:</term>
<listitem>
<para>
The current fiber owns <code><phrase role="special">*</phrase><phrase
role="keyword">this</phrase></code>.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Effects:</term>
<listitem>
<para>
Releases a lock on <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>
by the current fiber.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Throws:</term>
<listitem>
<para>
Nothing.
</para>
</listitem>
</varlistentry>
</variablelist>
<para>
<bridgehead renderas="sect4" id="timed_mutex_try_lock_until_bridgehead">
<phrase id="timed_mutex_try_lock_until"/>
<link linkend="timed_mutex_try_lock_until">Templated
member function <code>try_lock_until</code>()</link>
</bridgehead>
</para>
<programlisting><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Clock</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Duration</phrase> <phrase role="special">&gt;</phrase>
<phrase role="keyword">bool</phrase> <phrase role="identifier">try_lock_until</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">time_point</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Clock</phrase><phrase role="special">,</phrase> <phrase role="identifier">Duration</phrase> <phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">timeout_time</phrase><phrase role="special">)</phrase>
</programlisting>
<variablelist>
<title></title>
<varlistentry>
<term>Precondition:</term>
<listitem>
<para>
The calling fiber doesn't own the mutex.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Effects:</term>
<listitem>
<para>
Attempt to obtain ownership for the current fiber. Blocks until ownership
can be obtained, or the specified time is reached. If the specified
time has already passed, behaves as <link linkend="timed_mutex_try_lock"> <code>timed_mutex::try_lock()</code></link>.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Returns:</term>
<listitem>
<para>
<code><phrase role="keyword">true</phrase></code> if ownership was
obtained for the current fiber, <code><phrase role="keyword">false</phrase></code>
otherwise.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Throws:</term>
<listitem>
<para>
Nothing.
</para>
</listitem>
</varlistentry>
</variablelist>
<para>
<bridgehead renderas="sect4" id="timed_mutex_try_lock_for_bridgehead">
<phrase id="timed_mutex_try_lock_for"/>
<link linkend="timed_mutex_try_lock_for">Templated
member function <code>try_lock_for</code>()</link>
</bridgehead>
</para>
<programlisting><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Rep</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Period</phrase> <phrase role="special">&gt;</phrase>
<phrase role="keyword">bool</phrase> <phrase role="identifier">try_lock_for</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">duration</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Rep</phrase><phrase role="special">,</phrase> <phrase role="identifier">Period</phrase> <phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">timeout_duration</phrase><phrase role="special">)</phrase>
</programlisting>
<variablelist>
<title></title>
<varlistentry>
<term>Precondition:</term>
<listitem>
<para>
The calling fiber doesn't own the mutex.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Effects:</term>
<listitem>
<para>
Attempt to obtain ownership for the current fiber. Blocks until ownership
can be obtained, or the specified time is reached. If the specified
time has already passed, behaves as <link linkend="timed_mutex_try_lock"> <code>timed_mutex::try_lock()</code></link>.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Returns:</term>
<listitem>
<para>
<code><phrase role="keyword">true</phrase></code> if ownership was
obtained for the current fiber, <code><phrase role="keyword">false</phrase></code>
otherwise.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Throws:</term>
<listitem>
<para>
Nothing.
</para>
</listitem>
</varlistentry>
</variablelist>
<para>
<bridgehead renderas="sect4" id="class_recursive_mutex_bridgehead">
<phrase id="class_recursive_mutex"/>
<link linkend="class_recursive_mutex">Class
<code>recursive_mutex</code></link>
</bridgehead>
</para>
<programlisting><phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">fiber</phrase><phrase role="special">/</phrase><phrase role="identifier">recursive_mutex</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase>
<phrase role="keyword">class</phrase> <phrase role="identifier">recursive_mutex</phrase> <phrase role="special">{</phrase>
<phrase role="keyword">public</phrase><phrase role="special">:</phrase>
<phrase role="identifier">recursive_mutex</phrase><phrase role="special">();</phrase>
<phrase role="special">~</phrase><phrase role="identifier">recursive_mutex</phrase><phrase role="special">();</phrase>
<phrase role="identifier">recursive_mutex</phrase><phrase role="special">(</phrase> <phrase role="identifier">recursive_mutex</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="special">=</phrase> <phrase role="keyword">delete</phrase><phrase role="special">;</phrase>
<phrase role="identifier">recursive_mutex</phrase> <phrase role="special">&amp;</phrase> <phrase role="keyword">operator</phrase><phrase role="special">=(</phrase> <phrase role="identifier">recursive_mutex</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="special">=</phrase> <phrase role="keyword">delete</phrase><phrase role="special">;</phrase>
<phrase role="keyword">void</phrase> <phrase role="identifier">lock</phrase><phrase role="special">();</phrase>
<phrase role="keyword">bool</phrase> <phrase role="identifier">try_lock</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
<phrase role="keyword">void</phrase> <phrase role="identifier">unlock</phrase><phrase role="special">();</phrase>
<phrase role="special">};</phrase>
</programlisting>
<para>
<link linkend="class_recursive_mutex"> <code>recursive_mutex</code></link> provides an exclusive-ownership recursive
mutex. At most one fiber can own the lock on a given instance of <link linkend="class_recursive_mutex"> <code>recursive_mutex</code></link> at
any time. Multiple concurrent calls to <code><phrase role="identifier">lock</phrase><phrase
role="special">()</phrase></code>, <code><phrase role="identifier">try_lock</phrase><phrase
role="special">()</phrase></code> and <code><phrase role="identifier">unlock</phrase><phrase
role="special">()</phrase></code> shall be permitted. A fiber that already
has exclusive ownership of a given <link linkend="class_recursive_mutex"> <code>recursive_mutex</code></link> instance
can call <code><phrase role="identifier">lock</phrase><phrase role="special">()</phrase></code>
or <code><phrase role="identifier">try_lock</phrase><phrase role="special">()</phrase></code>
to acquire an additional level of ownership of the mutex. <code><phrase role="identifier">unlock</phrase><phrase
role="special">()</phrase></code> must be called once for each level of ownership
acquired by a single fiber before ownership can be acquired by another fiber.
</para>
<para>
<bridgehead renderas="sect4" id="recursive_mutex_lock_bridgehead">
<phrase id="recursive_mutex_lock"/>
<link linkend="recursive_mutex_lock">Member
function <code>lock</code>()</link>
</bridgehead>
</para>
<programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">lock</phrase><phrase role="special">();</phrase>
</programlisting>
<variablelist>
<title></title>
<varlistentry>
<term>Effects:</term>
<listitem>
<para>
The current fiber blocks until ownership can be obtained.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Throws:</term>
<listitem>
<para>
<code><phrase role="identifier">fiber_interrupted</phrase></code>
</para>
</listitem>
</varlistentry>
</variablelist>
<para>
<bridgehead renderas="sect4" id="recursive_mutex_try_lock_bridgehead">
<phrase id="recursive_mutex_try_lock"/>
<link linkend="recursive_mutex_try_lock">Member
function <code>try_lock</code>()</link>
</bridgehead>
</para>
<programlisting><phrase role="keyword">bool</phrase> <phrase role="identifier">try_lock</phrase><phrase role="special">();</phrase>
</programlisting>
<variablelist>
<title></title>
<varlistentry>
<term>Effects:</term>
<listitem>
<para>
Attempt to obtain ownership for the current fiber without blocking.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Returns:</term>
<listitem>
<para>
<code><phrase role="keyword">true</phrase></code> if ownership was
obtained for the current fiber, <code><phrase role="keyword">false</phrase></code>
otherwise.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Throws:</term>
<listitem>
<para>
Nothing.
</para>
</listitem>
</varlistentry>
</variablelist>
<para>
<bridgehead renderas="sect4" id="recursive_mutex_unlock_bridgehead">
<phrase id="recursive_mutex_unlock"/>
<link linkend="recursive_mutex_unlock">Member
function <code>unlock</code>()</link>
</bridgehead>
</para>
<programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">unlock</phrase><phrase role="special">();</phrase>
</programlisting>
<variablelist>
<title></title>
<varlistentry>
<term>Effects:</term>
<listitem>
<para>
Releases a lock on <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>
by the current fiber.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Throws:</term>
<listitem>
<para>
Nothing.
</para>
</listitem>
</varlistentry>
</variablelist>
<para>
<bridgehead renderas="sect4" id="class_recursive_timed_mutex_bridgehead">
<phrase id="class_recursive_timed_mutex"/>
<link linkend="class_recursive_timed_mutex">Class
<code>recursive_timed_mutex</code></link>
</bridgehead>
</para>
<programlisting><phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">fiber</phrase><phrase role="special">/</phrase><phrase role="identifier">recursive_timed_mutex</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase>
<phrase role="keyword">class</phrase> <phrase role="identifier">recursive_timed_mutex</phrase> <phrase role="special">{</phrase>
<phrase role="keyword">public</phrase><phrase role="special">:</phrase>
<phrase role="identifier">recursive_timed_mutex</phrase><phrase role="special">();</phrase>
<phrase role="special">~</phrase><phrase role="identifier">recursive_timed_mutex</phrase><phrase role="special">();</phrase>
<phrase role="identifier">recursive_timed_mutex</phrase><phrase role="special">(</phrase> <phrase role="identifier">recursive_timed_mutex</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="special">=</phrase> <phrase role="keyword">delete</phrase><phrase role="special">;</phrase>
<phrase role="identifier">recursive_timed_mutex</phrase> <phrase role="special">&amp;</phrase> <phrase role="keyword">operator</phrase><phrase role="special">=(</phrase> <phrase role="identifier">recursive_timed_mutex</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="special">=</phrase> <phrase role="keyword">delete</phrase><phrase role="special">;</phrase>
<phrase role="keyword">void</phrase> <phrase role="identifier">lock</phrase><phrase role="special">();</phrase>
<phrase role="keyword">bool</phrase> <phrase role="identifier">try_lock</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
<phrase role="keyword">void</phrase> <phrase role="identifier">unlock</phrase><phrase role="special">();</phrase>
<phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Clock</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Duration</phrase> <phrase role="special">&gt;</phrase>
<phrase role="keyword">bool</phrase> <phrase role="identifier">try_lock_until</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">time_point</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Clock</phrase><phrase role="special">,</phrase> <phrase role="identifier">Duration</phrase> <phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">timeout_time</phrase><phrase role="special">)</phrase>
<phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Rep</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Period</phrase> <phrase role="special">&gt;</phrase>
<phrase role="keyword">bool</phrase> <phrase role="identifier">try_lock_for</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">duration</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Rep</phrase><phrase role="special">,</phrase> <phrase role="identifier">Period</phrase> <phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">timeout_duration</phrase><phrase role="special">)</phrase>
<phrase role="special">};</phrase>
</programlisting>
<para>
<link linkend="class_recursive_timed_mutex"> <code>recursive_timed_mutex</code></link> provides an exclusive-ownership
recursive mutex. At most one fiber can own the lock on a given instance of
<link linkend="class_recursive_timed_mutex"> <code>recursive_timed_mutex</code></link> at any time. Multiple concurrent
calls to <code><phrase role="identifier">lock</phrase><phrase role="special">()</phrase></code>,
<code><phrase role="identifier">try_lock</phrase><phrase role="special">()</phrase></code>,
<code><phrase role="identifier">try_lock_for</phrase><phrase role="special">()</phrase></code>,
<code><phrase role="identifier">try_lock_until</phrase><phrase role="special">()</phrase></code>
and <code><phrase role="identifier">unlock</phrase><phrase role="special">()</phrase></code>
shall be permitted. A fiber that already has exclusive ownership of a given
<link linkend="class_recursive_timed_mutex"> <code>recursive_timed_mutex</code></link> instance can call <code><phrase
role="identifier">lock</phrase><phrase role="special">()</phrase></code>,
<code><phrase role="identifier">try_lock</phrase><phrase role="special">()</phrase></code>,
<code><phrase role="identifier">try_lock_for</phrase><phrase role="special">()</phrase></code>
or <code><phrase role="identifier">try_lock_until</phrase><phrase role="special">()</phrase></code>
to acquire an additional level of ownership of the mutex. <code><phrase role="identifier">unlock</phrase><phrase
role="special">()</phrase></code> must be called once for each level of ownership
acquired by a single fiber before ownership can be acquired by another fiber.
</para>
<para>
<bridgehead renderas="sect4" id="recursive_timed_mutex_lock_bridgehead">
<phrase id="recursive_timed_mutex_lock"/>
<link linkend="recursive_timed_mutex_lock">Member
function <code>lock</code>()</link>
</bridgehead>
</para>
<programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">lock</phrase><phrase role="special">();</phrase>
</programlisting>
<variablelist>
<title></title>
<varlistentry>
<term>Effects:</term>
<listitem>
<para>
The current fiber blocks until ownership can be obtained.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Throws:</term>
<listitem>
<para>
<code><phrase role="identifier">fiber_interrupted</phrase></code>
</para>
</listitem>
</varlistentry>
</variablelist>
<para>
<bridgehead renderas="sect4" id="recursive_timed_mutex_try_lock_bridgehead">
<phrase id="recursive_timed_mutex_try_lock"/>
<link linkend="recursive_timed_mutex_try_lock">Member
function <code>try_lock</code>()</link>
</bridgehead>
</para>
<programlisting><phrase role="keyword">bool</phrase> <phrase role="identifier">try_lock</phrase><phrase role="special">();</phrase>
</programlisting>
<variablelist>
<title></title>
<varlistentry>
<term>Effects:</term>
<listitem>
<para>
Attempt to obtain ownership for the current fiber without blocking.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Returns:</term>
<listitem>
<para>
<code><phrase role="keyword">true</phrase></code> if ownership was
obtained for the current fiber, <code><phrase role="keyword">false</phrase></code>
otherwise.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Throws:</term>
<listitem>
<para>
Nothing.
</para>
</listitem>
</varlistentry>
</variablelist>
<para>
<bridgehead renderas="sect4" id="recursive_timed_mutex_unlock_bridgehead">
<phrase id="recursive_timed_mutex_unlock"/>
<link linkend="recursive_timed_mutex_unlock">Member
function <code>unlock</code>()</link>
</bridgehead>
</para>
<programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">unlock</phrase><phrase role="special">();</phrase>
</programlisting>
<variablelist>
<title></title>
<varlistentry>
<term>Effects:</term>
<listitem>
<para>
Releases a lock on <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>
by the current fiber.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Throws:</term>
<listitem>
<para>
Nothing.
</para>
</listitem>
</varlistentry>
</variablelist>
<para>
<bridgehead renderas="sect4" id="recursive_timed_mutex_try_lock_until_bridgehead">
<phrase id="recursive_timed_mutex_try_lock_until"/>
<link linkend="recursive_timed_mutex_try_lock_until">Templated
member function <code>try_lock_until</code>()</link>
</bridgehead>
</para>
<programlisting><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Clock</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Duration</phrase> <phrase role="special">&gt;</phrase>
<phrase role="keyword">bool</phrase> <phrase role="identifier">try_lock_until</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">time_point</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Clock</phrase><phrase role="special">,</phrase> <phrase role="identifier">Duration</phrase> <phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">timeout_time</phrase><phrase role="special">)</phrase>
</programlisting>
<variablelist>
<title></title>
<varlistentry>
<term>Effects:</term>
<listitem>
<para>
Attempt to obtain ownership for the current fiber. Blocks until ownership
can be obtained, or the specified time is reached. If the specified
time has already passed, behaves as <link linkend="recursive_timed_mutex_try_lock"> <code>recursive_timed_mutex::try_lock()</code></link>.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Returns:</term>
<listitem>
<para>
<code><phrase role="keyword">true</phrase></code> if ownership was
obtained for the current fiber, <code><phrase role="keyword">false</phrase></code>
otherwise.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Throws:</term>
<listitem>
<para>
Nothing.
</para>
</listitem>
</varlistentry>
</variablelist>
<para>
<bridgehead renderas="sect4" id="recursive_timed_mutex_try_lock_for_bridgehead">
<phrase id="recursive_timed_mutex_try_lock_for"/>
<link linkend="recursive_timed_mutex_try_lock_for">Templated
member function <code>try_lock_for</code>()</link>
</bridgehead>
</para>
<programlisting><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Rep</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Period</phrase> <phrase role="special">&gt;</phrase>
<phrase role="keyword">bool</phrase> <phrase role="identifier">try_lock_for</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">duration</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Rep</phrase><phrase role="special">,</phrase> <phrase role="identifier">Period</phrase> <phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">timeout_duration</phrase><phrase role="special">)</phrase>
</programlisting>
<variablelist>
<title></title>
<varlistentry>
<term>Effects:</term>
<listitem>
<para>
Attempt to obtain ownership for the current fiber. Blocks until ownership
can be obtained, or the specified time is reached. If the specified
time has already passed, behaves as <link linkend="recursive_timed_mutex_try_lock"> <code>recursive_timed_mutex::try_lock()</code></link>.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Returns:</term>
<listitem>
<para>
<code><phrase role="keyword">true</phrase></code> if ownership was
obtained for the current fiber, <code><phrase role="keyword">false</phrase></code>
otherwise.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Throws:</term>
<listitem>
<para>
Nothing.
</para>
</listitem>
</varlistentry>
</variablelist>
</section>
<section id="fiber.synchronization.conditions">
<title><link linkend="fiber.synchronization.conditions">Condition Variables</link></title>
<bridgehead renderas="sect4" id="fiber.synchronization.conditions.h0">
<phrase id="fiber.synchronization.conditions.synopsis"/><link linkend="fiber.synchronization.conditions.synopsis">Synopsis</link>
</bridgehead>
<programlisting><phrase role="keyword">enum</phrase> <phrase role="keyword">class</phrase> <phrase role="identifier">cv_status</phrase><phrase role="special">;</phrase> <phrase role="special">{</phrase>
<phrase role="identifier">no_timeout</phrase><phrase role="special">,</phrase>
<phrase role="identifier">timeout</phrase>
<phrase role="special">};</phrase>
<phrase role="keyword">class</phrase> <phrase role="identifier">condition_variable</phrase><phrase role="special">;</phrase>
<phrase role="keyword">class</phrase> <phrase role="identifier">condition_variable_any</phrase><phrase role="special">;</phrase>
</programlisting>
<para>
The class <code><phrase role="identifier">condition_variable</phrase></code>
provides a mechanism for a fiber to wait for notification from another fiber.
When the fiber awakens from the wait, then it checks to see if the appropriate
condition is now true, and continues if so. If the condition is not true,
then the fiber calls <code><phrase role="identifier">wait</phrase></code>
again to resume waiting. In the simplest case, this condition is just a boolean
variable:
</para>
<programlisting><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">condition_variable</phrase> <phrase role="identifier">cond</phrase><phrase role="special">;</phrase>
<phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">mutex</phrase> <phrase role="identifier">mtx</phrase><phrase role="special">;</phrase>
<phrase role="keyword">bool</phrase> <phrase role="identifier">data_ready</phrase> <phrase role="special">=</phrase> <phrase role="keyword">false</phrase><phrase role="special">;</phrase>
<phrase role="keyword">void</phrase> <phrase role="identifier">process_data</phrase><phrase role="special">();</phrase>
<phrase role="keyword">void</phrase> <phrase role="identifier">wait_for_data_to_process</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">unique_lock</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">mutex</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">lk</phrase><phrase role="special">(</phrase> <phrase role="identifier">mtx</phrase><phrase role="special">);</phrase>
<phrase role="keyword">while</phrase> <phrase role="special">(</phrase> <phrase role="special">!</phrase> <phrase role="identifier">data_ready</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
<phrase role="identifier">cond</phrase><phrase role="special">.</phrase><phrase role="identifier">wait</phrase><phrase role="special">(</phrase> <phrase role="identifier">lk</phrase><phrase role="special">);</phrase>
<phrase role="special">}</phrase>
<phrase role="special">}</phrase> <phrase role="comment">// release lk</phrase>
<phrase role="identifier">process_data</phrase><phrase role="special">();</phrase>
<phrase role="special">}</phrase>
</programlisting>
<para>
Notice that the <code><phrase role="identifier">lk</phrase></code> is passed
to <code><phrase role="identifier">wait</phrase></code>: <code><phrase role="identifier">wait</phrase></code>
will atomically add the fiber to the set of fibers waiting on the condition
variable, and unlock the mutex. When the fiber is awakened, the mutex will
be locked again before the call to <code><phrase role="identifier">wait</phrase></code>
returns. This allows other fibers to acquire the mutex in order to update
the shared data, and ensures that the data associated with the condition
is correctly synchronized.
</para>
<para>
In the meantime, another fiber sets <code><phrase role="identifier">data_ready</phrase></code>
to <code><phrase role="keyword">true</phrase></code>, and then calls either
<code><phrase role="identifier">notify_one</phrase></code> or <code><phrase
role="identifier">notify_all</phrase></code> on the condition variable <code><phrase
role="identifier">cond</phrase></code> to wake one waiting fiber or all the
waiting fibers respectively.
</para>
<programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">retrieve_data</phrase><phrase role="special">();</phrase>
<phrase role="keyword">void</phrase> <phrase role="identifier">prepare_data</phrase><phrase role="special">();</phrase>
<phrase role="keyword">void</phrase> <phrase role="identifier">prepare_data_for_processing</phrase><phrase role="special">()</phrase> <phrase role="special">{</phrase>
<phrase role="identifier">retrieve_data</phrase><phrase role="special">();</phrase>
<phrase role="identifier">prepare_data</phrase><phrase role="special">();</phrase>
<phrase role="special">{</phrase>
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">unique_lock</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">mutex</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">lk</phrase><phrase role="special">(</phrase> <phrase role="identifier">mtx</phrase><phrase role="special">);</phrase>
<phrase role="identifier">data_ready</phrase> <phrase role="special">=</phrase> <phrase role="keyword">true</phrase><phrase role="special">;</phrase>
<phrase role="special">}</phrase>
<phrase role="identifier">cond</phrase><phrase role="special">.</phrase><phrase role="identifier">notify_one</phrase><phrase role="special">();</phrase>
<phrase role="special">}</phrase>
</programlisting>
<para>
Note that the same mutex is locked before the shared data is updated, but
that the mutex does not have to be locked across the call to <code><phrase
role="identifier">notify_one</phrase></code>.
</para>
<para>
Locking is important because the synchronization objects provided by <emphasis
role="bold">Boost.Fiber</emphasis> can be used to synchronize fibers running
on different threads.
</para>
<para>
<emphasis role="bold">Boost.Fiber</emphasis> provides both <code><phrase
role="identifier">condition_variable</phrase></code> and <code><phrase role="identifier">condition_variable_any</phrase></code>
because <ulink url="http://www.boost.org/doc/libs/release/libs/thread/index.html">Boost.Thread</ulink>
provides both. (<emphasis role="bold">Boost.Fiber</emphasis> also provides
the name <code><phrase role="identifier">condition</phrase></code>, which
has been deprecated in <ulink url="http://www.boost.org/doc/libs/release/libs/thread/index.html">Boost.Thread</ulink>.)
However, <code><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase
role="identifier">fiber</phrase><phrase role="special">::</phrase><phrase
role="identifier">condition_variable</phrase></code> and <code><phrase role="identifier">boost</phrase><phrase
role="special">::</phrase><phrase role="identifier">fiber</phrase><phrase
role="special">::</phrase><phrase role="identifier">condition_variable_any</phrase></code>
are the same class; like <code><phrase role="identifier">boost</phrase><phrase
role="special">::</phrase><phrase role="identifier">thread</phrase><phrase
role="special">::</phrase><phrase role="identifier">condition_variable_any</phrase></code>,
its wait() method will accept any form of lock. <code><phrase role="identifier">boost</phrase><phrase
role="special">::</phrase><phrase role="identifier">fiber</phrase><phrase
role="special">::</phrase><phrase role="identifier">condition_variable_any</phrase></code>
has no need to further optimize as described for <code><phrase role="identifier">boost</phrase><phrase
role="special">::</phrase><phrase role="identifier">thread</phrase><phrase
role="special">::</phrase><phrase role="identifier">condition_variable</phrase></code>.
</para>
<para>
<bridgehead renderas="sect4" id="class_condition_variable_bridgehead">
<phrase id="class_condition_variable"/>
<link linkend="class_condition_variable">Class
<code>condition_variable</code></link>
</bridgehead>
</para>
<programlisting><phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">fiber</phrase><phrase role="special">/</phrase><phrase role="identifier">condition</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase>
<phrase role="keyword">enum</phrase> <phrase role="identifier">cv_status</phrase> <phrase role="special">{</phrase>
<phrase role="identifier">no_timeout</phrase><phrase role="special">,</phrase>
<phrase role="identifier">timeout</phrase>
<phrase role="special">};</phrase>
<phrase role="keyword">class</phrase> <phrase role="identifier">condition_variable</phrase> <phrase role="special">{</phrase>
<phrase role="keyword">public</phrase><phrase role="special">:</phrase>
<phrase role="identifier">condition_variable</phrase><phrase role="special">();</phrase>
<phrase role="special">~</phrase><phrase role="identifier">condition_variable</phrase><phrase role="special">();</phrase>
<phrase role="identifier">condition_variable</phrase><phrase role="special">(</phrase> <phrase role="identifier">condition_variable</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;)</phrase> <phrase role="special">=</phrase> <phrase role="keyword">delete</phrase><phrase role="special">;</phrase>
<phrase role="identifier">condition_variable</phrase> <phrase role="special">&amp;</phrase> <phrase role="keyword">operator</phrase><phrase role="special">=(</phrase> <phrase role="identifier">condition_variable</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;)</phrase> <phrase role="special">=</phrase> <phrase role="keyword">delete</phrase><phrase role="special">;</phrase>
<phrase role="keyword">void</phrase> <phrase role="identifier">notify_one</phrase><phrase role="special">();</phrase>
<phrase role="keyword">void</phrase> <phrase role="identifier">notify_all</phrase><phrase role="special">();</phrase>
<phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">LockType</phrase> <phrase role="special">&gt;</phrase>
<phrase role="keyword">void</phrase> <phrase role="identifier">wait</phrase><phrase role="special">(</phrase> <phrase role="identifier">LockType</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">lk</phrase><phrase role="special">);</phrase>
<phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">LockType</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Pred</phrase> <phrase role="special">&gt;</phrase>
<phrase role="keyword">void</phrase> <phrase role="identifier">wait</phrase><phrase role="special">(</phrase> <phrase role="identifier">LockType</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">lk</phrase><phrase role="special">,</phrase> <phrase role="identifier">Pred</phrase> <phrase role="identifier">predicate</phrase><phrase role="special">);</phrase>
<phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">LockType</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Clock</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Duration</phrase> <phrase role="special">&gt;</phrase>
<phrase role="identifier">cv_status</phrase> <phrase role="identifier">wait_until</phrase><phrase role="special">(</phrase> <phrase role="identifier">LockType</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">lk</phrase><phrase role="special">,</phrase>
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">time_point</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Clock</phrase><phrase role="special">,</phrase> <phrase role="identifier">Duration</phrase> <phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">timeout_time</phrase><phrase role="special">);</phrase>
<phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">LockType</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Clock</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Duration</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Pred</phrase> <phrase role="special">&gt;</phrase>
<phrase role="keyword">bool</phrase> <phrase role="identifier">wait_until</phrase><phrase role="special">(</phrase> <phrase role="identifier">LockType</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">lk</phrase><phrase role="special">,</phrase>
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">time_point</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Clock</phrase><phrase role="special">,</phrase> <phrase role="identifier">Duration</phrase> <phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">timeout_time</phrase><phrase role="special">,</phrase>
<phrase role="identifier">Pred</phrase> <phrase role="identifier">pred</phrase><phrase role="special">);</phrase>
<phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">LockType</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Rep</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Period</phrase> <phrase role="special">&gt;</phrase>
<phrase role="identifier">cv_status</phrase> <phrase role="identifier">wait_for</phrase><phrase role="special">(</phrase> <phrase role="identifier">LockType</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">lk</phrase><phrase role="special">,</phrase>
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">duration</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Rep</phrase><phrase role="special">,</phrase> <phrase role="identifier">Period</phrase> <phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">timeout_duration</phrase><phrase role="special">);</phrase>
<phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">LockType</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Rep</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Period</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Pred</phrase> <phrase role="special">&gt;</phrase>
<phrase role="keyword">bool</phrase> <phrase role="identifier">wait_for</phrase><phrase role="special">(</phrase> <phrase role="identifier">LockType</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">lk</phrase><phrase role="special">,</phrase>
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">duration</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Rep</phrase><phrase role="special">,</phrase> <phrase role="identifier">Period</phrase> <phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">timeout_duration</phrase><phrase role="special">,</phrase>
<phrase role="identifier">Pred</phrase> <phrase role="identifier">pred</phrase><phrase role="special">);</phrase>
<phrase role="special">};</phrase>
<phrase role="keyword">typedef</phrase> <phrase role="identifier">condition_variable</phrase> <phrase role="identifier">condition_variable_any</phrase><phrase role="special">;</phrase>
</programlisting>
<bridgehead renderas="sect4" id="fiber.synchronization.conditions.h1">
<phrase id="fiber.synchronization.conditions.constructor"/><link linkend="fiber.synchronization.conditions.constructor">Constructor</link>
</bridgehead>
<programlisting><phrase role="identifier">condition_variable</phrase><phrase role="special">()</phrase>
</programlisting>
<variablelist>
<title></title>
<varlistentry>
<term>Effects:</term>
<listitem>
<para>
Creates the object.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Throws:</term>
<listitem>
<para>
Nothing.
</para>
</listitem>
</varlistentry>
</variablelist>
<bridgehead renderas="sect4" id="fiber.synchronization.conditions.h2">
<phrase id="fiber.synchronization.conditions.destructor"/><link linkend="fiber.synchronization.conditions.destructor">Destructor</link>
</bridgehead>
<programlisting><phrase role="special">~</phrase><phrase role="identifier">condition_variable</phrase><phrase role="special">()</phrase>
</programlisting>
<variablelist>
<title></title>
<varlistentry>
<term>Precondition:</term>
<listitem>
<para>
All fibers waiting on <code><phrase role="special">*</phrase><phrase
role="keyword">this</phrase></code> have been notified by a call to
<code><phrase role="identifier">notify_one</phrase></code> or <code><phrase
role="identifier">notify_all</phrase></code> (though the respective
calls to <code><phrase role="identifier">wait</phrase></code>, <code><phrase
role="identifier">wait_for</phrase></code> or <code><phrase role="identifier">wait_until</phrase></code>
need not have returned).
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Effects:</term>
<listitem>
<para>
Destroys the object.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Throws:</term>
<listitem>
<para>
Nothing.
</para>
</listitem>
</varlistentry>
</variablelist>
<para>
<bridgehead renderas="sect4" id="condition_variable_notify_one_bridgehead">
<phrase id="condition_variable_notify_one"/>
<link linkend="condition_variable_notify_one">Member
function <code>notify_one</code>()</link>
</bridgehead>
</para>
<programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">notify_one</phrase><phrase role="special">();</phrase>
</programlisting>
<variablelist>
<title></title>
<varlistentry>
<term>Effects:</term>
<listitem>
<para>
If any fibers are currently <link linkend="blocking"><emphasis>blocked</emphasis></link>
waiting on <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>
in a call to <code><phrase role="identifier">wait</phrase></code>,
<code><phrase role="identifier">wait_for</phrase></code> or <code><phrase
role="identifier">wait_until</phrase></code>, unblocks one of those
fibers.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Throws:</term>
<listitem>
<para>
Nothing.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Note:</term>
<listitem>
<para>
It is arbitrary which waiting fiber is resumed.
</para>
</listitem>
</varlistentry>
</variablelist>
<para>
<bridgehead renderas="sect4" id="condition_variable_notify_all_bridgehead">
<phrase id="condition_variable_notify_all"/>
<link linkend="condition_variable_notify_all">Member
function <code>notify_all</code>()</link>
</bridgehead>
</para>
<programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">notify_all</phrase><phrase role="special">();</phrase>
</programlisting>
<variablelist>
<title></title>
<varlistentry>
<term>Effects:</term>
<listitem>
<para>
If any fibers are currently <link linkend="blocking"><emphasis>blocked</emphasis></link>
waiting on <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>
in a call to <code><phrase role="identifier">wait</phrase></code>,
<code><phrase role="identifier">wait_for</phrase></code> or <code><phrase
role="identifier">wait_until</phrase></code>, unblocks all of those
fibers.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Throws:</term>
<listitem>
<para>
Nothing.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Note:</term>
<listitem>
<para>
This is why a waiting fiber must <emphasis>also</emphasis> check for
the desired program state using a mechanism external to the <code><phrase
role="identifier">condition_variable</phrase></code>, and retry the
wait until that state is reached. A fiber waiting on a <code><phrase
role="identifier">condition_variable</phrase></code> might well wake
up a number of times before the desired state is reached.
</para>
</listitem>
</varlistentry>
</variablelist>
<para>
<bridgehead renderas="sect4" id="condition_variable_wait_bridgehead">
<phrase id="condition_variable_wait"/>
<link linkend="condition_variable_wait">Templated
member function <code>wait</code>()</link>
</bridgehead>
</para>
<programlisting><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">LockType</phrase> <phrase role="special">&gt;</phrase>
<phrase role="keyword">void</phrase> <phrase role="identifier">wait</phrase><phrase role="special">(</phrase> <phrase role="identifier">LockType</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">lk</phrase><phrase role="special">);</phrase>
<phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">LockType</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Pred</phrase> <phrase role="special">&gt;</phrase>
<phrase role="keyword">void</phrase> <phrase role="identifier">wait</phrase><phrase role="special">(</phrase> <phrase role="identifier">LockType</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">lk</phrase><phrase role="special">,</phrase> <phrase role="identifier">Pred</phrase> <phrase role="identifier">pred</phrase><phrase role="special">);</phrase>
</programlisting>
<variablelist>
<title></title>
<varlistentry>
<term>Precondition:</term>
<listitem>
<para>
<code><phrase role="identifier">lk</phrase></code> is locked by the
current fiber, and either no other fiber is currently waiting on <code><phrase
role="special">*</phrase><phrase role="keyword">this</phrase></code>,
or the execution of the <code><phrase role="identifier">mutex</phrase><phrase
role="special">()</phrase></code> member function on the <code><phrase
role="identifier">lk</phrase></code> objects supplied in the calls
to <code><phrase role="identifier">wait</phrase></code> in all the
fibers currently waiting on <code><phrase role="special">*</phrase><phrase
role="keyword">this</phrase></code> would return the same value as
<code><phrase role="identifier">lk</phrase><phrase role="special">-&gt;</phrase><phrase
role="identifier">mutex</phrase><phrase role="special">()</phrase></code>
for this call to <code><phrase role="identifier">wait</phrase></code>.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Effects:</term>
<listitem>
<para>
Atomically call <code><phrase role="identifier">lk</phrase><phrase
role="special">.</phrase><phrase role="identifier">unlock</phrase><phrase
role="special">()</phrase></code> and blocks the current fiber. The
fiber will unblock when notified by a call to <code><phrase role="keyword">this</phrase><phrase
role="special">-&gt;</phrase><phrase role="identifier">notify_one</phrase><phrase
role="special">()</phrase></code> or <code><phrase role="keyword">this</phrase><phrase
role="special">-&gt;</phrase><phrase role="identifier">notify_all</phrase><phrase
role="special">()</phrase></code>, or spuriously. When the fiber is
unblocked (for whatever reason), the lock is reacquired by invoking
<code><phrase role="identifier">lk</phrase><phrase role="special">.</phrase><phrase
role="identifier">lock</phrase><phrase role="special">()</phrase></code>
before the call to <code><phrase role="identifier">wait</phrase></code>
returns. The lock is also reacquired by invoking <code><phrase role="identifier">lk</phrase><phrase
role="special">.</phrase><phrase role="identifier">lock</phrase><phrase
role="special">()</phrase></code> if the function exits with an exception.
The member function accepting <code><phrase role="identifier">pred</phrase></code>
is shorthand for:
<programlisting><phrase role="keyword">while</phrase> <phrase role="special">(</phrase> <phrase role="special">!</phrase> <phrase role="identifier">pred</phrase><phrase role="special">()</phrase> <phrase role="special">)</phrase> <phrase role="special">{</phrase>
<phrase role="identifier">wait</phrase><phrase role="special">(</phrase> <phrase role="identifier">lk</phrase><phrase role="special">);</phrase>
<phrase role="special">}</phrase>
</programlisting>
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Postcondition:</term>
<listitem>
<para>
<code><phrase role="identifier">lk</phrase></code> is locked by the
current fiber.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Throws:</term>
<listitem>
<para>
<code><phrase role="identifier">fiber_exception</phrase></code> if
an error occurs. <code><phrase role="identifier">fiber_interrupted</phrase></code>
if the wait was interrupted by a call to <link linkend="fiber_interrupt"> <code>fiber::interrupt()</code></link> on
the <link linkend="class_fiber"> <code>fiber</code></link> object associated with the current fiber of execution.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Note:</term>
<listitem>
<para>
The Precondition is a bit dense. It merely states that all the fibers
calling <code><phrase role="identifier">wait</phrase></code> on <code><phrase
role="special">*</phrase><phrase role="keyword">this</phrase></code>
must wait on <code><phrase role="identifier">lk</phrase></code> objects
governing the <emphasis>same</emphasis> <code><phrase role="identifier">mutex</phrase></code>.
Three distinct objects are involved in any <code><phrase role="identifier">condition_variable</phrase><phrase
role="special">::</phrase><phrase role="identifier">wait</phrase><phrase
role="special">()</phrase></code> call: the <code><phrase role="identifier">condition_variable</phrase></code>
itself, the <code><phrase role="identifier">mutex</phrase></code> coordinating
access between fibers and a lock object (e.g. <code><phrase role="identifier">std</phrase><phrase
role="special">::</phrase><phrase role="identifier">unique_lock</phrase></code>).
In some sense it would be nice if the <code><phrase role="identifier">condition_variable</phrase></code>'s
constructor could accept the related <code><phrase role="identifier">mutex</phrase></code>
object, enforcing agreement across all <code><phrase role="identifier">wait</phrase><phrase
role="special">()</phrase></code> calls; but the existing APIs prevent
that. Instead we must require the <code><phrase role="identifier">wait</phrase><phrase
role="special">()</phrase></code> call to accept a reference to the
local lock object. It is an error to reuse a given <code><phrase role="identifier">condition_variable</phrase></code>
instance with lock objects that reference <emphasis>different</emphasis>
underlying <code><phrase role="identifier">mutex</phrase></code> objects.
It would be like a road intersection with traffic lights independent
of one another: sooner or later a collision will result.
</para>
</listitem>
</varlistentry>
</variablelist>
<para>
<bridgehead renderas="sect4" id="condition_variable_wait_until_bridgehead">
<phrase id="condition_variable_wait_until"/>
<link linkend="condition_variable_wait_until">Templated
member function <code>wait_until</code>()</link>
</bridgehead>
</para>
<programlisting><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">LockType</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Clock</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Duration</phrase> <phrase role="special">&gt;</phrase>
<phrase role="identifier">cv_status</phrase> <phrase role="identifier">wait_until</phrase><phrase role="special">(</phrase> <phrase role="identifier">LockType</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">lk</phrase><phrase role="special">,</phrase>
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">time_point</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Clock</phrase><phrase role="special">,</phrase> <phrase role="identifier">Duration</phrase> <phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">timeout_time</phrase><phrase role="special">);</phrase>
<phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">LockType</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Clock</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Duration</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Pred</phrase> <phrase role="special">&gt;</phrase>
<phrase role="keyword">bool</phrase> <phrase role="identifier">wait_until</phrase><phrase role="special">(</phrase> <phrase role="identifier">LockType</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">lk</phrase><phrase role="special">,</phrase>
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">time_point</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Clock</phrase><phrase role="special">,</phrase> <phrase role="identifier">Duration</phrase> <phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">timeout_time</phrase><phrase role="special">,</phrase>
<phrase role="identifier">Pred</phrase> <phrase role="identifier">pred</phrase><phrase role="special">);</phrase>
</programlisting>
<variablelist>
<title></title>
<varlistentry>
<term>Precondition:</term>
<listitem>
<para>
<code><phrase role="identifier">lk</phrase></code> is locked by the
current fiber, and either no other fiber is currently waiting on <code><phrase
role="special">*</phrase><phrase role="keyword">this</phrase></code>,
or the execution of the <code><phrase role="identifier">mutex</phrase><phrase
role="special">()</phrase></code> member function on the <code><phrase
role="identifier">lk</phrase></code> objects supplied in the calls
to <code><phrase role="identifier">wait</phrase></code>, <code><phrase
role="identifier">wait_for</phrase></code> or <code><phrase role="identifier">wait_until</phrase></code>
in all the fibers currently waiting on <code><phrase role="special">*</phrase><phrase
role="keyword">this</phrase></code> would return the same value as
<code><phrase role="identifier">lk</phrase><phrase role="special">.</phrase><phrase
role="identifier">mutex</phrase><phrase role="special">()</phrase></code>
for this call to <code><phrase role="identifier">wait_until</phrase></code>.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Effects:</term>
<listitem>
<para>
Atomically call <code><phrase role="identifier">lk</phrase><phrase
role="special">.</phrase><phrase role="identifier">unlock</phrase><phrase
role="special">()</phrase></code> and blocks the current fiber. The
fiber will unblock when notified by a call to <code><phrase role="keyword">this</phrase><phrase
role="special">-&gt;</phrase><phrase role="identifier">notify_one</phrase><phrase
role="special">()</phrase></code> or <code><phrase role="keyword">this</phrase><phrase
role="special">-&gt;</phrase><phrase role="identifier">notify_all</phrase><phrase
role="special">()</phrase></code>, when the system time would be equal
to or later than the specified <code><phrase role="identifier">timeout_time</phrase></code>,
or spuriously. When the fiber is unblocked (for whatever reason), the
lock is reacquired by invoking <code><phrase role="identifier">lk</phrase><phrase
role="special">.</phrase><phrase role="identifier">lock</phrase><phrase
role="special">()</phrase></code> before the call to <code><phrase
role="identifier">wait_until</phrase></code> returns. The lock is also
reacquired by invoking <code><phrase role="identifier">lk</phrase><phrase
role="special">.</phrase><phrase role="identifier">lock</phrase><phrase
role="special">()</phrase></code> if the function exits with an exception.
The member function accepting <code><phrase role="identifier">pred</phrase></code>
is shorthand for:
<programlisting><phrase role="keyword">while</phrase> <phrase role="special">(</phrase> <phrase role="special">!</phrase> <phrase role="identifier">pred</phrase><phrase role="special">()</phrase> <phrase role="special">)</phrase> <phrase role="special">{</phrase>
<phrase role="keyword">if</phrase> <phrase role="special">(</phrase> <phrase role="identifier">cv_status</phrase><phrase role="special">::</phrase><phrase role="identifier">timeout</phrase> <phrase role="special">==</phrase> <phrase role="identifier">wait_until</phrase><phrase role="special">(</phrase> <phrase role="identifier">lk</phrase><phrase role="special">,</phrase> <phrase role="identifier">timeout_time</phrase><phrase role="special">)</phrase> <phrase role="special">)</phrase>
<phrase role="keyword">return</phrase> <phrase role="identifier">pred</phrase><phrase role="special">();</phrase>
<phrase role="special">}</phrase>
<phrase role="keyword">return</phrase> <phrase role="keyword">true</phrase><phrase role="special">;</phrase>
</programlisting>
That is, even if <code><phrase role="identifier">wait_until</phrase><phrase
role="special">()</phrase></code> times out, it can still return <code><phrase
role="keyword">true</phrase></code> if <code><phrase role="identifier">pred</phrase><phrase
role="special">()</phrase></code> returns <code><phrase role="keyword">true</phrase></code>
at that time.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Postcondition:</term>
<listitem>
<para>
<code><phrase role="identifier">lk</phrase></code> is locked by the
current fiber.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Throws:</term>
<listitem>
<para>
<code><phrase role="identifier">fiber_exception</phrase></code> if
an error occurs. <code><phrase role="identifier">fiber_interrupted</phrase></code>
if the wait was interrupted by a call to <link linkend="fiber_interrupt"> <code>fiber::interrupt()</code></link> on
the <link linkend="class_fiber"> <code>fiber</code></link> object associated with the current fiber of execution.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Returns:</term>
<listitem>
<para>
The overload without <code><phrase role="identifier">pred</phrase></code>
returns <code><phrase role="identifier">cv_status</phrase><phrase role="special">::</phrase><phrase
role="identifier">no_timeout</phrase></code> if awakened by <code><phrase
role="identifier">notify_one</phrase><phrase role="special">()</phrase></code>
or <code><phrase role="identifier">notify_all</phrase><phrase role="special">()</phrase></code>,
or <code><phrase role="identifier">cv_status</phrase><phrase role="special">::</phrase><phrase
role="identifier">timeout</phrase></code> if awakened because the system
time is past <code><phrase role="identifier">timeout_time</phrase></code>.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Returns:</term>
<listitem>
<para>
The overload accepting <code><phrase role="identifier">pred</phrase></code>
returns <code><phrase role="keyword">false</phrase></code> if the call
is returning because the time specified by <code><phrase role="identifier">timeout_time</phrase></code>
was reached and the predicate returns <code><phrase role="keyword">false</phrase></code>,
<code><phrase role="keyword">true</phrase></code> otherwise.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Note:</term>
<listitem>
<para>
See <emphasis role="bold">Note</emphasis> for <link linkend="condition_variable_wait"> <code>condition_variable::wait()</code></link>.
</para>
</listitem>
</varlistentry>
</variablelist>
<para>
<bridgehead renderas="sect4" id="condition_variable_wait_for_bridgehead">
<phrase id="condition_variable_wait_for"/>
<link linkend="condition_variable_wait_for">Templated
member function <code>wait_for</code>()</link>
</bridgehead>
</para>
<programlisting><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">LockType</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Rep</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Period</phrase> <phrase role="special">&gt;</phrase>
<phrase role="identifier">cv_status</phrase> <phrase role="identifier">wait_for</phrase><phrase role="special">(</phrase> <phrase role="identifier">LockType</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">lk</phrase><phrase role="special">,</phrase>
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">duration</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Rep</phrase><phrase role="special">,</phrase> <phrase role="identifier">Period</phrase> <phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">timeout_duration</phrase><phrase role="special">);</phrase>
<phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">LockType</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Rep</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Period</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Pred</phrase> <phrase role="special">&gt;</phrase>
<phrase role="keyword">bool</phrase> <phrase role="identifier">wait_for</phrase><phrase role="special">(</phrase> <phrase role="identifier">LockType</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">lk</phrase><phrase role="special">,</phrase>
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">duration</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Rep</phrase><phrase role="special">,</phrase> <phrase role="identifier">Period</phrase> <phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">timeout_duration</phrase><phrase role="special">,</phrase>
<phrase role="identifier">Pred</phrase> <phrase role="identifier">pred</phrase><phrase role="special">);</phrase>
</programlisting>
<variablelist>
<title></title>
<varlistentry>
<term>Precondition:</term>
<listitem>
<para>
<code><phrase role="identifier">lk</phrase></code> is locked by the
current fiber, and either no other fiber is currently waiting on <code><phrase
role="special">*</phrase><phrase role="keyword">this</phrase></code>,
or the execution of the <code><phrase role="identifier">mutex</phrase><phrase
role="special">()</phrase></code> member function on the <code><phrase
role="identifier">lk</phrase></code> objects supplied in the calls
to <code><phrase role="identifier">wait</phrase></code>, <code><phrase
role="identifier">wait_for</phrase></code> or <code><phrase role="identifier">wait_until</phrase></code>
in all the fibers currently waiting on <code><phrase role="special">*</phrase><phrase
role="keyword">this</phrase></code> would return the same value as
<code><phrase role="identifier">lk</phrase><phrase role="special">.</phrase><phrase
role="identifier">mutex</phrase><phrase role="special">()</phrase></code>
for this call to <code><phrase role="identifier">wait_for</phrase></code>.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Effects:</term>
<listitem>
<para>
Atomically call <code><phrase role="identifier">lk</phrase><phrase
role="special">.</phrase><phrase role="identifier">unlock</phrase><phrase
role="special">()</phrase></code> and blocks the current fiber. The
fiber will unblock when notified by a call to <code><phrase role="keyword">this</phrase><phrase
role="special">-&gt;</phrase><phrase role="identifier">notify_one</phrase><phrase
role="special">()</phrase></code> or <code><phrase role="keyword">this</phrase><phrase
role="special">-&gt;</phrase><phrase role="identifier">notify_all</phrase><phrase
role="special">()</phrase></code>, when a time interval equal to or
greater than the specified <code><phrase role="identifier">timeout_duration</phrase></code>
has elapsed, or spuriously. When the fiber is unblocked (for whatever
reason), the lock is reacquired by invoking <code><phrase role="identifier">lk</phrase><phrase
role="special">.</phrase><phrase role="identifier">lock</phrase><phrase
role="special">()</phrase></code> before the call to <code><phrase
role="identifier">wait</phrase></code> returns. The lock is also reacquired
by invoking <code><phrase role="identifier">lk</phrase><phrase role="special">.</phrase><phrase
role="identifier">lock</phrase><phrase role="special">()</phrase></code>
if the function exits with an exception. The <code><phrase role="identifier">wait_for</phrase><phrase
role="special">()</phrase></code> member function accepting <code><phrase
role="identifier">pred</phrase></code> is shorthand for:
<programlisting><phrase role="keyword">while</phrase> <phrase role="special">(</phrase> <phrase role="special">!</phrase> <phrase role="identifier">pred</phrase><phrase role="special">()</phrase> <phrase role="special">)</phrase> <phrase role="special">{</phrase>
<phrase role="keyword">if</phrase> <phrase role="special">(</phrase> <phrase role="identifier">cv_status</phrase><phrase role="special">::</phrase><phrase role="identifier">timeout</phrase> <phrase role="special">==</phrase> <phrase role="identifier">wait_for</phrase><phrase role="special">(</phrase> <phrase role="identifier">lk</phrase><phrase role="special">,</phrase> <phrase role="identifier">timeout_duration</phrase><phrase role="special">)</phrase> <phrase role="special">)</phrase> <phrase role="special">{</phrase>
<phrase role="keyword">return</phrase> <phrase role="identifier">pred</phrase><phrase role="special">();</phrase>
<phrase role="special">}</phrase>
<phrase role="special">}</phrase>
<phrase role="keyword">return</phrase> <phrase role="keyword">true</phrase><phrase role="special">;</phrase>
</programlisting>
(except of course that <code><phrase role="identifier">timeout_duration</phrase></code>
is adjusted for each iteration). The point is that, even if <code><phrase
role="identifier">wait_for</phrase><phrase role="special">()</phrase></code>
times out, it can still return <code><phrase role="keyword">true</phrase></code>
if <code><phrase role="identifier">pred</phrase><phrase role="special">()</phrase></code>
returns <code><phrase role="keyword">true</phrase></code> at that time.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Postcondition:</term>
<listitem>
<para>
<code><phrase role="identifier">lk</phrase></code> is locked by the
current fiber.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Throws:</term>
<listitem>
<para>
<code><phrase role="identifier">fiber_exception</phrase></code> if
an error occurs. <code><phrase role="identifier">fiber_interrupted</phrase></code>
if the wait was interrupted by a call to <link linkend="fiber_interrupt"> <code>fiber::interrupt()</code></link> on
the <link linkend="class_fiber"> <code>fiber</code></link> object associated with the current fiber of execution.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Returns:</term>
<listitem>
<para>
The overload without <code><phrase role="identifier">pred</phrase></code>
returns <code><phrase role="identifier">cv_status</phrase><phrase role="special">::</phrase><phrase
role="identifier">no_timeout</phrase></code> if awakened by <code><phrase
role="identifier">notify_one</phrase><phrase role="special">()</phrase></code>
or <code><phrase role="identifier">notify_all</phrase><phrase role="special">()</phrase></code>,
or <code><phrase role="identifier">cv_status</phrase><phrase role="special">::</phrase><phrase
role="identifier">timeout</phrase></code> if awakened because at least
<code><phrase role="identifier">timeout_duration</phrase></code> has
elapsed.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Returns:</term>
<listitem>
<para>
The overload accepting <code><phrase role="identifier">pred</phrase></code>
returns <code><phrase role="keyword">false</phrase></code> if the call
is returning because at least <code><phrase role="identifier">timeout_duration</phrase></code>
has elapsed and the predicate returns <code><phrase role="keyword">false</phrase></code>,
<code><phrase role="keyword">true</phrase></code> otherwise.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Note:</term>
<listitem>
<para>
See <emphasis role="bold">Note</emphasis> for <link linkend="condition_variable_wait"> <code>condition_variable::wait()</code></link>.
</para>
</listitem>
</varlistentry>
</variablelist>
</section>
<section id="fiber.synchronization.barriers">
<title><link linkend="fiber.synchronization.barriers">Barriers</link></title>
<para>
A barrier is a concept also known as a <emphasis>rendezvous</emphasis>, it
is a synchronization point between multiple contexts of execution (fibers).
The barrier is configured for a particular number of fibers (<code><phrase
role="identifier">n</phrase></code>), and as fibers reach the barrier they
must wait until all <code><phrase role="identifier">n</phrase></code> fibers
have arrived. Once the <code><phrase role="identifier">n</phrase></code>-th
fiber has reached the barrier, all the waiting fibers can proceed, and the
barrier is reset.
</para>
<para>
The fact that the barrier automatically resets is significant. Consider a
case in which you launch some number of fibers and want to wait only until
the first of them has completed. You might be tempted to use a <code><phrase
role="identifier">barrier</phrase><phrase role="special">(</phrase><phrase
role="number">2</phrase><phrase role="special">)</phrase></code> as the synchronization
mechanism, making each new fiber call its <link linkend="barrier_wait"> <code>barrier::wait()</code></link> method,
then calling <code><phrase role="identifier">wait</phrase><phrase role="special">()</phrase></code>
in the launching fiber to wait until the first other fiber completes.
</para>
<para>
That will in fact unblock the launching fiber. The unfortunate part is that
it will continue blocking the <emphasis>remaining</emphasis> fibers.
</para>
<para>
Consider the following scenario:
</para>
<orderedlist>
<listitem>
<simpara>
Fiber &quot;main&quot; launches fibers A, B, C and D, then calls <code><phrase
role="identifier">barrier</phrase><phrase role="special">::</phrase><phrase
role="identifier">wait</phrase><phrase role="special">()</phrase></code>.
</simpara>
</listitem>
<listitem>
<simpara>
Fiber C finishes first and likewise calls <code><phrase role="identifier">barrier</phrase><phrase
role="special">::</phrase><phrase role="identifier">wait</phrase><phrase
role="special">()</phrase></code>.
</simpara>
</listitem>
<listitem>
<simpara>
Fiber &quot;main&quot; is unblocked, as desired.
</simpara>
</listitem>
<listitem>
<simpara>
Fiber B calls <code><phrase role="identifier">barrier</phrase><phrase
role="special">::</phrase><phrase role="identifier">wait</phrase><phrase
role="special">()</phrase></code>. Fiber B is <emphasis>blocked!</emphasis>
</simpara>
</listitem>
<listitem>
<simpara>
Fiber A calls <code><phrase role="identifier">barrier</phrase><phrase
role="special">::</phrase><phrase role="identifier">wait</phrase><phrase
role="special">()</phrase></code>. Fibers A and B are unblocked.
</simpara>
</listitem>
<listitem>
<simpara>
Fiber D calls <code><phrase role="identifier">barrier</phrase><phrase
role="special">::</phrase><phrase role="identifier">wait</phrase><phrase
role="special">()</phrase></code>. Fiber D is blocked indefinitely.
</simpara>
</listitem>
</orderedlist>
<para>
(See also <link linkend="wait_first_simple_section">when_any, simple completion</link>.)
</para>
<note>
<para>
It is unwise to tie the lifespan of a barrier to any one of its participating
fibers. Although conceptually all waiting fibers awaken &quot;simultaneously,&quot;
because of the nature of fibers, in practice they will awaken one by one
in indeterminate order.<footnote id="fiber.synchronization.barriers.f0">
<para>
The current implementation wakes fibers in FIFO order: the first to call
<code><phrase role="identifier">wait</phrase><phrase role="special">()</phrase></code>
wakes first, and so forth. But it is perilous to rely on the order in
which the various fibers will reach the <code><phrase role="identifier">wait</phrase><phrase
role="special">()</phrase></code> call.
</para>
</footnote> The rest of the waiting fibers will still be blocked in <code><phrase
role="identifier">wait</phrase><phrase role="special">()</phrase></code>,
which must, before returning, access data members in the barrier object.
</para>
</note>
<para>
<bridgehead renderas="sect4" id="class_barrier_bridgehead">
<phrase id="class_barrier"/>
<link linkend="class_barrier">Class <code>barrier</code></link>
</bridgehead>
</para>
<programlisting><phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">fiber</phrase><phrase role="special">/</phrase><phrase role="identifier">barrier</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase>
<phrase role="keyword">class</phrase> <phrase role="identifier">barrier</phrase> <phrase role="special">{</phrase>
<phrase role="keyword">public</phrase><phrase role="special">:</phrase>
<phrase role="identifier">barrier</phrase><phrase role="special">(</phrase> <phrase role="keyword">unsigned</phrase> <phrase role="keyword">int</phrase> <phrase role="identifier">initial</phrase><phrase role="special">);</phrase>
<phrase role="identifier">barrier</phrase><phrase role="special">(</phrase> <phrase role="identifier">barrier</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="special">=</phrase> <phrase role="keyword">delete</phrase><phrase role="special">;</phrase>
<phrase role="identifier">barrier</phrase> <phrase role="special">&amp;</phrase> <phrase role="keyword">operator</phrase><phrase role="special">=(</phrase> <phrase role="identifier">barrier</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="special">=</phrase> <phrase role="keyword">delete</phrase><phrase role="special">;</phrase>
<phrase role="keyword">bool</phrase> <phrase role="identifier">wait</phrase><phrase role="special">();</phrase>
<phrase role="special">};</phrase>
</programlisting>
<para>
Instances of <link linkend="class_barrier"> <code>barrier</code></link> are not copyable or movable.
</para>
<bridgehead renderas="sect4" id="fiber.synchronization.barriers.h0">
<phrase id="fiber.synchronization.barriers.constructor"/><link linkend="fiber.synchronization.barriers.constructor">Constructor</link>
</bridgehead>
<programlisting><phrase role="identifier">barrier</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">initial</phrase><phrase role="special">);</phrase>
</programlisting>
<variablelist>
<title></title>
<varlistentry>
<term>Effects:</term>
<listitem>
<para>
Construct a barrier for <code><phrase role="identifier">initial</phrase></code>
fibers.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Throws:</term>
<listitem>
<para>
<code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase
role="identifier">invalid_argument</phrase></code> if <code><phrase
role="identifier">initial</phrase></code> is zero
</para>
</listitem>
</varlistentry>
</variablelist>
<para>
<bridgehead renderas="sect4" id="barrier_wait_bridgehead">
<phrase id="barrier_wait"/>
<link linkend="barrier_wait">Member function <code>wait</code>()</link>
</bridgehead>
</para>
<programlisting><phrase role="keyword">bool</phrase> <phrase role="identifier">wait</phrase><phrase role="special">();</phrase>
</programlisting>
<variablelist>
<title></title>
<varlistentry>
<term>Effects:</term>
<listitem>
<para>
Block until <code><phrase role="identifier">initial</phrase></code>
fibers have called <code><phrase role="identifier">wait</phrase></code>
on <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>.
When the <code><phrase role="identifier">initial</phrase></code>-th
fiber calls <code><phrase role="identifier">wait</phrase></code>, all
waiting fibers are unblocked, and the barrier is reset.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Returns:</term>
<listitem>
<para>
<code><phrase role="keyword">true</phrase></code> for exactly one fiber
from each batch of waiting fibers, <code><phrase role="keyword">false</phrase></code>
otherwise.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Throws:</term>
<listitem>
<para>
<code><phrase role="identifier">fiber_exception</phrase></code>
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Notes:</term>
<listitem>
<para>
<code><phrase role="identifier">wait</phrase><phrase role="special">()</phrase></code>
is one of the predefined <link linkend="interruption"><emphasis>interruption-points</emphasis></link>.
</para>
</listitem>
</varlistentry>
</variablelist>
</section>
<section id="fiber.synchronization.channels">
<title><link linkend="fiber.synchronization.channels">Channels</link></title>
<para>
<emphasis role="bold">Boost.Fiber</emphasis> provides a bounded and a unbounded
channel suitable to synchonize fibers via message passing.
</para>
<programlisting><phrase role="keyword">typedef</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">unbounded_channel</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">int</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">channel_t</phrase><phrase role="special">;</phrase>
<phrase role="keyword">void</phrase> <phrase role="identifier">send</phrase><phrase role="special">(</phrase> <phrase role="identifier">channel_t</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">channel</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="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="identifier">channel</phrase><phrase role="special">.</phrase><phrase role="identifier">push</phrase><phrase role="special">(</phrase> <phrase role="identifier">i</phrase><phrase role="special">);</phrase>
<phrase role="special">}</phrase>
<phrase role="identifier">channel</phrase><phrase role="special">.</phrase><phrase role="identifier">close</phrase><phrase role="special">();</phrase>
<phrase role="special">}</phrase>
<phrase role="keyword">void</phrase> <phrase role="identifier">recv</phrase><phrase role="special">(</phrase> <phrase role="identifier">channel_t</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">channel</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="keyword">while</phrase> <phrase role="special">(</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">channel_op_status</phrase><phrase role="special">::</phrase><phrase role="identifier">success</phrase> <phrase role="special">==</phrase> <phrase role="identifier">channel</phrase><phrase role="special">.</phrase><phrase role="identifier">pop</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="string">&quot;received &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="special">}</phrase>
<phrase role="special">}</phrase>
<phrase role="identifier">channel_t</phrase> <phrase role="identifier">channel</phrase><phrase role="special">;</phrase>
<phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">fiber</phrase> <phrase role="identifier">f1</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">bind</phrase><phrase role="special">(</phrase> <phrase role="identifier">send</phrase><phrase role="special">,</phrase> <phrase role="identifier">ref</phrase><phrase role="special">(</phrase> <phrase role="identifier">channel</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">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">fiber</phrase> <phrase role="identifier">f2</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">bind</phrase><phrase role="special">(</phrase> <phrase role="identifier">recv</phrase><phrase role="special">,</phrase> <phrase role="identifier">ref</phrase><phrase role="special">(</phrase> <phrase role="identifier">channel</phrase><phrase role="special">)</phrase> <phrase role="special">)</phrase> <phrase role="special">);</phrase>
<phrase role="identifier">f1</phrase><phrase role="special">.</phrase><phrase role="identifier">join</phrase><phrase role="special">();</phrase>
<phrase role="identifier">f2</phrase><phrase role="special">.</phrase><phrase role="identifier">join</phrase><phrase role="special">();</phrase>
</programlisting>
<anchor id="class_channel_op_status"/>
<bridgehead renderas="sect4" id="fiber.synchronization.channels.h0">
<phrase id="fiber.synchronization.channels.enumeration__code__phrase_role__identifier__channel_op_status__phrase___code_"/><link
linkend="fiber.synchronization.channels.enumeration__code__phrase_role__identifier__channel_op_status__phrase___code_">Enumeration
<code><phrase role="identifier">channel_op_status</phrase></code></link>
</bridgehead>
<para>
channel operations return the state of the channel.
</para>
<programlisting><phrase role="keyword">enum</phrase> <phrase role="keyword">class</phrase> <phrase role="identifier">channel_op_status</phrase> <phrase role="special">{</phrase>
<phrase role="identifier">success</phrase><phrase role="special">,</phrase>
<phrase role="identifier">empty</phrase><phrase role="special">,</phrase>
<phrase role="identifier">full</phrase><phrase role="special">,</phrase>
<phrase role="identifier">closed</phrase><phrase role="special">,</phrase>
<phrase role="identifier">timeout</phrase>
<phrase role="special">};</phrase>
</programlisting>
<bridgehead renderas="sect4" id="fiber.synchronization.channels.h1">
<phrase id="fiber.synchronization.channels._code__phrase_role__identifier__success__phrase___code_"/><link
linkend="fiber.synchronization.channels._code__phrase_role__identifier__success__phrase___code_"><code><phrase
role="identifier">success</phrase></code></link>
</bridgehead>
<variablelist>
<title></title>
<varlistentry>
<term>Effects:</term>
<listitem>
<para>
Operation was successful.
</para>
</listitem>
</varlistentry>
</variablelist>
<bridgehead renderas="sect4" id="fiber.synchronization.channels.h2">
<phrase id="fiber.synchronization.channels._code__phrase_role__identifier__empty__phrase___code_"/><link
linkend="fiber.synchronization.channels._code__phrase_role__identifier__empty__phrase___code_"><code><phrase
role="identifier">empty</phrase></code></link>
</bridgehead>
<variablelist>
<title></title>
<varlistentry>
<term>Effects:</term>
<listitem>
<para>
channel is empty, operation failed.
</para>
</listitem>
</varlistentry>
</variablelist>
<bridgehead renderas="sect4" id="fiber.synchronization.channels.h3">
<phrase id="fiber.synchronization.channels._code__phrase_role__identifier__full__phrase___code_"/><link
linkend="fiber.synchronization.channels._code__phrase_role__identifier__full__phrase___code_"><code><phrase
role="identifier">full</phrase></code></link>
</bridgehead>
<variablelist>
<title></title>
<varlistentry>
<term>Effects:</term>
<listitem>
<para>
channel is full, operation failed.
</para>
</listitem>
</varlistentry>
</variablelist>
<bridgehead renderas="sect4" id="fiber.synchronization.channels.h4">
<phrase id="fiber.synchronization.channels._code__phrase_role__identifier__closed__phrase___code_"/><link
linkend="fiber.synchronization.channels._code__phrase_role__identifier__closed__phrase___code_"><code><phrase
role="identifier">closed</phrase></code></link>
</bridgehead>
<variablelist>
<title></title>
<varlistentry>
<term>Effects:</term>
<listitem>
<para>
channel is closed, operation failed.
</para>
</listitem>
</varlistentry>
</variablelist>
<bridgehead renderas="sect4" id="fiber.synchronization.channels.h5">
<phrase id="fiber.synchronization.channels._code__phrase_role__identifier__timeout__phrase___code_"/><link
linkend="fiber.synchronization.channels._code__phrase_role__identifier__timeout__phrase___code_"><code><phrase
role="identifier">timeout</phrase></code></link>
</bridgehead>
<variablelist>
<title></title>
<varlistentry>
<term>Effects:</term>
<listitem>
<para>
The operation did not become ready before specified timeout elapsed.
</para>
</listitem>
</varlistentry>
</variablelist>
<para>
<bridgehead renderas="sect4" id="class_unbounded_channel_bridgehead">
<phrase id="class_unbounded_channel"/>
<link linkend="class_unbounded_channel">Template
<code>unbounded_channel&lt;&gt;</code></link>
</bridgehead>
</para>
<programlisting><phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">fiber</phrase><phrase role="special">/</phrase><phrase role="identifier">unbounded_channel</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase>
<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">unbounded_channel</phrase> <phrase role="special">{</phrase>
<phrase role="keyword">public</phrase><phrase role="special">:</phrase>
<phrase role="keyword">typedef</phrase> <phrase role="identifier">T</phrase> <phrase role="identifier">value_type</phrase><phrase role="special">;</phrase>
<phrase role="identifier">unbounded_channel</phrase><phrase role="special">(</phrase> <phrase role="identifier">unbounded_channel</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="special">=</phrase> <phrase role="keyword">delete</phrase><phrase role="special">;</phrase>
<phrase role="identifier">unbounded_channel</phrase> <phrase role="special">&amp;</phrase> <phrase role="keyword">operator</phrase><phrase role="special">=(</phrase> <phrase role="identifier">unbounded_channel</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="special">=</phrase> <phrase role="keyword">delete</phrase><phrase role="special">;</phrase>
<phrase role="keyword">void</phrase> <phrase role="identifier">close</phrase><phrase role="special">();</phrase>
<phrase role="identifier">channel_op_status</phrase> <phrase role="identifier">push</phrase><phrase role="special">(</phrase> <phrase role="identifier">value_type</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">va</phrase><phrase role="special">);</phrase>
<phrase role="identifier">channel_op_status</phrase> <phrase role="identifier">push</phrase><phrase role="special">(</phrase> <phrase role="identifier">value_type</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="identifier">va</phrase><phrase role="special">);</phrase>
<phrase role="identifier">channel_op_status</phrase> <phrase role="identifier">pop</phrase><phrase role="special">(</phrase> <phrase role="identifier">value_type</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">va</phrase><phrase role="special">);</phrase>
<phrase role="identifier">value_type</phrase> <phrase role="identifier">value_pop</phrase><phrase role="special">();</phrase>
<phrase role="identifier">channel_op_status</phrase> <phrase role="identifier">try_pop</phrase><phrase role="special">(</phrase> <phrase role="identifier">value_type</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">va</phrase><phrase role="special">);</phrase>
<phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Rep</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Period</phrase> <phrase role="special">&gt;</phrase>
<phrase role="identifier">channel_op_status</phrase> <phrase role="identifier">pop_wait_for</phrase><phrase role="special">(</phrase>
<phrase role="identifier">value_type</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">va</phrase><phrase role="special">,</phrase>
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">duration</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Rep</phrase><phrase role="special">,</phrase> <phrase role="identifier">Period</phrase> <phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">timeout_duration</phrase><phrase role="special">);</phrase>
<phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Clock</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Duration</phrase> <phrase role="special">&gt;</phrase>
<phrase role="identifier">channel_op_status</phrase> <phrase role="identifier">pop_wait_until</phrase><phrase role="special">(</phrase>
<phrase role="identifier">value_type</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">va</phrase><phrase role="special">,</phrase>
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">time_point</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Clock</phrase><phrase role="special">,</phrase> <phrase role="identifier">Duration</phrase> <phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">timeout_time</phrase><phrase role="special">);</phrase>
<phrase role="special">};</phrase>
</programlisting>
<para>
<bridgehead renderas="sect4" id="unbounded_channel_close_bridgehead">
<phrase id="unbounded_channel_close"/>
<link linkend="unbounded_channel_close">Member
function <code>close</code>()</link>
</bridgehead>
</para>
<programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">close</phrase><phrase role="special">();</phrase>
</programlisting>
<variablelist>
<title></title>
<varlistentry>
<term>Effects:</term>
<listitem>
<para>
Deactivates the channel. No values can be put after calling <code><phrase
role="keyword">this</phrase><phrase role="special">-&gt;</phrase><phrase
role="identifier">close</phrase><phrase role="special">()</phrase></code>.
Fibers blocked in <code><phrase role="keyword">this</phrase><phrase
role="special">-&gt;</phrase><phrase role="identifier">pop</phrase><phrase
role="special">()</phrase></code>, <code><phrase role="keyword">this</phrase><phrase
role="special">-&gt;</phrase><phrase role="identifier">pop_wait_for</phrase><phrase
role="special">()</phrase></code> or <code><phrase role="keyword">this</phrase><phrase
role="special">-&gt;</phrase><phrase role="identifier">pop_wait_until</phrase><phrase
role="special">()</phrase></code> will return <code><phrase role="identifier">closed</phrase></code>.
Fibers blocked in <code><phrase role="keyword">this</phrase><phrase
role="special">-&gt;</phrase><phrase role="identifier">value_pop</phrase><phrase
role="special">()</phrase></code> will receive an exception.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Throws:</term>
<listitem>
<para>
Nothing.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Note:</term>
<listitem>
<para>
<code><phrase role="identifier">close</phrase><phrase role="special">()</phrase></code>
is like closing a pipe. It informs waiting consumers that no more values
will arrive.
</para>
</listitem>
</varlistentry>
</variablelist>
<para>
<bridgehead renderas="sect4" id="unbounded_channel_push_bridgehead">
<phrase id="unbounded_channel_push"/>
<link linkend="unbounded_channel_push">Member
function <code>push</code>()</link>
</bridgehead>
</para>
<programlisting><phrase role="identifier">channel_op_status</phrase> <phrase role="identifier">push</phrase><phrase role="special">(</phrase> <phrase role="identifier">value_type</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">va</phrase><phrase role="special">);</phrase>
<phrase role="identifier">channel_op_status</phrase> <phrase role="identifier">push</phrase><phrase role="special">(</phrase> <phrase role="identifier">value_type</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="identifier">va</phrase><phrase role="special">);</phrase>
</programlisting>
<variablelist>
<title></title>
<varlistentry>
<term>Effects:</term>
<listitem>
<para>
If channel is closed, returns <code><phrase role="identifier">closed</phrase></code>.
Otherwise enqueues the value in the channel, wakes up a fiber blocked
on <code><phrase role="keyword">this</phrase><phrase role="special">-&gt;</phrase><phrase
role="identifier">pop</phrase><phrase role="special">()</phrase></code>,
<code><phrase role="keyword">this</phrase><phrase role="special">-&gt;</phrase><phrase
role="identifier">value_pop</phrase><phrase role="special">()</phrase></code>,
<code><phrase role="keyword">this</phrase><phrase role="special">-&gt;</phrase><phrase
role="identifier">pop_wait_for</phrase><phrase role="special">()</phrase></code>
or <code><phrase role="keyword">this</phrase><phrase role="special">-&gt;</phrase><phrase
role="identifier">pop_wait_until</phrase><phrase role="special">()</phrase></code>
and returns <code><phrase role="identifier">success</phrase></code>.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Throws:</term>
<listitem>
<para>
Nothing.
</para>
</listitem>
</varlistentry>
</variablelist>
<para>
<bridgehead renderas="sect4" id="unbounded_channel_pop_bridgehead">
<phrase id="unbounded_channel_pop"/>
<link linkend="unbounded_channel_pop">Member
function <code>pop</code>()</link>
</bridgehead>
</para>
<programlisting><phrase role="identifier">channel_op_status</phrase> <phrase role="identifier">pop</phrase><phrase role="special">(</phrase> <phrase role="identifier">value_type</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">va</phrase><phrase role="special">);</phrase>
</programlisting>
<variablelist>
<title></title>
<varlistentry>
<term>Effects:</term>
<listitem>
<para>
Dequeues a value from the channel. If the channel is empty, the fiber
gets suspended until at least one new item is <code><phrase role="identifier">push</phrase><phrase
role="special">()</phrase></code>ed (return value <code><phrase role="identifier">success</phrase></code>
and <code><phrase role="identifier">va</phrase></code> contains dequeued
value) or the channel gets <code><phrase role="identifier">close</phrase><phrase
role="special">()</phrase></code>d (return value <code><phrase role="identifier">closed</phrase></code>).
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Throws:</term>
<listitem>
<para>
<code><phrase role="identifier">fiber_interrupted</phrase></code>
</para>
</listitem>
</varlistentry>
</variablelist>
<para>
<bridgehead renderas="sect4" id="unbounded_channel_value_pop_bridgehead">
<phrase id="unbounded_channel_value_pop"/>
<link linkend="unbounded_channel_value_pop">Member
function <code>value_pop</code>()</link>
</bridgehead>
</para>
<programlisting><phrase role="identifier">value_type</phrase> <phrase role="identifier">value_pop</phrase><phrase role="special">();</phrase>
</programlisting>
<variablelist>
<title></title>
<varlistentry>
<term>Effects:</term>
<listitem>
<para>
Dequeues a value from the channel. If the channel is empty, the fiber
gets suspended until at least one new item is <code><phrase role="identifier">push</phrase><phrase
role="special">()</phrase></code>ed or the channel gets <code><phrase
role="identifier">close</phrase><phrase role="special">()</phrase></code>d
(which throws an exception).
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Throws:</term>
<listitem>
<para>
<code><phrase role="identifier">logic_error</phrase></code> if <code><phrase
role="special">*</phrase><phrase role="keyword">this</phrase></code>
is closed; <code><phrase role="identifier">fiber_interrupted</phrase></code>
</para>
</listitem>
</varlistentry>
</variablelist>
<para>
<bridgehead renderas="sect4" id="unbounded_channel_try_pop_bridgehead">
<phrase id="unbounded_channel_try_pop"/>
<link linkend="unbounded_channel_try_pop">Member
function <code>try_pop</code>()</link>
</bridgehead>
</para>
<programlisting><phrase role="identifier">channel_op_status</phrase> <phrase role="identifier">try_pop</phrase><phrase role="special">(</phrase> <phrase role="identifier">value_type</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">va</phrase><phrase role="special">);</phrase>
</programlisting>
<variablelist>
<title></title>
<varlistentry>
<term>Effects:</term>
<listitem>
<para>
If channel is empty, returns <code><phrase role="identifier">empty</phrase></code>.
If channel is closed, returns <code><phrase role="identifier">closed</phrase></code>.
Otherwise it returns <code><phrase role="identifier">success</phrase></code>
and <code><phrase role="identifier">va</phrase></code> contains the
dequeued value.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Throws:</term>
<listitem>
<para>
Nothing.
</para>
</listitem>
</varlistentry>
</variablelist>
<para>
<bridgehead renderas="sect4" id="unbounded_channel_pop_wait_for_bridgehead">
<phrase id="unbounded_channel_pop_wait_for"/>
<link linkend="unbounded_channel_pop_wait_for">Member
function <code>pop_wait_for</code>()</link>
</bridgehead>
</para>
<programlisting><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Rep</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Period</phrase> <phrase role="special">&gt;</phrase>
<phrase role="identifier">channel_op_status</phrase> <phrase role="identifier">pop_wait_for</phrase><phrase role="special">(</phrase>
<phrase role="identifier">value_type</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">va</phrase><phrase role="special">,</phrase>
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">duration</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Rep</phrase><phrase role="special">,</phrase> <phrase role="identifier">Period</phrase> <phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">timeout_duration</phrase><phrase role="special">)</phrase>
</programlisting>
<variablelist>
<title></title>
<varlistentry>
<term>Effects:</term>
<listitem>
<para>
Accepts <code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase
role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase
role="identifier">duration</phrase></code> and internally computes
a timeout time as (system time + <code><phrase role="identifier">timeout_duration</phrase></code>).
If channel is not empty, immediately dequeues a value from the channel.
Otherwise the fiber gets suspended until at least one new item is
<code><phrase role="identifier">push</phrase><phrase role="special">()</phrase></code>ed
(return value <code><phrase role="identifier">success</phrase></code>
and <code><phrase role="identifier">va</phrase></code> contains dequeued
value), or the channel gets <code><phrase role="identifier">close</phrase><phrase
role="special">()</phrase></code>d (return value <code><phrase role="identifier">closed</phrase></code>),
or the system time reaches the computed timeout time (return value
<code><phrase role="identifier">timeout</phrase></code>).
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Throws:</term>
<listitem>
<para>
<code><phrase role="identifier">fiber_interrupted</phrase></code>
</para>
</listitem>
</varlistentry>
</variablelist>
<para>
<bridgehead renderas="sect4" id="unbounded_channel_pop_wait_until_bridgehead">
<phrase id="unbounded_channel_pop_wait_until"/>
<link linkend="unbounded_channel_pop_wait_until">Member
function <code>pop_wait_until</code>()</link>
</bridgehead>
</para>
<programlisting><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Clock</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Duration</phrase> <phrase role="special">&gt;</phrase>
<phrase role="identifier">channel_op_status</phrase> <phrase role="identifier">pop_wait_until</phrase><phrase role="special">(</phrase>
<phrase role="identifier">value_type</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">va</phrase><phrase role="special">,</phrase>
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">time_point</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Clock</phrase><phrase role="special">,</phrase> <phrase role="identifier">Duration</phrase> <phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">timeout_time</phrase><phrase role="special">)</phrase>
</programlisting>
<variablelist>
<title></title>
<varlistentry>
<term>Effects:</term>
<listitem>
<para>
Accepts a <code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase
role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase
role="identifier">time_point</phrase><phrase role="special">&lt;</phrase>
<phrase role="identifier">Clock</phrase><phrase role="special">,</phrase>
<phrase role="identifier">Duration</phrase> <phrase role="special">&gt;</phrase></code>.
If channel is not empty, immediately dequeues a value from the channel.
Otherwise the fiber gets suspended until at least one new item is
<code><phrase role="identifier">push</phrase><phrase role="special">()</phrase></code>ed
(return value <code><phrase role="identifier">success</phrase></code>
and <code><phrase role="identifier">va</phrase></code> contains dequeued
value), or the channel gets <code><phrase role="identifier">close</phrase><phrase
role="special">()</phrase></code>d (return value <code><phrase role="identifier">closed</phrase></code>),
or the system time reaches the passed <code><phrase role="identifier">time_point</phrase></code>
(return value <code><phrase role="identifier">timeout</phrase></code>).
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Throws:</term>
<listitem>
<para>
<code><phrase role="identifier">fiber_interrupted</phrase></code>
</para>
</listitem>
</varlistentry>
</variablelist>
<para>
<bridgehead renderas="sect4" id="class_bounded_channel_bridgehead">
<phrase id="class_bounded_channel"/>
<link linkend="class_bounded_channel">Template
<code>bounded_channel&lt;&gt;</code></link>
</bridgehead>
</para>
<programlisting><phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">fiber</phrase><phrase role="special">/</phrase><phrase role="identifier">bounded_channel</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase>
<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">bounded_channel</phrase> <phrase role="special">{</phrase>
<phrase role="keyword">public</phrase><phrase role="special">:</phrase>
<phrase role="keyword">typedef</phrase> <phrase role="identifier">T</phrase> <phrase role="identifier">value_type</phrase><phrase role="special">;</phrase>
<phrase role="identifier">bounded_channel</phrase><phrase role="special">(</phrase> <phrase role="identifier">bounded_channel</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="special">=</phrase> <phrase role="keyword">delete</phrase><phrase role="special">;</phrase>
<phrase role="identifier">bounded_channel</phrase> <phrase role="special">&amp;</phrase> <phrase role="keyword">operator</phrase><phrase role="special">=(</phrase> <phrase role="identifier">bounded_channel</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="special">=</phrase> <phrase role="keyword">delete</phrase><phrase role="special">;</phrase>
<phrase role="identifier">bounded_channel</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">wm</phrase><phrase role="special">);</phrase>
<phrase role="identifier">bounded_channel</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">hwm</phrase><phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">lwm</phrase><phrase role="special">);</phrase>
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">upper_bound</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">lower_bound</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
<phrase role="keyword">void</phrase> <phrase role="identifier">close</phrase><phrase role="special">();</phrase>
<phrase role="identifier">channel_op_status</phrase> <phrase role="identifier">push</phrase><phrase role="special">(</phrase> <phrase role="identifier">value_type</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">va</phrase><phrase role="special">);</phrase>
<phrase role="identifier">channel_op_status</phrase> <phrase role="identifier">push</phrase><phrase role="special">(</phrase> <phrase role="identifier">value_type</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="identifier">va</phrase><phrase role="special">);</phrase>
<phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Rep</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Period</phrase> <phrase role="special">&gt;</phrase>
<phrase role="identifier">channel_op_status</phrase> <phrase role="identifier">push_wait_for</phrase><phrase role="special">(</phrase>
<phrase role="identifier">value_type</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">va</phrase><phrase role="special">,</phrase>
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">duration</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Rep</phrase><phrase role="special">,</phrase> <phrase role="identifier">Period</phrase> <phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">timeout_duration</phrase><phrase role="special">);</phrase>
<phrase role="identifier">channel_op_status</phrase> <phrase role="identifier">push_wait_for</phrase><phrase role="special">(</phrase> <phrase role="identifier">value_type</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="identifier">va</phrase><phrase role="special">,</phrase>
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">duration</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Rep</phrase><phrase role="special">,</phrase> <phrase role="identifier">Period</phrase> <phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">timeout_duration</phrase><phrase role="special">);</phrase>
<phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Clock</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Duration</phrase> <phrase role="special">&gt;</phrase>
<phrase role="identifier">channel_op_status</phrase> <phrase role="identifier">push_wait_until</phrase><phrase role="special">(</phrase>
<phrase role="identifier">value_type</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">va</phrase><phrase role="special">,</phrase>
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">time_point</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Clock</phrase><phrase role="special">,</phrase> <phrase role="identifier">Duration</phrase> <phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">timeout_time</phrase><phrase role="special">);</phrase>
<phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Clock</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Duration</phrase> <phrase role="special">&gt;</phrase>
<phrase role="identifier">channel_op_status</phrase> <phrase role="identifier">push_wait_until</phrase><phrase role="special">(</phrase>
<phrase role="identifier">value_type</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="identifier">va</phrase><phrase role="special">,</phrase>
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">time_point</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Clock</phrase><phrase role="special">,</phrase> <phrase role="identifier">Duration</phrase> <phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">timeout_time</phrase><phrase role="special">);</phrase>
<phrase role="identifier">channel_op_status</phrase> <phrase role="identifier">try_push</phrase><phrase role="special">(</phrase> <phrase role="identifier">value_type</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">va</phrase><phrase role="special">);</phrase>
<phrase role="identifier">channel_op_status</phrase> <phrase role="identifier">try_push</phrase><phrase role="special">(</phrase> <phrase role="identifier">value_type</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="identifier">va</phrase><phrase role="special">);</phrase>
<phrase role="identifier">channel_op_status</phrase> <phrase role="identifier">pop</phrase><phrase role="special">(</phrase> <phrase role="identifier">value_type</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">va</phrase><phrase role="special">);</phrase>
<phrase role="identifier">value_type</phrase> <phrase role="identifier">value_pop</phrase><phrase role="special">();</phrase>
<phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Rep</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Period</phrase> <phrase role="special">&gt;</phrase>
<phrase role="identifier">channel_op_status</phrase> <phrase role="identifier">pop_wait_for</phrase><phrase role="special">(</phrase>
<phrase role="identifier">value_type</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">va</phrase><phrase role="special">,</phrase>
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">duration</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Rep</phrase><phrase role="special">,</phrase> <phrase role="identifier">Period</phrase> <phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">timeout_duration</phrase><phrase role="special">);</phrase>
<phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Clock</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Duration</phrase> <phrase role="special">&gt;</phrase>
<phrase role="identifier">channel_op_status</phrase> <phrase role="identifier">pop_wait_until</phrase><phrase role="special">(</phrase>
<phrase role="identifier">value_type</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">va</phrase><phrase role="special">,</phrase>
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">time_point</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Clock</phrase><phrase role="special">,</phrase> <phrase role="identifier">Duration</phrase> <phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">timeout_time</phrase><phrase role="special">);</phrase>
<phrase role="identifier">channel_op_status</phrase> <phrase role="identifier">try_pop</phrase><phrase role="special">(</phrase> <phrase role="identifier">value_type</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">va</phrase><phrase role="special">);</phrase>
<phrase role="special">};</phrase>
</programlisting>
<bridgehead renderas="sect4" id="fiber.synchronization.channels.h6">
<phrase id="fiber.synchronization.channels.constructor"/><link linkend="fiber.synchronization.channels.constructor">Constructor</link>
</bridgehead>
<programlisting><phrase role="identifier">bounded_channel</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">wm</phrase><phrase role="special">);</phrase>
<phrase role="identifier">bounded_channel</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">hwm</phrase><phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">lwm</phrase><phrase role="special">);</phrase>
</programlisting>
<variablelist>
<title></title>
<varlistentry>
<term>Preconditions:</term>
<listitem>
<para>
<code><phrase role="identifier">hwm</phrase> <phrase role="special">&gt;</phrase>
<phrase role="identifier">lwm</phrase></code>
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Effects:</term>
<listitem>
<para>
Constructs an object of class <code><phrase role="identifier">bounded_channel</phrase></code>.
The constructor with two arguments constructs an object of class <code><phrase
role="identifier">bounded_channel</phrase></code> with a high-watermark
of <code><phrase role="identifier">hwm</phrase></code> and a low-watermark
of <code><phrase role="identifier">lwm</phrase></code> items. The constructor
with one argument is effectively the same as <code><phrase role="identifier">bounded_channel</phrase><phrase
role="special">(</phrase><phrase role="identifier">wm</phrase><phrase
role="special">,</phrase> <phrase role="special">(</phrase><phrase
role="identifier">wm</phrase><phrase role="special">-</phrase><phrase
role="number">1</phrase><phrase role="special">))</phrase></code>.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Throws:</term>
<listitem>
<para>
<code><phrase role="identifier">invalid_argument</phrase></code> if
<code><phrase role="identifier">lwm</phrase> <phrase role="special">&gt;=</phrase>
<phrase role="identifier">hwm</phrase></code>.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Notes:</term>
<listitem>
<para>
Once the number of values in the channel reaches <code><phrase role="identifier">hwm</phrase></code>,
any call to <code><phrase role="identifier">push</phrase><phrase role="special">()</phrase></code>,
<code><phrase role="identifier">push_wait_for</phrase><phrase role="special">()</phrase></code>
or <code><phrase role="identifier">push_wait_until</phrase><phrase
role="special">()</phrase></code> will block until the number of values
in the channel is at most <code><phrase role="identifier">lwm</phrase></code>.
That is, if <code><phrase role="identifier">lwm</phrase> <phrase role="special">&lt;</phrase>
<phrase role="special">(</phrase><phrase role="identifier">hwm</phrase><phrase
role="special">-</phrase><phrase role="number">1</phrase><phrase role="special">)</phrase></code>,
the channel can be in a state in which <code><phrase role="identifier">push</phrase><phrase
role="special">()</phrase></code>, <code><phrase role="identifier">push_wait_for</phrase><phrase
role="special">()</phrase></code> or <code><phrase role="identifier">push_wait_until</phrase><phrase
role="special">()</phrase></code> calls will block (channel is full)
even though the number of values in the channel is less than <code><phrase
role="identifier">hwm</phrase></code>.
</para>
</listitem>
</varlistentry>
</variablelist>
<para>
<bridgehead renderas="sect4" id="bounded_channel_upper_bound_bridgehead">
<phrase id="bounded_channel_upper_bound"/>
<link linkend="bounded_channel_upper_bound">Member
function <code>upper_bound</code>()</link>
</bridgehead>
</para>
<programlisting><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">upper_bound</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
</programlisting>
<variablelist>
<title></title>
<varlistentry>
<term>Returns:</term>
<listitem>
<para>
the high-watermark with which <code><phrase role="special">*</phrase><phrase
role="keyword">this</phrase></code> was constructed.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Throws:</term>
<listitem>
<para>
Nothing.
</para>
</listitem>
</varlistentry>
</variablelist>
<para>
<bridgehead renderas="sect4" id="bounded_channel_lower_bound_bridgehead">
<phrase id="bounded_channel_lower_bound"/>
<link linkend="bounded_channel_lower_bound">Member
function <code>lower_bound</code>()</link>
</bridgehead>
</para>
<programlisting><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">lower_bound</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
</programlisting>
<variablelist>
<title></title>
<varlistentry>
<term>Returns:</term>
<listitem>
<para>
the low-watermark with which <code><phrase role="special">*</phrase><phrase
role="keyword">this</phrase></code> was constructed.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Throws:</term>
<listitem>
<para>
Nothing.
</para>
</listitem>
</varlistentry>
</variablelist>
<para>
<bridgehead renderas="sect4" id="bounded_channel_close_bridgehead">
<phrase id="bounded_channel_close"/>
<link linkend="bounded_channel_close">Member
function <code>close</code>()</link>
</bridgehead>
</para>
<programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">close</phrase><phrase role="special">();</phrase>
</programlisting>
<variablelist>
<title></title>
<varlistentry>
<term>Effects:</term>
<listitem>
<para>
Deactivates the channel. No values can be put after calling <code><phrase
role="keyword">this</phrase><phrase role="special">-&gt;</phrase><phrase
role="identifier">close</phrase><phrase role="special">()</phrase></code>.
Fibers blocked in <code><phrase role="keyword">this</phrase><phrase
role="special">-&gt;</phrase><phrase role="identifier">pop</phrase><phrase
role="special">()</phrase></code>, <code><phrase role="keyword">this</phrase><phrase
role="special">-&gt;</phrase><phrase role="identifier">pop_wait_for</phrase><phrase
role="special">()</phrase></code> or <code><phrase role="keyword">this</phrase><phrase
role="special">-&gt;</phrase><phrase role="identifier">pop_wait_until</phrase><phrase
role="special">()</phrase></code> will return <code><phrase role="identifier">closed</phrase></code>.
Fibers blocked in <code><phrase role="keyword">this</phrase><phrase
role="special">-&gt;</phrase><phrase role="identifier">value_pop</phrase><phrase
role="special">()</phrase></code> will receive an exception.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Throws:</term>
<listitem>
<para>
Nothing.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Note:</term>
<listitem>
<para>
<code><phrase role="identifier">close</phrase><phrase role="special">()</phrase></code>
is like closing a pipe. It informs waiting consumers that no more values
will arrive.
</para>
</listitem>
</varlistentry>
</variablelist>
<para>
<bridgehead renderas="sect4" id="bounded_channel_push_bridgehead">
<phrase id="bounded_channel_push"/>
<link linkend="bounded_channel_push">Member
function <code>push</code>()</link>
</bridgehead>
</para>
<programlisting><phrase role="identifier">channel_op_status</phrase> <phrase role="identifier">push</phrase><phrase role="special">(</phrase> <phrase role="identifier">value_type</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">va</phrase><phrase role="special">);</phrase>
<phrase role="identifier">channel_op_status</phrase> <phrase role="identifier">push</phrase><phrase role="special">(</phrase> <phrase role="identifier">value_type</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="identifier">va</phrase><phrase role="special">);</phrase>
</programlisting>
<variablelist>
<title></title>
<varlistentry>
<term>Effects:</term>
<listitem>
<para>
If channel is closed, returns <code><phrase role="identifier">closed</phrase></code>.
If channel is not full, enqueues the value in the channel, wakes up
a fiber blocked on <code><phrase role="keyword">this</phrase><phrase
role="special">-&gt;</phrase><phrase role="identifier">pop</phrase><phrase
role="special">()</phrase></code>, <code><phrase role="keyword">this</phrase><phrase
role="special">-&gt;</phrase><phrase role="identifier">value_pop</phrase><phrase
role="special">()</phrase></code>, <code><phrase role="keyword">this</phrase><phrase
role="special">-&gt;</phrase><phrase role="identifier">pop_wait_for</phrase><phrase
role="special">()</phrase></code> or <code><phrase role="keyword">this</phrase><phrase
role="special">-&gt;</phrase><phrase role="identifier">pop_wait_until</phrase><phrase
role="special">()</phrase></code> and returns <code><phrase role="identifier">success</phrase></code>.
Otherwise the calling fiber is suspended until the number of values
in the channel drops to <code><phrase role="identifier">lwm</phrase></code>
(return value <code><phrase role="identifier">success</phrase></code>)or
the channel is <code><phrase role="identifier">close</phrase><phrase
role="special">()</phrase></code>d (return value <code><phrase role="identifier">closed</phrase></code>).
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Throws:</term>
<listitem>
<para>
<code><phrase role="identifier">fiber_interrupted</phrase></code>
</para>
</listitem>
</varlistentry>
</variablelist>
<para>
<bridgehead renderas="sect4" id="bounded_channel_push_wait_for_bridgehead">
<phrase id="bounded_channel_push_wait_for"/>
<link linkend="bounded_channel_push_wait_for">Member
function <code>push_wait_for</code>()</link>
</bridgehead>
</para>
<programlisting><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Rep</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Period</phrase> <phrase role="special">&gt;</phrase>
<phrase role="identifier">channel_op_status</phrase> <phrase role="identifier">push_wait_for</phrase><phrase role="special">(</phrase>
<phrase role="identifier">value_type</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">va</phrase><phrase role="special">,</phrase>
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">duration</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Rep</phrase><phrase role="special">,</phrase> <phrase role="identifier">Period</phrase> <phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">timeout_duration</phrase><phrase role="special">);</phrase>
<phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Rep</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Period</phrase> <phrase role="special">&gt;</phrase>
<phrase role="identifier">channel_op_status</phrase> <phrase role="identifier">push_wait_for</phrase><phrase role="special">(</phrase>
<phrase role="identifier">value_type</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="identifier">va</phrase><phrase role="special">,</phrase>
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">duration</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Rep</phrase><phrase role="special">,</phrase> <phrase role="identifier">Period</phrase> <phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">timeout_duration</phrase><phrase role="special">);</phrase>
</programlisting>
<variablelist>
<title></title>
<varlistentry>
<term>Effects:</term>
<listitem>
<para>
Accepts <code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase
role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase
role="identifier">duration</phrase></code> and internally computes
a time_point as (system time + <code><phrase role="identifier">timeout_duration</phrase></code>).
If channel is closed, returns <code><phrase role="identifier">closed</phrase></code>.
If channel is not full, enqueues the value in the channel, wakes up
a fiber blocked on <code><phrase role="keyword">this</phrase><phrase
role="special">-&gt;</phrase><phrase role="identifier">pop</phrase><phrase
role="special">()</phrase></code>, <code><phrase role="keyword">this</phrase><phrase
role="special">-&gt;</phrase><phrase role="identifier">value_pop</phrase><phrase
role="special">()</phrase></code>, <code><phrase role="keyword">this</phrase><phrase
role="special">-&gt;</phrase><phrase role="identifier">pop_wait_for</phrase><phrase
role="special">()</phrase></code> or <code><phrase role="keyword">this</phrase><phrase
role="special">-&gt;</phrase><phrase role="identifier">pop_wait_until</phrase><phrase
role="special">()</phrase></code> and returns <code><phrase role="identifier">success</phrase></code>.
Otherwise the calling fiber is suspended until the number of values
in the channel drops to <code><phrase role="identifier">lwm</phrase></code>
(return value <code><phrase role="identifier">success</phrase></code>),
the channel is <code><phrase role="identifier">close</phrase><phrase
role="special">()</phrase></code>d (return value <code><phrase role="identifier">closed</phrase></code>),
or the system time reaches the computed time_point (return value <code><phrase
role="identifier">timeout</phrase></code>).
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Throws:</term>
<listitem>
<para>
<code><phrase role="identifier">fiber_interrupted</phrase></code>
</para>
</listitem>
</varlistentry>
</variablelist>
<para>
<bridgehead renderas="sect4" id="bounded_channel_push_wait_until_bridgehead">
<phrase id="bounded_channel_push_wait_until"/>
<link linkend="bounded_channel_push_wait_until">Member
function <code>push_wait_until</code>()</link>
</bridgehead>
</para>
<programlisting><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Clock</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Duration</phrase> <phrase role="special">&gt;</phrase>
<phrase role="identifier">channel_op_status</phrase> <phrase role="identifier">push_wait_until</phrase><phrase role="special">(</phrase>
<phrase role="identifier">value_type</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">va</phrase><phrase role="special">,</phrase>
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">time_point</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Clock</phrase><phrase role="special">,</phrase> <phrase role="identifier">Duration</phrase> <phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">timeout_time</phrase><phrase role="special">);</phrase>
<phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Clock</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Duration</phrase> <phrase role="special">&gt;</phrase>
<phrase role="identifier">channel_op_status</phrase> <phrase role="identifier">push_wait_until</phrase><phrase role="special">(</phrase>
<phrase role="identifier">value_type</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="identifier">va</phrase><phrase role="special">,</phrase>
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">time_point</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Clock</phrase><phrase role="special">,</phrase> <phrase role="identifier">Duration</phrase> <phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">timeout_time</phrase><phrase role="special">);</phrase>
</programlisting>
<variablelist>
<title></title>
<varlistentry>
<term>Effects:</term>
<listitem>
<para>
Accepts an absolute <code><phrase role="identifier">timeout_time</phrase></code>
in any supported time_point type. If channel is closed, returns <code><phrase
role="identifier">closed</phrase></code>. If channel is not full, enqueues
the value in the channel, wakes up a fiber blocked on <code><phrase
role="keyword">this</phrase><phrase role="special">-&gt;</phrase><phrase
role="identifier">pop</phrase><phrase role="special">()</phrase></code>,
<code><phrase role="keyword">this</phrase><phrase role="special">-&gt;</phrase><phrase
role="identifier">value_pop</phrase><phrase role="special">()</phrase></code>,
<code><phrase role="keyword">this</phrase><phrase role="special">-&gt;</phrase><phrase
role="identifier">pop_wait_for</phrase><phrase role="special">()</phrase></code>
or <code><phrase role="keyword">this</phrase><phrase role="special">-&gt;</phrase><phrase
role="identifier">pop_wait_until</phrase><phrase role="special">()</phrase></code>
and returns <code><phrase role="identifier">success</phrase></code>.
Otherwise the calling fiber is suspended until the number of values
in the channel drops to <code><phrase role="identifier">lwm</phrase></code>
(return value <code><phrase role="identifier">success</phrase></code>),
the channel is <code><phrase role="identifier">close</phrase><phrase
role="special">()</phrase></code>d (return value <code><phrase role="identifier">closed</phrase></code>),
or the system time reaches the passed time_point (return value <code><phrase
role="identifier">timeout</phrase></code>).
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Throws:</term>
<listitem>
<para>
<code><phrase role="identifier">fiber_interrupted</phrase></code>
</para>
</listitem>
</varlistentry>
</variablelist>
<para>
<bridgehead renderas="sect4" id="bounded_channel_try_push_bridgehead">
<phrase id="bounded_channel_try_push"/>
<link linkend="bounded_channel_try_push">Member
function <code>try_push</code>()</link>
</bridgehead>
</para>
<programlisting><phrase role="identifier">channel_op_status</phrase> <phrase role="identifier">try_push</phrase><phrase role="special">(</phrase> <phrase role="identifier">value_type</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">va</phrase><phrase role="special">);</phrase>
<phrase role="identifier">channel_op_status</phrase> <phrase role="identifier">try_push</phrase><phrase role="special">(</phrase> <phrase role="identifier">value_type</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="identifier">va</phrase><phrase role="special">);</phrase>
</programlisting>
<variablelist>
<title></title>
<varlistentry>
<term>Effects:</term>
<listitem>
<para>
If channel is full, returns <code><phrase role="identifier">full</phrase></code>.
If channel is closed, returns <code><phrase role="identifier">closed</phrase></code>.
Otherwise enqueues the value in the channel, wakes up a fiber blocked
on <code><phrase role="keyword">this</phrase><phrase role="special">-&gt;</phrase><phrase
role="identifier">pop</phrase><phrase role="special">()</phrase></code>,
<code><phrase role="keyword">this</phrase><phrase role="special">-&gt;</phrase><phrase
role="identifier">value_pop</phrase><phrase role="special">()</phrase></code>,
<code><phrase role="keyword">this</phrase><phrase role="special">-&gt;</phrase><phrase
role="identifier">pop_wait_for</phrase><phrase role="special">()</phrase></code>
or <code><phrase role="keyword">this</phrase><phrase role="special">-&gt;</phrase><phrase
role="identifier">pop_wait_until</phrase><phrase role="special">()</phrase></code>
and returns <code><phrase role="identifier">success</phrase></code>.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Throws:</term>
<listitem>
<para>
<code><phrase role="identifier">fiber_interrupted</phrase></code>
</para>
</listitem>
</varlistentry>
</variablelist>
<para>
<bridgehead renderas="sect4" id="bounded_channel_pop_bridgehead">
<phrase id="bounded_channel_pop"/>
<link linkend="bounded_channel_pop">Member
function <code>pop</code>()</link>
</bridgehead>
</para>
<programlisting><phrase role="identifier">channel_op_status</phrase> <phrase role="identifier">pop</phrase><phrase role="special">(</phrase> <phrase role="identifier">value_type</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">va</phrase><phrase role="special">);</phrase>
</programlisting>
<variablelist>
<title></title>
<varlistentry>
<term>Effects:</term>
<listitem>
<para>
Dequeues a value from the channel. If the channel is empty, the fiber
gets suspended until at least one new item is <code><phrase role="identifier">push</phrase><phrase
role="special">()</phrase></code>ed (return value <code><phrase role="identifier">success</phrase></code>
and <code><phrase role="identifier">va</phrase></code> contains dequeued
value) or the channel gets <code><phrase role="identifier">close</phrase><phrase
role="special">()</phrase></code>d (return value <code><phrase role="identifier">closed</phrase></code>).
Once the number of items remaining in the channel drops to <code><phrase
role="identifier">lwm</phrase></code>, any fibers blocked on <code><phrase
role="identifier">push</phrase><phrase role="special">()</phrase></code>,
<code><phrase role="identifier">push_wait_for</phrase><phrase role="special">()</phrase></code>
or <code><phrase role="identifier">push_wait_until</phrase><phrase
role="special">()</phrase></code> may resume.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Throws:</term>
<listitem>
<para>
<code><phrase role="identifier">fiber_interrupted</phrase></code>
</para>
</listitem>
</varlistentry>
</variablelist>
<para>
<bridgehead renderas="sect4" id="bounded_channel_value_pop_bridgehead">
<phrase id="bounded_channel_value_pop"/>
<link linkend="bounded_channel_value_pop">Member
function <code>value_pop</code>()</link>
</bridgehead>
</para>
<programlisting><phrase role="identifier">value_type</phrase> <phrase role="identifier">value_pop</phrase><phrase role="special">();</phrase>
</programlisting>
<variablelist>
<title></title>
<varlistentry>
<term>Effects:</term>
<listitem>
<para>
Dequeues a value from the channel. If the channel is empty, the fiber
gets suspended until at least one new item is <code><phrase role="identifier">push</phrase><phrase
role="special">()</phrase></code>ed or the channel gets <code><phrase
role="identifier">close</phrase><phrase role="special">()</phrase></code>d
(which throws an exception). Once the number of items remaining in
the channel drops to <code><phrase role="identifier">lwm</phrase></code>,
any fibers blocked on <code><phrase role="identifier">push</phrase><phrase
role="special">()</phrase></code>, <code><phrase role="identifier">push_wait_for</phrase><phrase
role="special">()</phrase></code> or <code><phrase role="identifier">push_wait_until</phrase><phrase
role="special">()</phrase></code> may resume.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Throws:</term>
<listitem>
<para>
<code><phrase role="identifier">logic_error</phrase></code> if <code><phrase
role="special">*</phrase><phrase role="keyword">this</phrase></code>
is closed; <code><phrase role="identifier">fiber_interrupted</phrase></code>
</para>
</listitem>
</varlistentry>
</variablelist>
<para>
<bridgehead renderas="sect4" id="bounded_channel_try_pop_bridgehead">
<phrase id="bounded_channel_try_pop"/>
<link linkend="bounded_channel_try_pop">Member
function <code>try_pop</code>()</link>
</bridgehead>
</para>
<programlisting><phrase role="identifier">channel_op_status</phrase> <phrase role="identifier">try_pop</phrase><phrase role="special">(</phrase> <phrase role="identifier">value_type</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">va</phrase><phrase role="special">);</phrase>
</programlisting>
<variablelist>
<title></title>
<varlistentry>
<term>Effects:</term>
<listitem>
<para>
If channel is empty, returns <code><phrase role="identifier">empty</phrase></code>.
If channel is closed, returns <code><phrase role="identifier">closed</phrase></code>.
Otherwise it returns <code><phrase role="identifier">success</phrase></code>
and <code><phrase role="identifier">va</phrase></code> contains the
dequeued value. Once the number of items remaining in the channel drops
to <code><phrase role="identifier">lwm</phrase></code>, any fibers
blocked on <code><phrase role="identifier">push</phrase><phrase role="special">()</phrase></code>,
<code><phrase role="identifier">push_wait_for</phrase><phrase role="special">()</phrase></code>
or <code><phrase role="identifier">push_wait_until</phrase><phrase
role="special">()</phrase></code> may resume.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Throws:</term>
<listitem>
<para>
Nothing.
</para>
</listitem>
</varlistentry>
</variablelist>
<para>
<bridgehead renderas="sect4" id="bounded_channel_pop_wait_for_bridgehead">
<phrase id="bounded_channel_pop_wait_for"/>
<link linkend="bounded_channel_pop_wait_for">Member
function <code>pop_wait_for</code>()</link>
</bridgehead>
</para>
<programlisting><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Rep</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Period</phrase> <phrase role="special">&gt;</phrase>
<phrase role="identifier">channel_op_status</phrase> <phrase role="identifier">pop_wait_for</phrase><phrase role="special">(</phrase>
<phrase role="identifier">value_type</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">va</phrase><phrase role="special">,</phrase>
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">duration</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Rep</phrase><phrase role="special">,</phrase> <phrase role="identifier">Period</phrase> <phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">timeout_duration</phrase><phrase role="special">)</phrase>
</programlisting>
<variablelist>
<title></title>
<varlistentry>
<term>Effects:</term>
<listitem>
<para>
Accepts <code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase
role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase
role="identifier">duration</phrase></code> and internally computes
a timeout time as (system time + <code><phrase role="identifier">timeout_duration</phrase></code>).
If channel is not empty, immediately dequeues a value from the channel.
Otherwise the fiber gets suspended until at least one new item is
<code><phrase role="identifier">push</phrase><phrase role="special">()</phrase></code>ed
(return value <code><phrase role="identifier">success</phrase></code>
and <code><phrase role="identifier">va</phrase></code> contains dequeued
value), or the channel gets <code><phrase role="identifier">close</phrase><phrase
role="special">()</phrase></code>d (return value <code><phrase role="identifier">closed</phrase></code>),
or the system time reaches the computed timeout time (return value
<code><phrase role="identifier">timeout</phrase></code>). Once the
number of items remaining in the channel drops to <code><phrase role="identifier">lwm</phrase></code>,
any fibers blocked on <code><phrase role="identifier">push</phrase><phrase
role="special">()</phrase></code>, <code><phrase role="identifier">push_wait_for</phrase><phrase
role="special">()</phrase></code> or <code><phrase role="identifier">push_wait_until</phrase><phrase
role="special">()</phrase></code> may resume.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Throws:</term>
<listitem>
<para>
<code><phrase role="identifier">fiber_interrupted</phrase></code>
</para>
</listitem>
</varlistentry>
</variablelist>
<para>
<bridgehead renderas="sect4" id="bounded_channel_pop_wait_until_bridgehead">
<phrase id="bounded_channel_pop_wait_until"/>
<link linkend="bounded_channel_pop_wait_until">Member
function <code>pop_wait_until</code>()</link>
</bridgehead>
</para>
<programlisting><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Clock</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Duration</phrase> <phrase role="special">&gt;</phrase>
<phrase role="identifier">channel_op_status</phrase> <phrase role="identifier">pop_wait_until</phrase><phrase role="special">(</phrase>
<phrase role="identifier">value_type</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">va</phrase><phrase role="special">,</phrase>
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">time_point</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Clock</phrase><phrase role="special">,</phrase> <phrase role="identifier">Duration</phrase> <phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">timeout_time</phrase><phrase role="special">)</phrase>
</programlisting>
<variablelist>
<title></title>
<varlistentry>
<term>Effects:</term>
<listitem>
<para>
Accepts a <code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase
role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase
role="identifier">time_point</phrase><phrase role="special">&lt;</phrase>
<phrase role="identifier">Clock</phrase><phrase role="special">,</phrase>
<phrase role="identifier">Duration</phrase> <phrase role="special">&gt;</phrase></code>.
If channel is not empty, immediately dequeues a value from the channel.
Otherwise the fiber gets suspended until at least one new item is
<code><phrase role="identifier">push</phrase><phrase role="special">()</phrase></code>ed
(return value <code><phrase role="identifier">success</phrase></code>
and <code><phrase role="identifier">va</phrase></code> contains dequeued
value), or the channel gets <code><phrase role="identifier">close</phrase><phrase
role="special">()</phrase></code>d (return value <code><phrase role="identifier">closed</phrase></code>),
or the system time reaches the passed <code><phrase role="identifier">time_point</phrase></code>
(return value <code><phrase role="identifier">timeout</phrase></code>).
Once the number of items remaining in the channel drops to <code><phrase
role="identifier">lwm</phrase></code>, any fibers blocked on <code><phrase
role="identifier">push</phrase><phrase role="special">()</phrase></code>,
<code><phrase role="identifier">push_wait_for</phrase><phrase role="special">()</phrase></code>
or <code><phrase role="identifier">push_wait_until</phrase><phrase
role="special">()</phrase></code> may resume.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Throws:</term>
<listitem>
<para>
<code><phrase role="identifier">fiber_interrupted</phrase></code>
</para>
</listitem>
</varlistentry>
</variablelist>
</section>
<section id="fiber.synchronization.futures">
<title><link linkend="fiber.synchronization.futures">Futures</link></title>
<bridgehead renderas="sect4" id="fiber.synchronization.futures.h0">
<phrase id="fiber.synchronization.futures.overview"/><link linkend="fiber.synchronization.futures.overview">Overview</link>
</bridgehead>
<para>
The futures library provides a means of handling asynchronous future values,
whether those values are generated by another fiber, or on a single fiber
in response to external stimuli, or on-demand.
</para>
<para>
This is done through the provision of four class templates: <link linkend="class_future"> <code>future&lt;&gt;</code></link> and
<link linkend="class_shared_future"> <code>shared_future&lt;&gt;</code></link> which are used to retrieve the asynchronous
results, and <link linkend="class_promise"> <code>promise&lt;&gt;</code></link> and <link linkend="class_packaged_task"> <code>packaged_task&lt;&gt;</code></link> which
are used to generate the asynchronous results.
</para>
<para>
An instance of <link linkend="class_future"> <code>future&lt;&gt;</code></link> holds the one and only reference
to a result. Ownership can be transferred between instances using the move
constructor or move-assignment operator, but at most one instance holds a
reference to a given asynchronous result. When the result is ready, it is
returned from <link linkend="future_get"> <code>future::get()</code></link> by rvalue-reference to allow the result
to be moved or copied as appropriate for the type.
</para>
<para>
On the other hand, many instances of <link linkend="class_shared_future"> <code>shared_future&lt;&gt;</code></link> may
reference the same result. Instances can be freely copied and assigned, and
<link linkend="shared_future_get"> <code>shared_future::get()</code></link>
returns a <code><phrase role="keyword">const</phrase></code>
reference so that multiple calls to <link linkend="shared_future_get"> <code>shared_future::get()</code></link>
are
safe. You can move an instance of <link linkend="class_future"> <code>future&lt;&gt;</code></link> into an instance
of <link linkend="class_shared_future"> <code>shared_future&lt;&gt;</code></link>, thus transferring ownership
of the associated asynchronous result, but not vice-versa.
</para>
<para>
<link linkend="fibers_async"> <code>fibers::async()</code></link> is a simple way of running asynchronous tasks.
A call to <code><phrase role="identifier">async</phrase><phrase role="special">()</phrase></code>
spawns a fiber and returns a <link linkend="class_future"> <code>future&lt;&gt;</code></link> that will deliver
the result of the fiber function.
</para>
<bridgehead renderas="sect4" id="fiber.synchronization.futures.h1">
<phrase id="fiber.synchronization.futures.creating_asynchronous_values"/><link
linkend="fiber.synchronization.futures.creating_asynchronous_values">Creating
asynchronous values</link>
</bridgehead>
<para>
You can set the value in a future with either a <link linkend="class_promise"> <code>promise&lt;&gt;</code></link> or
a <link linkend="class_packaged_task"> <code>packaged_task&lt;&gt;</code></link>. A <link linkend="class_packaged_task"> <code>packaged_task&lt;&gt;</code></link> is
a callable object with <code><phrase role="keyword">void</phrase></code>
return that wraps a function or callable object returning the specified type.
When the <link linkend="class_packaged_task"> <code>packaged_task&lt;&gt;</code></link> is invoked, it invokes the
contained function in turn, and populates a future with the contained function's
return value. This is an answer to the perennial question: &quot;How do I
return a value from a fiber?&quot; Package the function you wish to run as
a <link linkend="class_packaged_task"> <code>packaged_task&lt;&gt;</code></link> and pass the packaged task to the
fiber constructor. The future retrieved from the packaged task can then be
used to obtain the return value. If the function throws an exception, that
is stored in the future in place of the return value.
</para>
<programlisting><phrase role="keyword">int</phrase> <phrase role="identifier">calculate_the_answer_to_life_the_universe_and_everything</phrase><phrase role="special">()</phrase> <phrase role="special">{</phrase>
<phrase role="keyword">return</phrase> <phrase role="number">42</phrase><phrase role="special">;</phrase>
<phrase role="special">}</phrase>
<phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">packaged_task</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">()&gt;</phrase> <phrase role="identifier">pt</phrase><phrase role="special">(</phrase><phrase role="identifier">calculate_the_answer_to_life_the_universe_and_everything</phrase><phrase role="special">);</phrase>
<phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">future</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&gt;</phrase> <phrase role="identifier">fi</phrase><phrase role="special">=</phrase><phrase role="identifier">pt</phrase><phrase role="special">.</phrase><phrase role="identifier">get_future</phrase><phrase role="special">();</phrase>
<phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">fiber</phrase><phrase role="special">(</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">move</phrase><phrase role="special">(</phrase><phrase role="identifier">pt</phrase><phrase role="special">)).</phrase><phrase role="identifier">detach</phrase><phrase role="special">();</phrase> <phrase role="comment">// launch task on a fiber</phrase>
<phrase role="identifier">fi</phrase><phrase role="special">.</phrase><phrase role="identifier">wait</phrase><phrase role="special">();</phrase> <phrase role="comment">// wait for it to finish</phrase>
<phrase role="identifier">assert</phrase><phrase role="special">(</phrase><phrase role="identifier">fi</phrase><phrase role="special">.</phrase><phrase role="identifier">is_ready</phrase><phrase role="special">());</phrase>
<phrase role="identifier">assert</phrase><phrase role="special">(</phrase><phrase role="identifier">fi</phrase><phrase role="special">.</phrase><phrase role="identifier">has_value</phrase><phrase role="special">());</phrase>
<phrase role="identifier">assert</phrase><phrase role="special">(!</phrase><phrase role="identifier">fi</phrase><phrase role="special">.</phrase><phrase role="identifier">has_exception</phrase><phrase role="special">());</phrase>
<phrase role="identifier">assert</phrase><phrase role="special">(</phrase><phrase role="identifier">fi</phrase><phrase role="special">.</phrase><phrase role="identifier">get</phrase><phrase role="special">()==</phrase><phrase role="number">42</phrase><phrase role="special">);</phrase>
</programlisting>
<para>
A <link linkend="class_promise"> <code>promise&lt;&gt;</code></link> is a bit more low level: it just provides explicit
functions to store a value or an exception in the associated future. A promise
can therefore be used where the value might come from more than one possible
source.
</para>
<programlisting><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">promise</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&gt;</phrase> <phrase role="identifier">pi</phrase><phrase role="special">;</phrase>
<phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">future</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">int</phrase><phrase role="special">&gt;</phrase> <phrase role="identifier">fi</phrase><phrase role="special">;</phrase>
<phrase role="identifier">fi</phrase><phrase role="special">=</phrase><phrase role="identifier">pi</phrase><phrase role="special">.</phrase><phrase role="identifier">get_future</phrase><phrase role="special">();</phrase>
<phrase role="identifier">pi</phrase><phrase role="special">.</phrase><phrase role="identifier">set_value</phrase><phrase role="special">(</phrase><phrase role="number">42</phrase><phrase role="special">);</phrase>
<phrase role="identifier">assert</phrase><phrase role="special">(</phrase><phrase role="identifier">fi</phrase><phrase role="special">.</phrase><phrase role="identifier">is_ready</phrase><phrase role="special">());</phrase>
<phrase role="identifier">assert</phrase><phrase role="special">(</phrase><phrase role="identifier">fi</phrase><phrase role="special">.</phrase><phrase role="identifier">has_value</phrase><phrase role="special">());</phrase>
<phrase role="identifier">assert</phrase><phrase role="special">(!</phrase><phrase role="identifier">fi</phrase><phrase role="special">.</phrase><phrase role="identifier">has_exception</phrase><phrase role="special">());</phrase>
<phrase role="identifier">assert</phrase><phrase role="special">(</phrase><phrase role="identifier">fi</phrase><phrase role="special">.</phrase><phrase role="identifier">get</phrase><phrase role="special">()==</phrase><phrase role="number">42</phrase><phrase role="special">);</phrase>
</programlisting>
<section id="fiber.synchronization.futures.future">
<title><link linkend="fiber.synchronization.futures.future">Future</link></title>
<para>
A future provides a mechanism to access the result of an asynchronous operation.
</para>
<anchor id="shared_state"/>
<bridgehead renderas="sect5" id="fiber.synchronization.futures.future.h0">
<phrase id="fiber.synchronization.futures.future.shared_state"/><link linkend="fiber.synchronization.futures.future.shared_state">shared
state</link>
</bridgehead>
<para>
Behind a <link linkend="class_promise"> <code>promise&lt;&gt;</code></link> and its <link linkend="class_future"> <code>future&lt;&gt;</code></link> lies
an unspecified object called their <emphasis>shared state</emphasis>. The
shared state is what will actually hold the async result (or the exception).
</para>
<para>
The shared state is instantiated along with the <link linkend="class_promise"> <code>promise&lt;&gt;</code></link>.
</para>
<para>
Aside from its originating <code><phrase role="identifier">promise</phrase><phrase
role="special">&lt;&gt;</phrase></code>, a <link linkend="class_future"> <code>future&lt;&gt;</code></link> holds
a unique reference to a particular shared state. However, multiple <link linkend="class_shared_future"> <code>shared_future&lt;&gt;</code></link> instances
can reference the same underlying shared state.
</para>
<para>
As <link linkend="class_packaged_task"> <code>packaged_task&lt;&gt;</code></link> and <link linkend="fibers_async"> <code>fibers::async()</code></link> are
implemented using <link linkend="class_promise"> <code>promise&lt;&gt;</code></link>, discussions of shared state
apply to them as well.
</para>
<anchor id="class_future_status"/>
<bridgehead renderas="sect5" id="fiber.synchronization.futures.future.h1">
<phrase id="fiber.synchronization.futures.future.enumeration__code__phrase_role__identifier__future_status__phrase___code_"/><link
linkend="fiber.synchronization.futures.future.enumeration__code__phrase_role__identifier__future_status__phrase___code_">Enumeration
<code><phrase role="identifier">future_status</phrase></code></link>
</bridgehead>
<para>
Timed wait-operations ( <link linkend="future_wait_for"> <code>future::wait_for()</code></link> and <link linkend="future_wait_until"> <code>future::wait_until()</code></link>)
return the state of the future.
</para>
<programlisting><phrase role="keyword">enum</phrase> <phrase role="keyword">class</phrase> <phrase role="identifier">future_status</phrase> <phrase role="special">{</phrase>
<phrase role="identifier">ready</phrase><phrase role="special">,</phrase>
<phrase role="identifier">timeout</phrase><phrase role="special">,</phrase>
<phrase role="identifier">deferred</phrase> <phrase role="comment">// not supported yet</phrase>
<phrase role="special">};</phrase>
</programlisting>
<bridgehead renderas="sect5" id="fiber.synchronization.futures.future.h2">
<phrase id="fiber.synchronization.futures.future._code__phrase_role__identifier__ready__phrase___code_"/><link
linkend="fiber.synchronization.futures.future._code__phrase_role__identifier__ready__phrase___code_"><code><phrase
role="identifier">ready</phrase></code></link>
</bridgehead>
<variablelist>
<title></title>
<varlistentry>
<term>Effects:</term>
<listitem>
<para>
The <link linkend="shared_state">shared state</link> is ready.
</para>
</listitem>
</varlistentry>
</variablelist>
<bridgehead renderas="sect5" id="fiber.synchronization.futures.future.h3">
<phrase id="fiber.synchronization.futures.future._code__phrase_role__identifier__timeout__phrase___code_"/><link
linkend="fiber.synchronization.futures.future._code__phrase_role__identifier__timeout__phrase___code_"><code><phrase
role="identifier">timeout</phrase></code></link>
</bridgehead>
<variablelist>
<title></title>
<varlistentry>
<term>Effects:</term>
<listitem>
<para>
The <link linkend="shared_state">shared state</link> did not become
ready before timeout has passed.
</para>
</listitem>
</varlistentry>
</variablelist>
<para>
<bridgehead renderas="sect4" id="class_future_bridgehead">
<phrase id="class_future"/>
<link linkend="class_future">Template <code>future&lt;&gt;</code></link>
</bridgehead>
</para>
<para>
A <link linkend="class_future"> <code>future&lt;&gt;</code></link> contains a <link linkend="shared_state">shared
state</link> which is not shared with any other future.
</para>
<programlisting><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">R</phrase> <phrase role="special">&gt;</phrase>
<phrase role="keyword">class</phrase> <phrase role="identifier">future</phrase> <phrase role="special">{</phrase>
<phrase role="keyword">public</phrase><phrase role="special">:</phrase>
<phrase role="identifier">future</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
<phrase role="identifier">future</phrase><phrase role="special">(</phrase> <phrase role="identifier">future</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
<phrase role="identifier">future</phrase><phrase role="special">(</phrase> <phrase role="identifier">future</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="special">=</phrase> <phrase role="keyword">delete</phrase><phrase role="special">;</phrase>
<phrase role="special">~</phrase><phrase role="identifier">future</phrase><phrase role="special">();</phrase>
<phrase role="identifier">future</phrase> <phrase role="special">&amp;</phrase> <phrase role="keyword">operator</phrase><phrase role="special">=(</phrase> <phrase role="identifier">future</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
<phrase role="identifier">future</phrase> <phrase role="special">&amp;</phrase> <phrase role="keyword">operator</phrase><phrase role="special">=(</phrase> <phrase role="identifier">future</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="special">=</phrase> <phrase role="keyword">delete</phrase><phrase role="special">;</phrase>
<phrase role="keyword">bool</phrase> <phrase role="identifier">valid</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
<phrase role="identifier">shared_future</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">R</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">share</phrase><phrase role="special">();</phrase>
<phrase role="identifier">R</phrase> <phrase role="identifier">get</phrase><phrase role="special">();</phrase>
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">exception_ptr</phrase> <phrase role="identifier">get_exception_ptr</phrase><phrase role="special">();</phrase>
<phrase role="keyword">void</phrase> <phrase role="identifier">wait</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
<phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">class</phrase> <phrase role="identifier">Rep</phrase><phrase role="special">,</phrase> <phrase role="keyword">class</phrase> <phrase role="identifier">Period</phrase> <phrase role="special">&gt;</phrase>
<phrase role="identifier">future_status</phrase> <phrase role="identifier">wait_for</phrase><phrase role="special">(</phrase>
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">duration</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Rep</phrase><phrase role="special">,</phrase> <phrase role="identifier">Period</phrase> <phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">timeout_duration</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
<phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Clock</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Duration</phrase> <phrase role="special">&gt;</phrase>
<phrase role="identifier">future_status</phrase> <phrase role="identifier">wait_until</phrase><phrase role="special">(</phrase>
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">time_point</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Clock</phrase><phrase role="special">,</phrase> <phrase role="identifier">Duration</phrase> <phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">timeout_time</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
<phrase role="special">};</phrase>
</programlisting>
<bridgehead renderas="sect5" id="fiber.synchronization.futures.future.h4">
<phrase id="fiber.synchronization.futures.future.default_constructor"/><link
linkend="fiber.synchronization.futures.future.default_constructor">Default
constructor</link>
</bridgehead>
<programlisting><phrase role="identifier">future</phrase><phrase role="special">();</phrase>
</programlisting>
<variablelist>
<title></title>
<varlistentry>
<term>Effects:</term>
<listitem>
<para>
Creates a future with no <link linkend="shared_state">shared state</link>.
After construction <code><phrase role="keyword">false</phrase> <phrase
role="special">==</phrase> <phrase role="identifier">valid</phrase><phrase
role="special">()</phrase></code>.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Throws:</term>
<listitem>
<para>
Nothing.
</para>
</listitem>
</varlistentry>
</variablelist>
<bridgehead renderas="sect5" id="fiber.synchronization.futures.future.h5">
<phrase id="fiber.synchronization.futures.future.move_constructor"/><link
linkend="fiber.synchronization.futures.future.move_constructor">Move constructor</link>
</bridgehead>
<programlisting><phrase role="identifier">future</phrase><phrase role="special">(</phrase> <phrase role="identifier">future</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
</programlisting>
<variablelist>
<title></title>
<varlistentry>
<term>Effects:</term>
<listitem>
<para>
Constructs a future with the <link linkend="shared_state">shared
state</link> of other. After construction <code><phrase role="keyword">false</phrase>
<phrase role="special">==</phrase> <phrase role="identifier">other</phrase><phrase
role="special">.</phrase><phrase role="identifier">valid</phrase><phrase
role="special">()</phrase></code>.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Throws:</term>
<listitem>
<para>
Nothing.
</para>
</listitem>
</varlistentry>
</variablelist>
<bridgehead renderas="sect5" id="fiber.synchronization.futures.future.h6">
<phrase id="fiber.synchronization.futures.future.destructor"/><link linkend="fiber.synchronization.futures.future.destructor">Destructor</link>
</bridgehead>
<programlisting><phrase role="special">~</phrase><phrase role="identifier">future</phrase><phrase role="special">();</phrase>
</programlisting>
<variablelist>
<title></title>
<varlistentry>
<term>Effects:</term>
<listitem>
<para>
Destroys the future; ownership is abandoned.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Throws:</term>
<listitem>
<para>
Nothing.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Note:</term>
<listitem>
<para>
<code>~future()</code> does <emphasis>not</emphasis> block the calling fiber.
</para>
</listitem>
</varlistentry>
</variablelist>
<para>
Consider a sequence such as:
</para>
<orderedlist>
<listitem>
<simpara>
instantiate <link linkend="class_promise"> <code>promise&lt;&gt;</code></link>
</simpara>
</listitem>
<listitem>
<simpara>
obtain its <code><phrase role="identifier">future</phrase><phrase role="special">&lt;&gt;</phrase></code>
via <link linkend="promise_get_future"> <code>promise::get_future()</code></link>
</simpara>
</listitem>
<listitem>
<simpara>
launch <link linkend="class_fiber"> <code>fiber</code></link>, capturing <code><phrase role="identifier">promise</phrase><phrase
role="special">&lt;&gt;</phrase></code>
</simpara>
</listitem>
<listitem>
<simpara>
destroy <code><phrase role="identifier">future</phrase><phrase role="special">&lt;&gt;</phrase></code>
</simpara>
</listitem>
<listitem>
<simpara>
call <link linkend="promise_set_value"> <code>promise::set_value()</code></link>
</simpara>
</listitem>
</orderedlist>
<para>
The final <code><phrase role="identifier">set_value</phrase><phrase role="special">()</phrase></code>
call succeeds, but the value is silently discarded: no additional <code><phrase
role="identifier">future</phrase><phrase role="special">&lt;&gt;</phrase></code>
can be obtained from that <code><phrase role="identifier">promise</phrase><phrase
role="special">&lt;&gt;</phrase></code>.
</para>
<para>
<bridgehead renderas="sect4" id="future_operator_assign_bridgehead">
<phrase id="future_operator_assign"/>
<link linkend="future_operator_assign">Member
function <code>operator=</code>()</link>
</bridgehead>
</para>
<programlisting><phrase role="identifier">future</phrase> <phrase role="special">&amp;</phrase> <phrase role="keyword">operator</phrase><phrase role="special">=(</phrase> <phrase role="identifier">future</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
</programlisting>
<variablelist>
<title></title>
<varlistentry>
<term>Effects:</term>
<listitem>
<para>
Moves the <link linkend="shared_state">shared state</link> of other
to <code><phrase role="keyword">this</phrase></code>. After the assignment,
<code><phrase role="keyword">false</phrase> <phrase role="special">==</phrase>
<phrase role="identifier">other</phrase><phrase role="special">.</phrase><phrase
role="identifier">valid</phrase><phrase role="special">()</phrase></code>.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Throws:</term>
<listitem>
<para>
Nothing.
</para>
</listitem>
</varlistentry>
</variablelist>
<para>
<bridgehead renderas="sect4" id="future_valid_bridgehead">
<phrase id="future_valid"/>
<link linkend="future_valid">Member function <code>valid</code>()</link>
</bridgehead>
</para>
<programlisting><phrase role="keyword">bool</phrase> <phrase role="identifier">valid</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
</programlisting>
<variablelist>
<title></title>
<varlistentry>
<term>Effects:</term>
<listitem>
<para>
Returns <code><phrase role="keyword">true</phrase></code> if future
contains a <link linkend="shared_state">shared state</link>.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Throws:</term>
<listitem>
<para>
Nothing.
</para>
</listitem>
</varlistentry>
</variablelist>
<para>
<bridgehead renderas="sect4" id="future_share_bridgehead">
<phrase id="future_share"/>
<link linkend="future_share">Member function <code>share</code>()</link>
</bridgehead>
</para>
<programlisting><phrase role="identifier">shared_future</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">R</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">share</phrase><phrase role="special">();</phrase>
</programlisting>
<variablelist>
<title></title>
<varlistentry>
<term>Effects:</term>
<listitem>
<para>
Move the state to a <link linkend="class_shared_future"> <code>shared_future&lt;&gt;</code></link>.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Returns:</term>
<listitem>
<para>
a <link linkend="class_shared_future"> <code>shared_future&lt;&gt;</code></link> containing the <link linkend="shared_state">shared
state</link> formerly belonging to <code><phrase role="special">*</phrase><phrase
role="keyword">this</phrase></code>.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Postcondition:</term>
<listitem>
<para>
<code><phrase role="keyword">false</phrase> <phrase role="special">==</phrase>
<phrase role="identifier">valid</phrase><phrase role="special">()</phrase></code>
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Throws:</term>
<listitem>
<para>
<code><phrase role="identifier">future_error</phrase></code> with
error condition <code><phrase role="identifier">future_errc</phrase><phrase
role="special">::</phrase><phrase role="identifier">no_state</phrase></code>.
</para>
</listitem>
</varlistentry>
</variablelist>
<para>
<bridgehead renderas="sect4" id="future_get_bridgehead">
<phrase id="future_get"/>
<link linkend="future_get">Member function <code>get</code>()</link>
</bridgehead>
</para>
<programlisting><phrase role="identifier">R</phrase> <phrase role="identifier">get</phrase><phrase role="special">();</phrase>
</programlisting>
<variablelist>
<title></title>
<varlistentry>
<term>Precondition:</term>
<listitem>
<para>
<code><phrase role="keyword">true</phrase> <phrase role="special">==</phrase>
<phrase role="identifier">valid</phrase><phrase role="special">()</phrase></code>
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Returns:</term>
<listitem>
<para>
Waits until <link linkend="promise_set_value"> <code>promise::set_value()</code></link> or <link linkend="promise_set_exception"> <code>promise::set_exception()</code></link> is
called. If <code><phrase role="identifier">set_value</phrase><phrase
role="special">()</phrase></code> is called, returns the value. If
<code><phrase role="identifier">set_exception</phrase><phrase role="special">()</phrase></code>
is called, throws the indicated exception.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Postcondition:</term>
<listitem>
<para>
<code><phrase role="keyword">false</phrase> <phrase role="special">==</phrase>
<phrase role="identifier">valid</phrase><phrase role="special">()</phrase></code>
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Throws:</term>
<listitem>
<para>
<code><phrase role="identifier">future_error</phrase></code> with
error condition <code><phrase role="identifier">future_errc</phrase><phrase
role="special">::</phrase><phrase role="identifier">no_state</phrase></code>,
or <code><phrase role="identifier">fiber_interrupted</phrase></code>.
Any exception passed to <code><phrase role="identifier">promise</phrase><phrase
role="special">::</phrase><phrase role="identifier">set_exception</phrase><phrase
role="special">()</phrase></code>.
</para>
</listitem>
</varlistentry>
</variablelist>
<para>
<bridgehead renderas="sect4" id="future_get_exception_ptr_bridgehead">
<phrase id="future_get_exception_ptr"/>
<link linkend="future_get_exception_ptr">Member
function <code>get_exception_ptr</code>()</link>
</bridgehead>
</para>
<programlisting><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">exception_ptr</phrase> <phrase role="identifier">get_exception_ptr</phrase><phrase role="special">();</phrase>
</programlisting>
<variablelist>
<title></title>
<varlistentry>
<term>Precondition:</term>
<listitem>
<para>
<code><phrase role="keyword">true</phrase> <phrase role="special">==</phrase>
<phrase role="identifier">valid</phrase><phrase role="special">()</phrase></code>
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Returns:</term>
<listitem>
<para>
Waits until <link linkend="promise_set_value"> <code>promise::set_value()</code></link> or <link linkend="promise_set_exception"> <code>promise::set_exception()</code></link> is
called. If <code><phrase role="identifier">set_value</phrase><phrase
role="special">()</phrase></code> is called, returns a default-constructed
<code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase
role="identifier">exception_ptr</phrase></code>. If <code><phrase
role="identifier">set_exception</phrase><phrase role="special">()</phrase></code>
is called, returns the passed <code><phrase role="identifier">std</phrase><phrase
role="special">::</phrase><phrase role="identifier">exception_ptr</phrase></code>.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Throws:</term>
<listitem>
<para>
<code><phrase role="identifier">future_error</phrase></code> with
error condition <code><phrase role="identifier">future_errc</phrase><phrase
role="special">::</phrase><phrase role="identifier">no_state</phrase></code>
or <code><phrase role="identifier">fiber_interrupted</phrase></code>.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Note:</term>
<listitem>
<para>
<code><phrase role="identifier">get_exception_ptr</phrase><phrase
role="special">()</phrase></code> does <emphasis>not</emphasis> invalidate
the <code>future</code>. After calling <code><phrase role="identifier">get_exception_ptr</phrase><phrase
role="special">()</phrase></code>, you may still call <link linkend="future_get"> <code>future::get()</code></link>.
</para>
</listitem>
</varlistentry>
</variablelist>
<para>
<bridgehead renderas="sect4" id="future_wait_bridgehead">
<phrase id="future_wait"/>
<link linkend="future_wait">Member function <code>wait</code>()</link>
</bridgehead>
</para>
<programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">wait</phrase><phrase role="special">();</phrase>
</programlisting>
<variablelist>
<title></title>
<varlistentry>
<term>Effects:</term>
<listitem>
<para>
Waits until <link linkend="promise_set_value"> <code>promise::set_value()</code></link> or <link linkend="promise_set_exception"> <code>promise::set_exception()</code></link> is
called.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Throws:</term>
<listitem>
<para>
<code><phrase role="identifier">future_error</phrase></code> with
error condition <code><phrase role="identifier">future_errc</phrase><phrase
role="special">::</phrase><phrase role="identifier">no_state</phrase></code>
or <code><phrase role="identifier">fiber_interrupted</phrase></code>.
</para>
</listitem>
</varlistentry>
</variablelist>
<para>
<bridgehead renderas="sect4" id="future_wait_for_bridgehead">
<phrase id="future_wait_for"/>
<link linkend="future_wait_for">Templated member
function <code>wait_for</code>()</link>
</bridgehead>
</para>
<programlisting><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">class</phrase> <phrase role="identifier">Rep</phrase><phrase role="special">,</phrase> <phrase role="keyword">class</phrase> <phrase role="identifier">Period</phrase> <phrase role="special">&gt;</phrase>
<phrase role="identifier">future_status</phrase> <phrase role="identifier">wait_for</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">duration</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Rep</phrase><phrase role="special">,</phrase> <phrase role="identifier">Period</phrase> <phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">timeout_duration</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
</programlisting>
<variablelist>
<title></title>
<varlistentry>
<term>Effects:</term>
<listitem>
<para>
Waits until <link linkend="promise_set_value"> <code>promise::set_value()</code></link> or <link linkend="promise_set_exception"> <code>promise::set_exception()</code></link> is
called, or <code><phrase role="identifier">timeout_duration</phrase></code>
has passed.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Result:</term>
<listitem>
<para>
A <code><phrase role="identifier">future_status</phrase></code> is
returned indicating the reason for returning.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Throws:</term>
<listitem>
<para>
<code><phrase role="identifier">future_error</phrase></code> with
error condition <code><phrase role="identifier">future_errc</phrase><phrase
role="special">::</phrase><phrase role="identifier">no_state</phrase></code>
or <code><phrase role="identifier">fiber_interrupted</phrase></code>.
</para>
</listitem>
</varlistentry>
</variablelist>
<para>
<bridgehead renderas="sect4" id="future_wait_until_bridgehead">
<phrase id="future_wait_until"/>
<link linkend="future_wait_until">Templated
member function <code>wait_until</code>()</link>
</bridgehead>
</para>
<programlisting><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Clock</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Duration</phrase> <phrase role="special">&gt;</phrase>
<phrase role="identifier">future_status</phrase> <phrase role="identifier">wait_until</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">time_point</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Clock</phrase><phrase role="special">,</phrase> <phrase role="identifier">Duration</phrase> <phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">timeout_time</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
</programlisting>
<variablelist>
<title></title>
<varlistentry>
<term>Effects:</term>
<listitem>
<para>
Waits until <link linkend="promise_set_value"> <code>promise::set_value()</code></link> or <link linkend="promise_set_exception"> <code>promise::set_exception()</code></link> is
called, or <code><phrase role="identifier">timeout_time</phrase></code>
has passed.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Result:</term>
<listitem>
<para>
A <code><phrase role="identifier">future_status</phrase></code> is
returned indicating the reason for returning.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Throws:</term>
<listitem>
<para>
<code><phrase role="identifier">future_error</phrase></code> with
error condition <code><phrase role="identifier">future_errc</phrase><phrase
role="special">::</phrase><phrase role="identifier">no_state</phrase></code>
or <code><phrase role="identifier">fiber_interrupted</phrase></code>.
</para>
</listitem>
</varlistentry>
</variablelist>
<para>
<bridgehead renderas="sect4" id="class_shared_future_bridgehead">
<phrase id="class_shared_future"/>
<link linkend="class_shared_future">Template
<code>shared_future&lt;&gt;</code></link>
</bridgehead>
</para>
<para>
A <link linkend="class_shared_future"> <code>shared_future&lt;&gt;</code></link> contains a <link linkend="shared_state">shared
state</link> which might be shared with other <link linkend="class_shared_future"> <code>shared_future&lt;&gt;</code></link> instances.
</para>
<programlisting><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">R</phrase> <phrase role="special">&gt;</phrase>
<phrase role="keyword">class</phrase> <phrase role="identifier">shared_future</phrase> <phrase role="special">{</phrase>
<phrase role="keyword">public</phrase><phrase role="special">:</phrase>
<phrase role="identifier">shared_future</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
<phrase role="special">~</phrase><phrase role="identifier">shared_future</phrase><phrase role="special">();</phrase>
<phrase role="identifier">shared_future</phrase><phrase role="special">(</phrase> <phrase role="identifier">shared_future</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">other</phrase><phrase role="special">);</phrase>
<phrase role="identifier">shared_future</phrase><phrase role="special">(</phrase> <phrase role="identifier">future</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">R</phrase> <phrase role="special">&gt;</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
<phrase role="identifier">shared_future</phrase><phrase role="special">(</phrase> <phrase role="identifier">shared_future</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
<phrase role="identifier">shared_future</phrase> <phrase role="special">&amp;</phrase> <phrase role="keyword">operator</phrase><phrase role="special">=(</phrase> <phrase role="identifier">shared_future</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
<phrase role="identifier">shared_future</phrase> <phrase role="special">&amp;</phrase> <phrase role="keyword">operator</phrase><phrase role="special">=(</phrase> <phrase role="identifier">future</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
<phrase role="identifier">shared_future</phrase> <phrase role="special">&amp;</phrase> <phrase role="keyword">operator</phrase><phrase role="special">=(</phrase> <phrase role="identifier">shared_future</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
<phrase role="keyword">bool</phrase> <phrase role="identifier">valid</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
<phrase role="identifier">R</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">get</phrase><phrase role="special">();</phrase> <phrase role="comment">// member only of generic shared_future template</phrase>
<phrase role="identifier">R</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">get</phrase><phrase role="special">();</phrase> <phrase role="comment">// member only of shared_future&lt; R &amp; &gt; template specialization</phrase>
<phrase role="keyword">void</phrase> <phrase role="identifier">get</phrase><phrase role="special">();</phrase> <phrase role="comment">// member only of shared_future&lt; void &gt; template specialization</phrase>
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">exception_ptr</phrase> <phrase role="identifier">get_exception_ptr</phrase><phrase role="special">();</phrase>
<phrase role="keyword">void</phrase> <phrase role="identifier">wait</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
<phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">class</phrase> <phrase role="identifier">Rep</phrase><phrase role="special">,</phrase> <phrase role="keyword">class</phrase> <phrase role="identifier">Period</phrase> <phrase role="special">&gt;</phrase>
<phrase role="identifier">future_status</phrase> <phrase role="identifier">wait_for</phrase><phrase role="special">(</phrase>
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">duration</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Rep</phrase><phrase role="special">,</phrase> <phrase role="identifier">Period</phrase> <phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">timeout_duration</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
<phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Clock</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Duration</phrase> <phrase role="special">&gt;</phrase>
<phrase role="identifier">future_status</phrase> <phrase role="identifier">wait_until</phrase><phrase role="special">(</phrase>
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">time_point</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Clock</phrase><phrase role="special">,</phrase> <phrase role="identifier">Duration</phrase> <phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">timeout_time</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
<phrase role="special">};</phrase>
</programlisting>
<bridgehead renderas="sect5" id="fiber.synchronization.futures.future.h7">
<phrase id="fiber.synchronization.futures.future.default_constructor0"/><link
linkend="fiber.synchronization.futures.future.default_constructor0">Default
constructor</link>
</bridgehead>
<programlisting><phrase role="identifier">shared_future</phrase><phrase role="special">();</phrase>
</programlisting>
<variablelist>
<title></title>
<varlistentry>
<term>Effects:</term>
<listitem>
<para>
Creates a shared_future with no <link linkend="shared_state">shared
state</link>. After construction <code><phrase role="keyword">false</phrase>
<phrase role="special">==</phrase> <phrase role="identifier">valid</phrase><phrase
role="special">()</phrase></code>.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Throws:</term>
<listitem>
<para>
Nothing.
</para>
</listitem>
</varlistentry>
</variablelist>
<bridgehead renderas="sect5" id="fiber.synchronization.futures.future.h8">
<phrase id="fiber.synchronization.futures.future.move_constructor0"/><link
linkend="fiber.synchronization.futures.future.move_constructor0">Move constructor</link>
</bridgehead>
<programlisting><phrase role="identifier">shared_future</phrase><phrase role="special">(</phrase> <phrase role="identifier">future</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
<phrase role="identifier">shared_future</phrase><phrase role="special">(</phrase> <phrase role="identifier">shared_future</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
</programlisting>
<variablelist>
<title></title>
<varlistentry>
<term>Effects:</term>
<listitem>
<para>
Constructs a shared_future with the <link linkend="shared_state">shared
state</link> of other. After construction <code><phrase role="keyword">false</phrase>
<phrase role="special">==</phrase> <phrase role="identifier">other</phrase><phrase
role="special">.</phrase><phrase role="identifier">valid</phrase><phrase
role="special">()</phrase></code>.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Throws:</term>
<listitem>
<para>
Nothing.
</para>
</listitem>
</varlistentry>
</variablelist>
<bridgehead renderas="sect5" id="fiber.synchronization.futures.future.h9">
<phrase id="fiber.synchronization.futures.future.copy_constructor"/><link
linkend="fiber.synchronization.futures.future.copy_constructor">Copy constructor</link>
</bridgehead>
<programlisting><phrase role="identifier">shared_future</phrase><phrase role="special">(</phrase> <phrase role="identifier">shared_future</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
</programlisting>
<variablelist>
<title></title>
<varlistentry>
<term>Effects:</term>
<listitem>
<para>
Constructs a shared_future with the <link linkend="shared_state">shared
state</link> of other. After construction <code><phrase role="identifier">other</phrase><phrase
role="special">.</phrase><phrase role="identifier">valid</phrase><phrase
role="special">()</phrase></code> is unchanged.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Throws:</term>
<listitem>
<para>
Nothing.
</para>
</listitem>
</varlistentry>
</variablelist>
<bridgehead renderas="sect5" id="fiber.synchronization.futures.future.h10">
<phrase id="fiber.synchronization.futures.future.destructor0"/><link linkend="fiber.synchronization.futures.future.destructor0">Destructor</link>
</bridgehead>
<programlisting><phrase role="special">~</phrase><phrase role="identifier">shared_future</phrase><phrase role="special">();</phrase>
</programlisting>
<variablelist>
<title></title>
<varlistentry>
<term>Effects:</term>
<listitem>
<para>
Destroys the shared_future; ownership is abandoned if not shared.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Throws:</term>
<listitem>
<para>
Nothing.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Note:</term>
<listitem>
<para>
<code>~shared_future()</code> does <emphasis>not</emphasis> block the calling fiber.
</para>
</listitem>
</varlistentry>
</variablelist>
<para>
<bridgehead renderas="sect4" id="shared_future_operator_assign_bridgehead">
<phrase id="shared_future_operator_assign"/>
<link linkend="shared_future_operator_assign">Member
function <code>operator=</code>()</link>
</bridgehead>
</para>
<programlisting><phrase role="identifier">shared_future</phrase> <phrase role="special">&amp;</phrase> <phrase role="keyword">operator</phrase><phrase role="special">=(</phrase> <phrase role="identifier">future</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
<phrase role="identifier">shared_future</phrase> <phrase role="special">&amp;</phrase> <phrase role="keyword">operator</phrase><phrase role="special">=(</phrase> <phrase role="identifier">shared_future</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
<phrase role="identifier">shared_future</phrase> <phrase role="special">&amp;</phrase> <phrase role="keyword">operator</phrase><phrase role="special">=(</phrase> <phrase role="identifier">shared_future</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
</programlisting>
<variablelist>
<title></title>
<varlistentry>
<term>Effects:</term>
<listitem>
<para>
Moves or copies the <link linkend="shared_state">shared state</link>
of other to <code><phrase role="keyword">this</phrase></code>. After
the assignment, the state of <code><phrase role="identifier">other</phrase><phrase
role="special">.</phrase><phrase role="identifier">valid</phrase><phrase
role="special">()</phrase></code> depends on which overload was invoked:
unchanged for the overload accepting <code><phrase role="identifier">shared_future</phrase>
<phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase></code>,
otherwise <code><phrase role="keyword">false</phrase></code>.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Throws:</term>
<listitem>
<para>
Nothing.
</para>
</listitem>
</varlistentry>
</variablelist>
<para>
<bridgehead renderas="sect4" id="shared_future_valid_bridgehead">
<phrase id="shared_future_valid"/>
<link linkend="shared_future_valid">Member
function <code>valid</code>()</link>
</bridgehead>
</para>
<programlisting><phrase role="keyword">bool</phrase> <phrase role="identifier">valid</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
</programlisting>
<variablelist>
<title></title>
<varlistentry>
<term>Effects:</term>
<listitem>
<para>
Returns <code><phrase role="keyword">true</phrase></code> if shared_future
contains a <link linkend="shared_state">shared state</link>.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Throws:</term>
<listitem>
<para>
Nothing.
</para>
</listitem>
</varlistentry>
</variablelist>
<para>
<bridgehead renderas="sect4" id="shared_future_get_bridgehead">
<phrase id="shared_future_get"/>
<link linkend="shared_future_get">Member function
<code>get</code>()</link>
</bridgehead>
</para>
<programlisting><phrase role="identifier">R</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">get</phrase><phrase role="special">();</phrase> <phrase role="comment">// member only of generic shared_future template</phrase>
<phrase role="identifier">R</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">get</phrase><phrase role="special">();</phrase> <phrase role="comment">// member only of shared_future&lt; R &amp; &gt; template specialization</phrase>
<phrase role="keyword">void</phrase> <phrase role="identifier">get</phrase><phrase role="special">();</phrase> <phrase role="comment">// member only of shared_future&lt; void &gt; template specialization</phrase>
</programlisting>
<variablelist>
<title></title>
<varlistentry>
<term>Precondition:</term>
<listitem>
<para>
<code><phrase role="keyword">true</phrase> <phrase role="special">==</phrase>
<phrase role="identifier">valid</phrase><phrase role="special">()</phrase></code>
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Returns:</term>
<listitem>
<para>
Waits until <link linkend="promise_set_value"> <code>promise::set_value()</code></link> or <link linkend="promise_set_exception"> <code>promise::set_exception()</code></link> is
called. If <code><phrase role="identifier">set_value</phrase><phrase
role="special">()</phrase></code> is called, returns the value. If
<code><phrase role="identifier">set_exception</phrase><phrase role="special">()</phrase></code>
is called, throws the indicated exception.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Postcondition:</term>
<listitem>
<para>
<code><phrase role="keyword">false</phrase> <phrase role="special">==</phrase>
<phrase role="identifier">valid</phrase><phrase role="special">()</phrase></code>
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Throws:</term>
<listitem>
<para>
<code><phrase role="identifier">future_error</phrase></code> with
error condition <code><phrase role="identifier">future_errc</phrase><phrase
role="special">::</phrase><phrase role="identifier">no_state</phrase></code>,
or <code><phrase role="identifier">fiber_interrupted</phrase></code>.
Any exception passed to <code><phrase role="identifier">promise</phrase><phrase
role="special">::</phrase><phrase role="identifier">set_exception</phrase><phrase
role="special">()</phrase></code>.
</para>
</listitem>
</varlistentry>
</variablelist>
<para>
<bridgehead renderas="sect4" id="shared_future_get_exception_ptr_bridgehead">
<phrase id="shared_future_get_exception_ptr"/>
<link linkend="shared_future_get_exception_ptr">Member
function <code>get_exception_ptr</code>()</link>
</bridgehead>
</para>
<programlisting><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">exception_ptr</phrase> <phrase role="identifier">get_exception_ptr</phrase><phrase role="special">();</phrase>
</programlisting>
<variablelist>
<title></title>
<varlistentry>
<term>Precondition:</term>
<listitem>
<para>
<code><phrase role="keyword">true</phrase> <phrase role="special">==</phrase>
<phrase role="identifier">valid</phrase><phrase role="special">()</phrase></code>
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Returns:</term>
<listitem>
<para>
Waits until <link linkend="promise_set_value"> <code>promise::set_value()</code></link> or <link linkend="promise_set_exception"> <code>promise::set_exception()</code></link> is
called. If <code><phrase role="identifier">set_value</phrase><phrase
role="special">()</phrase></code> is called, returns a default-constructed
<code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase
role="identifier">exception_ptr</phrase></code>. If <code><phrase
role="identifier">set_exception</phrase><phrase role="special">()</phrase></code>
is called, returns the passed <code><phrase role="identifier">std</phrase><phrase
role="special">::</phrase><phrase role="identifier">exception_ptr</phrase></code>.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Throws:</term>
<listitem>
<para>
<code><phrase role="identifier">future_error</phrase></code> with
error condition <code><phrase role="identifier">future_errc</phrase><phrase
role="special">::</phrase><phrase role="identifier">no_state</phrase></code>
or <code><phrase role="identifier">fiber_interrupted</phrase></code>.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Note:</term>
<listitem>
<para>
<code><phrase role="identifier">get_exception_ptr</phrase><phrase
role="special">()</phrase></code> does <emphasis>not</emphasis> invalidate
the <code>shared_future</code>. After calling <code><phrase role="identifier">get_exception_ptr</phrase><phrase
role="special">()</phrase></code>, you may still call <link linkend="shared_future_get"> <code>shared_future::get()</code></link>.
</para>
</listitem>
</varlistentry>
</variablelist>
<para>
<bridgehead renderas="sect4" id="shared_future_wait_bridgehead">
<phrase id="shared_future_wait"/>
<link linkend="shared_future_wait">Member
function <code>wait</code>()</link>
</bridgehead>
</para>
<programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">wait</phrase><phrase role="special">();</phrase>
</programlisting>
<variablelist>
<title></title>
<varlistentry>
<term>Effects:</term>
<listitem>
<para>
Waits until <link linkend="promise_set_value"> <code>promise::set_value()</code></link> or <link linkend="promise_set_exception"> <code>promise::set_exception()</code></link> is
called.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Throws:</term>
<listitem>
<para>
<code><phrase role="identifier">future_error</phrase></code> with
error condition <code><phrase role="identifier">future_errc</phrase><phrase
role="special">::</phrase><phrase role="identifier">no_state</phrase></code>
or <code><phrase role="identifier">fiber_interrupted</phrase></code>.
</para>
</listitem>
</varlistentry>
</variablelist>
<para>
<bridgehead renderas="sect4" id="shared_future_wait_for_bridgehead">
<phrase id="shared_future_wait_for"/>
<link linkend="shared_future_wait_for">Templated
member function <code>wait_for</code>()</link>
</bridgehead>
</para>
<programlisting><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">class</phrase> <phrase role="identifier">Rep</phrase><phrase role="special">,</phrase> <phrase role="keyword">class</phrase> <phrase role="identifier">Period</phrase> <phrase role="special">&gt;</phrase>
<phrase role="identifier">future_status</phrase> <phrase role="identifier">wait_for</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">duration</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Rep</phrase><phrase role="special">,</phrase> <phrase role="identifier">Period</phrase> <phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">timeout_duration</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
</programlisting>
<variablelist>
<title></title>
<varlistentry>
<term>Effects:</term>
<listitem>
<para>
Waits until <link linkend="promise_set_value"> <code>promise::set_value()</code></link> or <link linkend="promise_set_exception"> <code>promise::set_exception()</code></link> is
called, or <code><phrase role="identifier">timeout_duration</phrase></code>
has passed.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Result:</term>
<listitem>
<para>
A <code><phrase role="identifier">future_status</phrase></code> is
returned indicating the reason for returning.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Throws:</term>
<listitem>
<para>
<code><phrase role="identifier">future_error</phrase></code> with
error condition <code><phrase role="identifier">future_errc</phrase><phrase
role="special">::</phrase><phrase role="identifier">no_state</phrase></code>
or <code><phrase role="identifier">fiber_interrupted</phrase></code>.
</para>
</listitem>
</varlistentry>
</variablelist>
<para>
<bridgehead renderas="sect4" id="shared_future_wait_until_bridgehead">
<phrase id="shared_future_wait_until"/>
<link linkend="shared_future_wait_until">Templated
member function <code>wait_until</code>()</link>
</bridgehead>
</para>
<programlisting><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Clock</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Duration</phrase> <phrase role="special">&gt;</phrase>
<phrase role="identifier">future_status</phrase> <phrase role="identifier">wait_until</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">time_point</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Clock</phrase><phrase role="special">,</phrase> <phrase role="identifier">Duration</phrase> <phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">timeout_time</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
</programlisting>
<variablelist>
<title></title>
<varlistentry>
<term>Effects:</term>
<listitem>
<para>
Waits until <link linkend="promise_set_value"> <code>promise::set_value()</code></link> or <link linkend="promise_set_exception"> <code>promise::set_exception()</code></link> is
called, or <code><phrase role="identifier">timeout_time</phrase></code>
has passed.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Result:</term>
<listitem>
<para>
A <code><phrase role="identifier">future_status</phrase></code> is
returned indicating the reason for returning.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Throws:</term>
<listitem>
<para>
<code><phrase role="identifier">future_error</phrase></code> with
error condition <code><phrase role="identifier">future_errc</phrase><phrase
role="special">::</phrase><phrase role="identifier">no_state</phrase></code>
or <code><phrase role="identifier">fiber_interrupted</phrase></code>.
</para>
</listitem>
</varlistentry>
</variablelist>
<para>
<bridgehead renderas="sect4" id="fibers_async_bridgehead">
<phrase id="fibers_async"/>
<link linkend="fibers_async">Non-member function <code>fibers::async()</code></link>
</bridgehead>
</para>
<programlisting><phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">fiber</phrase><phrase role="special">/</phrase><phrase role="identifier">future</phrase><phrase role="special">/</phrase><phrase role="identifier">async</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</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="special">...</phrase> <phrase role="identifier">Args</phrase> <phrase role="special">&gt;</phrase>
<phrase role="identifier">future</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">result_of</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Fn</phrase><phrase role="special">&amp;&amp;(</phrase> <phrase role="identifier">Args</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="special">...</phrase> <phrase role="special">)</phrase> <phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase> <phrase role="special">&gt;</phrase>
<phrase role="identifier">async</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">Args</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="special">...</phrase> <phrase role="identifier">args</phrase><phrase role="special">);</phrase>
<phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">StackAllocator</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Fn</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="special">...</phrase> <phrase role="identifier">Args</phrase> <phrase role="special">&gt;</phrase>
<phrase role="identifier">future</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">result_of</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Fn</phrase><phrase role="special">&amp;&amp;(</phrase> <phrase role="identifier">Args</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="special">...</phrase> <phrase role="special">)</phrase> <phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase> <phrase role="special">&gt;</phrase>
<phrase role="identifier">async</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">allocator_arg_t</phrase><phrase role="special">,</phrase> <phrase role="identifier">StackAllocator</phrase> <phrase role="identifier">salloc</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">Args</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="special">...</phrase> <phrase role="identifier">args</phrase><phrase role="special">);</phrase>
</programlisting>
<variablelist>
<title></title>
<varlistentry>
<term>Effects:</term>
<listitem>
<para>
Executes <code><phrase role="identifier">fn</phrase></code> in a
<link linkend="class_fiber"> <code>fiber</code></link> and returns an associated <link linkend="class_future"> <code>future&lt;&gt;</code></link>.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Result:</term>
<listitem>
<para>
<code><phrase role="identifier">future</phrase><phrase role="special">&lt;</phrase>
<phrase role="keyword">typename</phrase> <phrase role="identifier">result_of</phrase><phrase
role="special">&lt;</phrase> <phrase role="identifier">Fn</phrase>
<phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase>
<phrase role="special">&gt;</phrase></code> representing the <link
linkend="shared_state">shared state</link> associated with the asynchronous
execution of <code><phrase role="identifier">fn</phrase></code>.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Throws:</term>
<listitem>
<para>
<code><phrase role="identifier">fiber_exception</phrase></code> or
<code><phrase role="identifier">future_error</phrase></code> if an
error occurs.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Notes:</term>
<listitem>
<para>
The overload accepting <ulink url="http://en.cppreference.com/w/cpp/memory/allocator_arg_t"><code><phrase
role="identifier">std</phrase><phrase role="special">::</phrase><phrase
role="identifier">allocator_arg_t</phrase></code></ulink> uses the
passed <code><phrase role="identifier">StackAllocator</phrase></code>
when constructing the launched <code><phrase role="identifier">fiber</phrase></code>.
</para>
</listitem>
</varlistentry>
</variablelist>
</section>
<section id="fiber.synchronization.futures.promise">
<title><anchor id="class_promise"/><link linkend="fiber.synchronization.futures.promise">Template
<code><phrase role="identifier">promise</phrase><phrase role="special">&lt;&gt;</phrase></code></link></title>
<para>
A <link linkend="class_promise"> <code>promise&lt;&gt;</code></link> provides a mechanism to store a value (or
exception) that can later be retrieved from the corresponding <link linkend="class_future"> <code>future&lt;&gt;</code></link> object.
<code><phrase role="identifier">promise</phrase><phrase role="special">&lt;&gt;</phrase></code>
and <code><phrase role="identifier">future</phrase><phrase role="special">&lt;&gt;</phrase></code>
communicate via their underlying <link linkend="shared_state">shared state</link>.
</para>
<programlisting><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">R</phrase> <phrase role="special">&gt;</phrase>
<phrase role="keyword">class</phrase> <phrase role="identifier">promise</phrase> <phrase role="special">{</phrase>
<phrase role="keyword">public</phrase><phrase role="special">:</phrase>
<phrase role="identifier">promise</phrase><phrase role="special">();</phrase>
<phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Allocator</phrase> <phrase role="special">&gt;</phrase>
<phrase role="identifier">promise</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">allocator_arg_t</phrase><phrase role="special">,</phrase> <phrase role="identifier">Allocator</phrase> <phrase role="identifier">alloc</phrase><phrase role="special">);</phrase>
<phrase role="identifier">promise</phrase><phrase role="special">(</phrase> <phrase role="identifier">promise</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
<phrase role="identifier">promise</phrase><phrase role="special">(</phrase> <phrase role="identifier">promise</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="special">=</phrase> <phrase role="keyword">delete</phrase><phrase role="special">;</phrase>
<phrase role="special">~</phrase><phrase role="identifier">promise</phrase><phrase role="special">();</phrase>
<phrase role="identifier">promise</phrase> <phrase role="special">&amp;</phrase> <phrase role="keyword">operator</phrase><phrase role="special">=(</phrase> <phrase role="identifier">promise</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
<phrase role="identifier">promise</phrase> <phrase role="special">&amp;</phrase> <phrase role="keyword">operator</phrase><phrase role="special">=(</phrase> <phrase role="identifier">promise</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="special">=</phrase> <phrase role="keyword">delete</phrase><phrase role="special">;</phrase>
<phrase role="keyword">void</phrase> <phrase role="identifier">swap</phrase><phrase role="special">(</phrase> <phrase role="identifier">promise</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
<phrase role="identifier">future</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">R</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">get_future</phrase><phrase role="special">();</phrase>
<phrase role="keyword">void</phrase> <phrase role="identifier">set_value</phrase><phrase role="special">(</phrase> <phrase role="identifier">R</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">value</phrase><phrase role="special">);</phrase>
<phrase role="keyword">void</phrase> <phrase role="identifier">set_value</phrase><phrase role="special">(</phrase> <phrase role="identifier">R</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="identifier">value</phrase><phrase role="special">);</phrase>
<phrase role="keyword">void</phrase> <phrase role="identifier">set_exception</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">exception_ptr</phrase> <phrase role="identifier">p</phrase><phrase role="special">);</phrase>
<phrase role="special">};</phrase>
</programlisting>
<bridgehead renderas="sect5" id="fiber.synchronization.futures.promise.h0">
<phrase id="fiber.synchronization.futures.promise.default_constructor"/><link
linkend="fiber.synchronization.futures.promise.default_constructor">Default
constructor</link>
</bridgehead>
<programlisting><phrase role="identifier">promise</phrase><phrase role="special">();</phrase>
</programlisting>
<variablelist>
<title></title>
<varlistentry>
<term>Effects:</term>
<listitem>
<para>
Creates a promise with an empty <link linkend="shared_state">shared
state</link>.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Throws:</term>
<listitem>
<para>
Nothing.
</para>
</listitem>
</varlistentry>
</variablelist>
<bridgehead renderas="sect5" id="fiber.synchronization.futures.promise.h1">
<phrase id="fiber.synchronization.futures.promise.constructor"/><link linkend="fiber.synchronization.futures.promise.constructor">Constructor</link>
</bridgehead>
<programlisting><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Allocator</phrase> <phrase role="special">&gt;</phrase>
<phrase role="identifier">promise</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">allocator_arg_t</phrase><phrase role="special">,</phrase> <phrase role="identifier">Allocator</phrase> <phrase role="identifier">alloc</phrase><phrase role="special">);</phrase>
</programlisting>
<variablelist>
<title></title>
<varlistentry>
<term>Effects:</term>
<listitem>
<para>
Creates a promise with an empty <link linkend="shared_state">shared
state</link> by using <code><phrase role="identifier">alloc</phrase></code>.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Throws:</term>
<listitem>
<para>
Nothing.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>See also:</term>
<listitem>
<para>
<ulink url="http://en.cppreference.com/w/cpp/memory/allocator_arg_t"><code><phrase
role="identifier">std</phrase><phrase role="special">::</phrase><phrase
role="identifier">allocator_arg_t</phrase></code></ulink>
</para>
</listitem>
</varlistentry>
</variablelist>
<bridgehead renderas="sect5" id="fiber.synchronization.futures.promise.h2">
<phrase id="fiber.synchronization.futures.promise.move_constructor"/><link
linkend="fiber.synchronization.futures.promise.move_constructor">Move constructor</link>
</bridgehead>
<programlisting><phrase role="identifier">promise</phrase><phrase role="special">(</phrase> <phrase role="identifier">promise</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
</programlisting>
<variablelist>
<title></title>
<varlistentry>
<term>Effects:</term>
<listitem>
<para>
Creates a promise by moving the <link linkend="shared_state">shared
state</link> from <code><phrase role="identifier">other</phrase></code>.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Postcondition:</term>
<listitem>
<para>
<code><phrase role="identifier">other</phrase></code> contains no
valid shared state.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Throws:</term>
<listitem>
<para>
Nothing.
</para>
</listitem>
</varlistentry>
</variablelist>
<bridgehead renderas="sect5" id="fiber.synchronization.futures.promise.h3">
<phrase id="fiber.synchronization.futures.promise.destructor"/><link linkend="fiber.synchronization.futures.promise.destructor">Destructor</link>
</bridgehead>
<programlisting><phrase role="special">~</phrase><phrase role="identifier">promise</phrase><phrase role="special">();</phrase>
</programlisting>
<variablelist>
<title></title>
<varlistentry>
<term>Effects:</term>
<listitem>
<para>
Destroys <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>
and abandons the <link linkend="shared_state">shared state</link>
if shared state is ready; otherwise stores <code><phrase role="identifier">future_error</phrase></code>
with error condition <code><phrase role="identifier">future_errc</phrase><phrase
role="special">::</phrase><phrase role="identifier">broken_promise</phrase></code>.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Throws:</term>
<listitem>
<para>
Nothing.
</para>
</listitem>
</varlistentry>
</variablelist>
<para>
<bridgehead renderas="sect4" id="promise_operator_assign_bridgehead">
<phrase id="promise_operator_assign"/>
<link linkend="promise_operator_assign">Member
function <code>operator=</code>()</link>
</bridgehead>
</para>
<programlisting><phrase role="identifier">promise</phrase> <phrase role="special">&amp;</phrase> <phrase role="keyword">operator</phrase><phrase role="special">=(</phrase> <phrase role="identifier">promise</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
</programlisting>
<variablelist>
<title></title>
<varlistentry>
<term>Effects:</term>
<listitem>
<para>
Transfers the ownership of <link linkend="shared_state">shared state</link>
to <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Postcondition:</term>
<listitem>
<para>
<code><phrase role="identifier">other</phrase></code> contains no
valid shared state.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Throws:</term>
<listitem>
<para>
Nothing.
</para>
</listitem>
</varlistentry>
</variablelist>
<para>
<bridgehead renderas="sect4" id="promise_swap_bridgehead">
<phrase id="promise_swap"/>
<link linkend="promise_swap">Member function <code>swap</code>()</link>
</bridgehead>
</para>
<programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">swap</phrase><phrase role="special">(</phrase> <phrase role="identifier">promise</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
</programlisting>
<variablelist>
<title></title>
<varlistentry>
<term>Effects:</term>
<listitem>
<para>
Swaps the <link linkend="shared_state">shared state</link> between
other and <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Throws:</term>
<listitem>
<para>
Nothing.
</para>
</listitem>
</varlistentry>
</variablelist>
<para>
<bridgehead renderas="sect4" id="promise_get_future_bridgehead">
<phrase id="promise_get_future"/>
<link linkend="promise_get_future">Member
function <code>get_future</code>()</link>
</bridgehead>
</para>
<programlisting><phrase role="identifier">future</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">R</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">get_future</phrase><phrase role="special">();</phrase>
</programlisting>
<variablelist>
<title></title>
<varlistentry>
<term>Returns:</term>
<listitem>
<para>
A <link linkend="class_future"> <code>future&lt;&gt;</code></link> with the same <link linkend="shared_state">shared
state</link>.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Throws:</term>
<listitem>
<para>
<code><phrase role="identifier">future_error</phrase></code> with
<code><phrase role="identifier">future_errc</phrase><phrase role="special">::</phrase><phrase
role="identifier">future_already_retrieved</phrase></code> or <code><phrase
role="identifier">future_errc</phrase><phrase role="special">::</phrase><phrase
role="identifier">no_state</phrase></code>.
</para>
</listitem>
</varlistentry>
</variablelist>
<para>
<bridgehead renderas="sect4" id="promise_set_value_bridgehead">
<phrase id="promise_set_value"/>
<link linkend="promise_set_value">Member function
<code>set_value</code>()</link>
</bridgehead>
</para>
<programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">set_value</phrase><phrase role="special">(</phrase> <phrase role="identifier">R</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">value</phrase><phrase role="special">);</phrase>
<phrase role="keyword">void</phrase> <phrase role="identifier">set_value</phrase><phrase role="special">(</phrase> <phrase role="identifier">R</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="identifier">value</phrase><phrase role="special">);</phrase>
</programlisting>
<variablelist>
<title></title>
<varlistentry>
<term>Effects:</term>
<listitem>
<para>
Store the result in the <link linkend="shared_state">shared state</link>
and marks the state as ready.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Throws:</term>
<listitem>
<para>
<code><phrase role="identifier">future_error</phrase></code> with
<code><phrase role="identifier">future_errc</phrase><phrase role="special">::</phrase><phrase
role="identifier">future_already_satisfied</phrase></code> or <code><phrase
role="identifier">future_errc</phrase><phrase role="special">::</phrase><phrase
role="identifier">no_state</phrase></code>.
</para>
</listitem>
</varlistentry>
</variablelist>
<para>
<bridgehead renderas="sect4" id="promise_set_exception_bridgehead">
<phrase id="promise_set_exception"/>
<link linkend="promise_set_exception">Member
function <code>set_exception</code>()</link>
</bridgehead>
</para>
<programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">set_exception</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">exception_ptr</phrase><phrase role="special">);</phrase>
</programlisting>
<variablelist>
<title></title>
<varlistentry>
<term>Effects:</term>
<listitem>
<para>
Store an exception pointer in the <link linkend="shared_state">shared
state</link> and marks the state as ready.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Throws:</term>
<listitem>
<para>
<code><phrase role="identifier">future_error</phrase></code> with
<code><phrase role="identifier">future_errc</phrase><phrase role="special">::</phrase><phrase
role="identifier">future_already_satisfied</phrase></code> or <code><phrase
role="identifier">future_errc</phrase><phrase role="special">::</phrase><phrase
role="identifier">no_state</phrase></code>.
</para>
</listitem>
</varlistentry>
</variablelist>
</section>
<section id="fiber.synchronization.futures.packaged_task">
<title><anchor id="class_packaged_task"/><link linkend="fiber.synchronization.futures.packaged_task">Template
<code><phrase role="identifier">packaged_task</phrase><phrase role="special">&lt;&gt;</phrase></code></link></title>
<para>
A <link linkend="class_packaged_task"> <code>packaged_task&lt;&gt;</code></link> wraps a callable target that
returns a value so that the return value can be computed asynchronously.
</para>
<para>
Conventional usage of <code><phrase role="identifier">packaged_task</phrase><phrase
role="special">&lt;&gt;</phrase></code> is like this:
</para>
<orderedlist>
<listitem>
<simpara>
Instantiate <code><phrase role="identifier">packaged_task</phrase><phrase
role="special">&lt;&gt;</phrase></code> with template arguments matching
the signature of the callable. Pass the callable to the <link linkend="packaged_task_packaged_task">constructor</link>.
</simpara>
</listitem>
<listitem>
<simpara>
Call <link linkend="packaged_task_get_future"> <code>packaged_task::get_future()</code></link> and capture
the returned <link linkend="class_future"> <code>future&lt;&gt;</code></link> instance.
</simpara>
</listitem>
<listitem>
<simpara>
Launch a <link linkend="class_fiber"> <code>fiber</code></link> to run the new <code><phrase role="identifier">packaged_task</phrase><phrase
role="special">&lt;&gt;</phrase></code>, passing any arguments required
by the original callable.
</simpara>
</listitem>
<listitem>
<simpara>
Call <link linkend="fiber_detach"> <code>fiber::detach()</code></link> on the newly-launched <code><phrase
role="identifier">fiber</phrase></code>.
</simpara>
</listitem>
<listitem>
<simpara>
At some later point, retrieve the result from the <code><phrase role="identifier">future</phrase><phrase
role="special">&lt;&gt;</phrase></code>.
</simpara>
</listitem>
</orderedlist>
<para>
This is, in fact, pretty much what <link linkend="fibers_async"> <code>fibers::async()</code></link>
encapsulates.
</para>
<programlisting><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">class</phrase> <phrase role="identifier">R</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="special">...</phrase> <phrase role="identifier">Args</phrase> <phrase role="special">&gt;</phrase>
<phrase role="keyword">class</phrase> <phrase role="identifier">packaged_task</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">R</phrase><phrase role="special">(</phrase> <phrase role="identifier">Args</phrase> <phrase role="special">...</phrase> <phrase role="special">)</phrase> <phrase role="special">&gt;</phrase> <phrase role="special">{</phrase>
<phrase role="keyword">public</phrase><phrase role="special">:</phrase>
<phrase role="identifier">packaged_task</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</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="keyword">explicit</phrase> <phrase role="identifier">packaged_task</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="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="keyword">explicit</phrase> <phrase role="identifier">packaged_task</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">allocator_arg_t</phrase><phrase role="special">,</phrase> <phrase role="identifier">Allocator</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">alloc</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">packaged_task</phrase><phrase role="special">(</phrase> <phrase role="identifier">packaged_task</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
<phrase role="identifier">packaged_task</phrase><phrase role="special">(</phrase> <phrase role="identifier">packaged_task</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="special">=</phrase> <phrase role="keyword">delete</phrase><phrase role="special">;</phrase>
<phrase role="special">~</phrase><phrase role="identifier">packaged_task</phrase><phrase role="special">();</phrase>
<phrase role="identifier">packaged_task</phrase> <phrase role="special">&amp;</phrase> <phrase role="keyword">operator</phrase><phrase role="special">=(</phrase> <phrase role="identifier">packaged_task</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
<phrase role="identifier">packaged_task</phrase> <phrase role="special">&amp;</phrase> <phrase role="keyword">operator</phrase><phrase role="special">=(</phrase> <phrase role="identifier">packaged_task</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="special">=</phrase> <phrase role="keyword">delete</phrase><phrase role="special">;</phrase>
<phrase role="keyword">void</phrase> <phrase role="identifier">swap</phrase><phrase role="special">(</phrase> <phrase role="identifier">packaged_task</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
<phrase role="keyword">bool</phrase> <phrase role="identifier">valid</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
<phrase role="identifier">future</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">R</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">get_future</phrase><phrase role="special">();</phrase>
<phrase role="keyword">void</phrase> <phrase role="keyword">operator</phrase><phrase role="special">()(</phrase> <phrase role="identifier">Args</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="special">...</phrase> <phrase role="identifier">args</phrase><phrase role="special">);</phrase>
<phrase role="keyword">void</phrase> <phrase role="identifier">reset</phrase><phrase role="special">();</phrase>
<phrase role="special">};</phrase>
</programlisting>
<bridgehead renderas="sect5" id="fiber.synchronization.futures.packaged_task.h0">
<phrase id="fiber.synchronization.futures.packaged_task.default_constructor__code__phrase_role__identifier__packaged_task__phrase__phrase_role__special______phrase___code_"/><link
linkend="fiber.synchronization.futures.packaged_task.default_constructor__code__phrase_role__identifier__packaged_task__phrase__phrase_role__special______phrase___code_">Default
constructor <code><phrase role="identifier">packaged_task</phrase><phrase
role="special">()</phrase></code></link>
</bridgehead>
<programlisting><phrase role="identifier">packaged_task</phrase><phrase role="special">();</phrase>
</programlisting>
<variablelist>
<title></title>
<varlistentry>
<term>Effects:</term>
<listitem>
<para>
Constructs an object of class <code><phrase role="identifier">packaged_task</phrase></code>
with no <link linkend="shared_state">shared state</link>.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Throws:</term>
<listitem>
<para>
Nothing.
</para>
</listitem>
</varlistentry>
</variablelist>
<anchor id="packaged_task_packaged_task"/>
<bridgehead renderas="sect5" id="fiber.synchronization.futures.packaged_task.h1">
<phrase id="fiber.synchronization.futures.packaged_task.templated_constructor__code__phrase_role__keyword__template__phrase__phrase_role__special___lt__gt___phrase___phrase_role__identifier__packaged_task__phrase__phrase_role__special______phrase___code_"/><link
linkend="fiber.synchronization.futures.packaged_task.templated_constructor__code__phrase_role__keyword__template__phrase__phrase_role__special___lt__gt___phrase___phrase_role__identifier__packaged_task__phrase__phrase_role__special______phrase___code_">Templated
constructor <code><phrase role="keyword">template</phrase><phrase role="special">&lt;&gt;</phrase>
<phrase role="identifier">packaged_task</phrase><phrase role="special">()</phrase></code></link>
</bridgehead>
<programlisting><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="keyword">explicit</phrase> <phrase role="identifier">packaged_task</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="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="keyword">explicit</phrase> <phrase role="identifier">packaged_task</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">allocator_arg_t</phrase><phrase role="special">,</phrase> <phrase role="identifier">Allocator</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">alloc</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>
</programlisting>
<variablelist>
<title></title>
<varlistentry>
<term>Effects:</term>
<listitem>
<para>
Constructs an object of class <code><phrase role="identifier">packaged_task</phrase></code>
with a <link linkend="shared_state">shared state</link> and stores
the callable target <code><phrase role="identifier">fn</phrase></code>
internally.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Throws:</term>
<listitem>
<para>
Nothing.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Note:</term>
<listitem>
<para>
The signature of <code><phrase role="identifier">Fn</phrase></code>
should have a return type convertible to <code><phrase role="identifier">R</phrase></code>.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>See also:</term>
<listitem>
<para>
<ulink url="http://en.cppreference.com/w/cpp/memory/allocator_arg_t"><code><phrase
role="identifier">std</phrase><phrase role="special">::</phrase><phrase
role="identifier">allocator_arg_t</phrase></code></ulink>
</para>
</listitem>
</varlistentry>
</variablelist>
<bridgehead renderas="sect5" id="fiber.synchronization.futures.packaged_task.h2">
<phrase id="fiber.synchronization.futures.packaged_task.move_constructor"/><link
linkend="fiber.synchronization.futures.packaged_task.move_constructor">Move
constructor</link>
</bridgehead>
<programlisting><phrase role="identifier">packaged_task</phrase><phrase role="special">(</phrase> <phrase role="identifier">packaged_task</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
</programlisting>
<variablelist>
<title></title>
<varlistentry>
<term>Effects:</term>
<listitem>
<para>
Creates a packaged_task by moving the <link linkend="shared_state">shared
state</link> from <code><phrase role="identifier">other</phrase></code>.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Postcondition:</term>
<listitem>
<para>
<code><phrase role="identifier">other</phrase></code> contains no
valid shared state.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Throws:</term>
<listitem>
<para>
Nothing.
</para>
</listitem>
</varlistentry>
</variablelist>
<bridgehead renderas="sect5" id="fiber.synchronization.futures.packaged_task.h3">
<phrase id="fiber.synchronization.futures.packaged_task.destructor"/><link
linkend="fiber.synchronization.futures.packaged_task.destructor">Destructor</link>
</bridgehead>
<programlisting><phrase role="special">~</phrase><phrase role="identifier">packaged_task</phrase><phrase role="special">();</phrase>
</programlisting>
<variablelist>
<title></title>
<varlistentry>
<term>Effects:</term>
<listitem>
<para>
Destroys <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>
and abandons the <link linkend="shared_state">shared state</link>
if shared state is ready; otherwise stores <code><phrase role="identifier">future_error</phrase></code>
with error condition <code><phrase role="identifier">future_errc</phrase><phrase
role="special">::</phrase><phrase role="identifier">broken_promise</phrase></code>.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Throws:</term>
<listitem>
<para>
Nothing.
</para>
</listitem>
</varlistentry>
</variablelist>
<para>
<bridgehead renderas="sect4" id="packaged_task_operator_assign_bridgehead">
<phrase id="packaged_task_operator_assign"/>
<link linkend="packaged_task_operator_assign">Member
function <code>operator=</code>()</link>
</bridgehead>
</para>
<programlisting><phrase role="identifier">packaged_task</phrase> <phrase role="special">&amp;</phrase> <phrase role="keyword">operator</phrase><phrase role="special">=(</phrase> <phrase role="identifier">packaged_task</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
</programlisting>
<variablelist>
<title></title>
<varlistentry>
<term>Effects:</term>
<listitem>
<para>
Transfers the ownership of <link linkend="shared_state">shared state</link>
to <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Postcondition:</term>
<listitem>
<para>
<code><phrase role="identifier">other</phrase></code> contains no
valid shared state.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Throws:</term>
<listitem>
<para>
Nothing.
</para>
</listitem>
</varlistentry>
</variablelist>
<para>
<bridgehead renderas="sect4" id="packaged_task_swap_bridgehead">
<phrase id="packaged_task_swap"/>
<link linkend="packaged_task_swap">Member
function <code>swap</code>()</link>
</bridgehead>
</para>
<programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">swap</phrase><phrase role="special">(</phrase> <phrase role="identifier">packaged_task</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
</programlisting>
<variablelist>
<title></title>
<varlistentry>
<term>Effects:</term>
<listitem>
<para>
Swaps the <link linkend="shared_state">shared state</link> between
other and <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Throws:</term>
<listitem>
<para>
Nothing.
</para>
</listitem>
</varlistentry>
</variablelist>
<para>
<bridgehead renderas="sect4" id="packaged_task_valid_bridgehead">
<phrase id="packaged_task_valid"/>
<link linkend="packaged_task_valid">Member
function <code>valid</code>()</link>
</bridgehead>
</para>
<programlisting><phrase role="keyword">bool</phrase> <phrase role="identifier">valid</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
</programlisting>
<variablelist>
<title></title>
<varlistentry>
<term>Effects:</term>
<listitem>
<para>
Returns <code><phrase role="keyword">true</phrase></code> if <code><phrase
role="special">*</phrase><phrase role="keyword">this</phrase></code>
contains a <link linkend="shared_state">shared state</link>.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Throws:</term>
<listitem>
<para>
Nothing.
</para>
</listitem>
</varlistentry>
</variablelist>
<para>
<bridgehead renderas="sect4" id="packaged_task_get_future_bridgehead">
<phrase id="packaged_task_get_future"/>
<link linkend="packaged_task_get_future">Member
function <code>get_future</code>()</link>
</bridgehead>
</para>
<programlisting><phrase role="identifier">future</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">R</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">get_future</phrase><phrase role="special">();</phrase>
</programlisting>
<variablelist>
<title></title>
<varlistentry>
<term>Returns:</term>
<listitem>
<para>
A <link linkend="class_future"> <code>future&lt;&gt;</code></link> with the same <link linkend="shared_state">shared
state</link>.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Throws:</term>
<listitem>
<para>
<code><phrase role="identifier">future_error</phrase></code> with
<code><phrase role="identifier">future_errc</phrase><phrase role="special">::</phrase><phrase
role="identifier">future_already_retrieved</phrase></code> or <code><phrase
role="identifier">future_errc</phrase><phrase role="special">::</phrase><phrase
role="identifier">no_state</phrase></code>.
</para>
</listitem>
</varlistentry>
</variablelist>
<para>
<bridgehead renderas="sect4" id="packaged_task_operator_apply_bridgehead">
<phrase id="packaged_task_operator_apply"/>
<link linkend="packaged_task_operator_apply">Member
function <code>operator()</code>()</link>
</bridgehead>
</para>
<programlisting><phrase role="keyword">void</phrase> <phrase role="keyword">operator</phrase><phrase role="special">()(</phrase> <phrase role="identifier">Args</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="special">...</phrase> <phrase role="identifier">args</phrase><phrase role="special">);</phrase>
</programlisting>
<variablelist>
<title></title>
<varlistentry>
<term>Effects:</term>
<listitem>
<para>
Invokes the stored callable target. Any exception thrown by the callable
target <code><phrase role="identifier">fn</phrase></code> is stored
in the <link linkend="shared_state">shared state</link>. Otherwise,
the value returned by <code><phrase role="identifier">fn</phrase></code>
is stored in the shared state.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Throws:</term>
<listitem>
<para>
<code><phrase role="identifier">future_error</phrase></code> with
<code><phrase role="identifier">future_errc</phrase><phrase role="special">::</phrase><phrase
role="identifier">no_state</phrase></code>.
</para>
</listitem>
</varlistentry>
</variablelist>
<para>
<bridgehead renderas="sect4" id="packaged_task_reset_bridgehead">
<phrase id="packaged_task_reset"/>
<link linkend="packaged_task_reset">Member
function <code>reset</code>()</link>
</bridgehead>
</para>
<programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">reset</phrase><phrase role="special">();</phrase>
</programlisting>
<variablelist>
<title></title>
<varlistentry>
<term>Effects:</term>
<listitem>
<para>
Resets the <link linkend="shared_state">shared state</link> and abondons
the result of previous executions. A new shared state is constructed.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Throws:</term>
<listitem>
<para>
<code><phrase role="identifier">future_error</phrase></code> with
<code><phrase role="identifier">future_errc</phrase><phrase role="special">::</phrase><phrase
role="identifier">no_state</phrase></code>.
</para>
</listitem>
</varlistentry>
</variablelist>
</section>
</section>
</section>
<section id="fiber.fls">
<title><link linkend="fiber.fls">Fiber local storage</link></title>
<bridgehead renderas="sect3" id="fiber.fls.h0">
<phrase id="fiber.fls.synopsis"/><link linkend="fiber.fls.synopsis">Synopsis</link>
</bridgehead>
<para>
Fiber local storage allows a separate instance of a given data item for each
fiber.
</para>
<bridgehead renderas="sect3" id="fiber.fls.h1">
<phrase id="fiber.fls.cleanup_at_fiber_exit"/><link linkend="fiber.fls.cleanup_at_fiber_exit">Cleanup
at fiber exit</link>
</bridgehead>
<para>
When a fiber exits, the objects associated with each <link linkend="class_fiber_specific_ptr"> <code>fiber_specific_ptr</code></link> instance
are destroyed. By default, the object pointed to by a pointer <code><phrase
role="identifier">p</phrase></code> is destroyed by invoking <code><phrase
role="keyword">delete</phrase> <phrase role="identifier">p</phrase></code>,
but this can be overridden for a specific instance of <link linkend="class_fiber_specific_ptr"> <code>fiber_specific_ptr</code></link> by
providing a cleanup routine <code><phrase role="identifier">func</phrase></code>
to the constructor. In this case, the object is destroyed by invoking <code><phrase
role="identifier">func</phrase><phrase role="special">(</phrase><phrase role="identifier">p</phrase><phrase
role="special">)</phrase></code>. The cleanup functions are called in an unspecified
order.
</para>
<para>
<bridgehead renderas="sect4" id="class_fiber_specific_ptr_bridgehead">
<phrase id="class_fiber_specific_ptr"/>
<link linkend="class_fiber_specific_ptr">Class
<code>fiber_specific_ptr</code></link>
</bridgehead>
</para>
<programlisting><phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">fiber</phrase><phrase role="special">/</phrase><phrase role="identifier">fss</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase>
<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">fiber_specific_ptr</phrase> <phrase role="special">{</phrase>
<phrase role="keyword">public</phrase><phrase role="special">:</phrase>
<phrase role="keyword">typedef</phrase> <phrase role="identifier">T</phrase> <phrase role="identifier">element_type</phrase><phrase role="special">;</phrase>
<phrase role="identifier">fiber_specific_ptr</phrase><phrase role="special">();</phrase>
<phrase role="keyword">explicit</phrase> <phrase role="identifier">fiber_specific_ptr</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">T</phrase><phrase role="special">*)</phrase> <phrase role="special">);</phrase>
<phrase role="special">~</phrase><phrase role="identifier">fiber_specific_ptr</phrase><phrase role="special">();</phrase>
<phrase role="identifier">fiber_specific_ptr</phrase><phrase role="special">(</phrase> <phrase role="identifier">fiber_specific_ptr</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="special">=</phrase> <phrase role="keyword">delete</phrase><phrase role="special">;</phrase>
<phrase role="identifier">fiber_specific_ptr</phrase> <phrase role="special">&amp;</phrase> <phrase role="keyword">operator</phrase><phrase role="special">=(</phrase> <phrase role="identifier">fiber_specific_ptr</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="special">=</phrase> <phrase role="keyword">delete</phrase><phrase role="special">;</phrase>
<phrase role="identifier">T</phrase> <phrase role="special">*</phrase> <phrase role="identifier">get</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
<phrase role="identifier">T</phrase> <phrase role="special">*</phrase> <phrase role="keyword">operator</phrase><phrase role="special">-&gt;()</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
<phrase role="identifier">T</phrase> <phrase role="special">&amp;</phrase> <phrase role="keyword">operator</phrase><phrase role="special">*()</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
<phrase role="identifier">T</phrase> <phrase role="special">*</phrase> <phrase role="identifier">release</phrase><phrase role="special">();</phrase>
<phrase role="keyword">void</phrase> <phrase role="identifier">reset</phrase><phrase role="special">(</phrase> <phrase role="identifier">T</phrase> <phrase role="special">*</phrase> <phrase role="identifier">t</phrase><phrase role="special">);</phrase>
<phrase role="special">};</phrase>
</programlisting>
<bridgehead renderas="sect3" id="fiber.fls.h2">
<phrase id="fiber.fls.constructor"/><link linkend="fiber.fls.constructor">Constructor</link>
</bridgehead>
<programlisting><phrase role="identifier">fiber_specific_ptr</phrase><phrase role="special">();</phrase>
<phrase role="keyword">explicit</phrase> <phrase role="identifier">fiber_specific_ptr</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">T</phrase><phrase role="special">*)</phrase> <phrase role="special">);</phrase>
</programlisting>
<variablelist>
<title></title>
<varlistentry>
<term>Requires:</term>
<listitem>
<para>
<code><phrase role="keyword">delete</phrase> <phrase role="keyword">this</phrase><phrase
role="special">-&gt;</phrase><phrase role="identifier">get</phrase><phrase
role="special">()</phrase></code> is well-formed; <code><phrase role="identifier">fn</phrase><phrase
role="special">(</phrase><phrase role="keyword">this</phrase><phrase
role="special">-&gt;</phrase><phrase role="identifier">get</phrase><phrase
role="special">())</phrase></code> does not throw
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Effects:</term>
<listitem>
<para>
Construct a <link linkend="class_fiber_specific_ptr"> <code>fiber_specific_ptr</code></link> object for storing
a pointer to an object of type <code><phrase role="identifier">T</phrase></code>
specific to each fiber. When <code><phrase role="identifier">reset</phrase><phrase
role="special">()</phrase></code> is called, or the fiber exits, <link linkend="class_fiber_specific_ptr"> <code>fiber_specific_ptr</code></link> calls
<code><phrase role="identifier">fn</phrase><phrase role="special">(</phrase><phrase
role="keyword">this</phrase><phrase role="special">-&gt;</phrase><phrase
role="identifier">get</phrase><phrase role="special">())</phrase></code>.
If the no-arguments constructor is used, the default <code><phrase role="keyword">delete</phrase></code>-based
cleanup function will be used to destroy the fiber-local objects.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Throws:</term>
<listitem>
<para>
<code><phrase role="identifier">fiber_resource_error</phrase></code>
if an error occurs.
</para>
</listitem>
</varlistentry>
</variablelist>
<bridgehead renderas="sect3" id="fiber.fls.h3">
<phrase id="fiber.fls.destructor"/><link linkend="fiber.fls.destructor">Destructor</link>
</bridgehead>
<programlisting><phrase role="special">~</phrase><phrase role="identifier">fiber_specific_ptr</phrase><phrase role="special">();</phrase>
</programlisting>
<variablelist>
<title></title>
<varlistentry>
<term>Requires:</term>
<listitem>
<para>
All the fiber specific instances associated to this <link linkend="class_fiber_specific_ptr"> <code>fiber_specific_ptr</code></link>
(except
maybe the one associated to this fiber) must be nullptr.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Effects:</term>
<listitem>
<para>
Calls <code><phrase role="keyword">this</phrase><phrase role="special">-&gt;</phrase><phrase
role="identifier">reset</phrase><phrase role="special">()</phrase></code>
to clean up the associated value for the current fiber, and destroys
<code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Throws:</term>
<listitem>
<para>
Nothing.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Remarks:</term>
<listitem>
<para>
The requirement is an implementation restriction. If the destructor promised
to delete instances for all fibers, the implementation would be forced
to maintain a list of all the fibers having an associated specific ptr,
which is against the goal of fiber specific data. In general, a <link linkend="class_fiber_specific_ptr"> <code>fiber_specific_ptr</code></link> should
outlive the fibers that use it.
</para>
</listitem>
</varlistentry>
</variablelist>
<note>
<para>
Care needs to be taken to ensure that any fibers still running after an instance
of <link linkend="class_fiber_specific_ptr"> <code>fiber_specific_ptr</code></link> has been destroyed do not call
any member functions on that instance.
</para>
</note>
<para>
<bridgehead renderas="sect4" id="fiber_specific_ptr_get_bridgehead">
<phrase id="fiber_specific_ptr_get"/>
<link linkend="fiber_specific_ptr_get">Member
function <code>get</code>()</link>
</bridgehead>
</para>
<programlisting><phrase role="identifier">T</phrase><phrase role="special">*</phrase> <phrase role="identifier">get</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
</programlisting>
<variablelist>
<title></title>
<varlistentry>
<term>Returns:</term>
<listitem>
<para>
The pointer associated with the current fiber.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Throws:</term>
<listitem>
<para>
Nothing.
</para>
</listitem>
</varlistentry>
</variablelist>
<note>
<para>
The initial value associated with an instance of <link linkend="class_fiber_specific_ptr"> <code>fiber_specific_ptr</code></link> is
<code><phrase role="keyword">nullptr</phrase></code> for each fiber.
</para>
</note>
<para>
<bridgehead renderas="sect4" id="fiber_specific_ptr_operator_arrow_bridgehead">
<phrase id="fiber_specific_ptr_operator_arrow"/>
<link linkend="fiber_specific_ptr_operator_arrow">Member
function <code>operator-&gt;</code>()</link>
</bridgehead>
</para>
<programlisting><phrase role="identifier">T</phrase><phrase role="special">*</phrase> <phrase role="keyword">operator</phrase><phrase role="special">-&gt;()</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
</programlisting>
<variablelist>
<title></title>
<varlistentry>
<term>Requires:</term>
<listitem>
<para>
<code><phrase role="keyword">this</phrase><phrase role="special">-&gt;</phrase><phrase
role="identifier">get</phrase><phrase role="special">()</phrase></code>
is not <code><phrase role="keyword">nullptr</phrase></code>.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Returns:</term>
<listitem>
<para>
<code><phrase role="keyword">this</phrase><phrase role="special">-&gt;</phrase><phrase
role="identifier">get</phrase><phrase role="special">()</phrase></code>
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Throws:</term>
<listitem>
<para>
Nothing.
</para>
</listitem>
</varlistentry>
</variablelist>
<para>
<bridgehead renderas="sect4" id="fiber_specific_ptr_operator_star_bridgehead">
<phrase id="fiber_specific_ptr_operator_star"/>
<link linkend="fiber_specific_ptr_operator_star">Member
function <code>operator*</code>()</link>
</bridgehead>
</para>
<programlisting><phrase role="identifier">T</phrase><phrase role="special">&amp;</phrase> <phrase role="keyword">operator</phrase><phrase role="special">*()</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
</programlisting>
<variablelist>
<title></title>
<varlistentry>
<term>Requires:</term>
<listitem>
<para>
<code><phrase role="keyword">this</phrase><phrase role="special">-&gt;</phrase><phrase
role="identifier">get</phrase><phrase role="special">()</phrase></code>
is not <code><phrase role="keyword">nullptr</phrase></code>.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Returns:</term>
<listitem>
<para>
<code><phrase role="special">*(</phrase><phrase role="keyword">this</phrase><phrase
role="special">-&gt;</phrase><phrase role="identifier">get</phrase><phrase
role="special">())</phrase></code>
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Throws:</term>
<listitem>
<para>
Nothing.
</para>
</listitem>
</varlistentry>
</variablelist>
<para>
<bridgehead renderas="sect4" id="fiber_specific_ptr_release_bridgehead">
<phrase id="fiber_specific_ptr_release"/>
<link linkend="fiber_specific_ptr_release">Member
function <code>release</code>()</link>
</bridgehead>
</para>
<programlisting><phrase role="identifier">T</phrase><phrase role="special">*</phrase> <phrase role="identifier">release</phrase><phrase role="special">();</phrase>
</programlisting>
<variablelist>
<title></title>
<varlistentry>
<term>Effects:</term>
<listitem>
<para>
Return <code><phrase role="keyword">this</phrase><phrase role="special">-&gt;</phrase><phrase
role="identifier">get</phrase><phrase role="special">()</phrase></code>
and store <code><phrase role="keyword">nullptr</phrase></code> as the
pointer associated with the current fiber without invoking the cleanup
function.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Postcondition:</term>
<listitem>
<para>
<code><phrase role="keyword">this</phrase><phrase role="special">-&gt;</phrase><phrase
role="identifier">get</phrase><phrase role="special">()==</phrase><phrase
role="keyword">nullptr</phrase></code>
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Throws:</term>
<listitem>
<para>
Nothing.
</para>
</listitem>
</varlistentry>
</variablelist>
<para>
<bridgehead renderas="sect4" id="fiber_specific_ptr_reset_bridgehead">
<phrase id="fiber_specific_ptr_reset"/>
<link linkend="fiber_specific_ptr_reset">Member
function <code>reset</code>()</link>
</bridgehead>
</para>
<programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">reset</phrase><phrase role="special">(</phrase><phrase role="identifier">T</phrase><phrase role="special">*</phrase> <phrase role="identifier">new_value</phrase><phrase role="special">);</phrase>
</programlisting>
<variablelist>
<title></title>
<varlistentry>
<term>Effects:</term>
<listitem>
<para>
If <code><phrase role="keyword">this</phrase><phrase role="special">-&gt;</phrase><phrase
role="identifier">get</phrase><phrase role="special">()!=</phrase><phrase
role="identifier">new_value</phrase></code> and <code><phrase role="keyword">this</phrase><phrase
role="special">-&gt;</phrase><phrase role="identifier">get</phrase><phrase
role="special">()</phrase></code> is not <code><phrase role="keyword">nullptr</phrase></code>,
invoke <code><phrase role="keyword">delete</phrase> <phrase role="keyword">this</phrase><phrase
role="special">-&gt;</phrase><phrase role="identifier">get</phrase><phrase
role="special">()</phrase></code> or <code><phrase role="identifier">fn</phrase><phrase
role="special">(</phrase><phrase role="keyword">this</phrase><phrase
role="special">-&gt;</phrase><phrase role="identifier">get</phrase><phrase
role="special">())</phrase></code> as appropriate. Store <code><phrase
role="identifier">new_value</phrase></code> as the pointer associated
with the current fiber.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Postcondition:</term>
<listitem>
<para>
<code><phrase role="keyword">this</phrase><phrase role="special">-&gt;</phrase><phrase
role="identifier">get</phrase><phrase role="special">()==</phrase><phrase
role="identifier">new_value</phrase></code>
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Throws:</term>
<listitem>
<para>
<code><phrase role="identifier">fiber_resource_error</phrase></code>
if an error occurs.
</para>
</listitem>
</varlistentry>
</variablelist>
</section>
<section id="fiber.callbacks">
<title><anchor id="callbacks"/><link linkend="fiber.callbacks">Integrating Fibers
with Asynchronous Callbacks</link></title>
<bridgehead renderas="sect3" id="fiber.callbacks.h0">
<phrase id="fiber.callbacks.overview"/><link linkend="fiber.callbacks.overview">Overview</link>
</bridgehead>
<para>
One of the primary benefits of <emphasis role="bold">Boost.Fiber</emphasis>
is the ability to use asynchronous operations for efficiency, while at the
same time structuring the calling code <emphasis>as if</emphasis> the operations
were synchronous. Asynchronous operations provide completion notification in
a variety of ways, but most involve a callback function of some kind. This
section discusses tactics for interfacing <emphasis role="bold">Boost.Fiber</emphasis>
with an arbitrary async operation.
</para>
<para>
For purposes of illustration, consider the following hypothetical API:
</para>
<para>
<programlisting><phrase role="keyword">class</phrase> <phrase role="identifier">AsyncAPI</phrase> <phrase role="special">{</phrase>
<phrase role="keyword">public</phrase><phrase role="special">:</phrase>
<phrase role="comment">// constructor acquires some resource that can be read and written</phrase>
<phrase role="identifier">AsyncAPI</phrase><phrase role="special">();</phrase>
<phrase role="comment">// callbacks accept an int error code; 0 == success</phrase>
<phrase role="keyword">typedef</phrase> <phrase role="keyword">int</phrase> <phrase role="identifier">errorcode</phrase><phrase role="special">;</phrase>
<phrase role="comment">// write callback only needs to indicate success or failure</phrase>
<phrase role="keyword">void</phrase> <phrase role="identifier">init_write</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">data</phrase><phrase role="special">,</phrase>
<phrase role="identifier">std</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">errorcode</phrase><phrase role="special">)</phrase> <phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">callback</phrase><phrase role="special">);</phrase>
<phrase role="comment">// read callback needs to accept both errorcode and data</phrase>
<phrase role="keyword">void</phrase> <phrase role="identifier">init_read</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</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">errorcode</phrase><phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;)</phrase> <phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;);</phrase>
<phrase role="comment">// ... other operations ...</phrase>
<phrase role="special">};</phrase>
</programlisting>
</para>
<para>
The significant points about each of <code><phrase role="identifier">init_write</phrase><phrase
role="special">()</phrase></code> and <code><phrase role="identifier">init_read</phrase><phrase
role="special">()</phrase></code> are:
</para>
<itemizedlist>
<listitem>
<simpara>
The <code><phrase role="identifier">AsyncAPI</phrase></code> method only
initiates the operation. It returns immediately, while the requested operation
is still pending.
</simpara>
</listitem>
<listitem>
<simpara>
The method accepts a callback. When the operation completes, the callback
is called with relevant parameters (error code, data if applicable).
</simpara>
</listitem>
</itemizedlist>
<para>
We would like to wrap these asynchronous methods in functions that appear synchronous
by blocking the calling fiber until the operation completes. This lets us use
the wrapper function's return value to deliver relevant data.
</para>
<tip>
<para>
<link linkend="class_promise"> <code>promise&lt;&gt;</code></link> and <link linkend="class_future"> <code>future&lt;&gt;</code></link> are your friends
here.
</para>
</tip>
<bridgehead renderas="sect3" id="fiber.callbacks.h1">
<phrase id="fiber.callbacks.return_errorcode"/><link linkend="fiber.callbacks.return_errorcode">Return
Errorcode</link>
</bridgehead>
<para>
The <code><phrase role="identifier">AsyncAPI</phrase><phrase role="special">::</phrase><phrase
role="identifier">init_write</phrase><phrase role="special">()</phrase></code>
callback passes only an <code><phrase role="identifier">errorcode</phrase></code>.
If we simply want the blocking wrapper to return that <code><phrase role="identifier">errorcode</phrase></code>,
this is an extremely straightforward use of <link linkend="class_promise"> <code>promise&lt;&gt;</code></link> and
<link linkend="class_future"> <code>future&lt;&gt;</code></link>:
</para>
<para>
<programlisting><phrase role="identifier">AsyncAPI</phrase><phrase role="special">::</phrase><phrase role="identifier">errorcode</phrase> <phrase role="identifier">write_ec</phrase><phrase role="special">(</phrase> <phrase role="identifier">AsyncAPI</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">api</phrase><phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">data</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
<phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">promise</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">AsyncAPI</phrase><phrase role="special">::</phrase><phrase role="identifier">errorcode</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">promise</phrase><phrase role="special">;</phrase>
<phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">future</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">AsyncAPI</phrase><phrase role="special">::</phrase><phrase role="identifier">errorcode</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">future</phrase><phrase role="special">(</phrase> <phrase role="identifier">promise</phrase><phrase role="special">.</phrase><phrase role="identifier">get_future</phrase><phrase role="special">()</phrase> <phrase role="special">);</phrase>
<phrase role="comment">// We can confidently bind a reference to local variable 'promise' into</phrase>
<phrase role="comment">// the lambda callback because we know for a fact we're going to suspend</phrase>
<phrase role="comment">// (preserving the lifespan of both 'promise' and 'future') until the</phrase>
<phrase role="comment">// callback has fired.</phrase>
<phrase role="identifier">api</phrase><phrase role="special">.</phrase><phrase role="identifier">init_write</phrase><phrase role="special">(</phrase> <phrase role="identifier">data</phrase><phrase role="special">,</phrase>
<phrase role="special">[&amp;</phrase><phrase role="identifier">promise</phrase><phrase role="special">](</phrase> <phrase role="identifier">AsyncAPI</phrase><phrase role="special">::</phrase><phrase role="identifier">errorcode</phrase> <phrase role="identifier">ec</phrase><phrase role="special">){</phrase>
<phrase role="identifier">promise</phrase><phrase role="special">.</phrase><phrase role="identifier">set_value</phrase><phrase role="special">(</phrase> <phrase role="identifier">ec</phrase><phrase role="special">);</phrase>
<phrase role="special">});</phrase>
<phrase role="keyword">return</phrase> <phrase role="identifier">future</phrase><phrase role="special">.</phrase><phrase role="identifier">get</phrase><phrase role="special">();</phrase>
<phrase role="special">}</phrase>
</programlisting>
</para>
<para>
All we have to do is:
</para>
<orderedlist>
<listitem>
<simpara>
Instantiate a <code><phrase role="identifier">promise</phrase><phrase role="special">&lt;&gt;</phrase></code>
of correct type.
</simpara>
</listitem>
<listitem>
<simpara>
Obtain its <code><phrase role="identifier">future</phrase><phrase role="special">&lt;&gt;</phrase></code>.
</simpara>
</listitem>
<listitem>
<simpara>
Arrange for the callback to call <link linkend="promise_set_value"> <code>promise::set_value()</code></link>.
</simpara>
</listitem>
<listitem>
<simpara>
Block on <link linkend="future_get"> <code>future::get()</code></link>.
</simpara>
</listitem>
</orderedlist>
<note>
<para>
This tactic for resuming a pending fiber works even if the callback is called
on a different thread than the one on which the initiating fiber is running.
In fact, <ulink url="../../examples/adapt_callbacks.cpp">the example program's</ulink>
dummy <code><phrase role="identifier">AsyncAPI</phrase></code> implementation
illustrates that: it simulates async I/O by launching a new thread that sleeps
briefly and then calls the relevant callback.
</para>
</note>
<bridgehead renderas="sect3" id="fiber.callbacks.h2">
<phrase id="fiber.callbacks.success_or_exception"/><link linkend="fiber.callbacks.success_or_exception">Success
or Exception</link>
</bridgehead>
<para>
A wrapper more aligned with modern C++ practice would use an exception, rather
than an <code><phrase role="identifier">errorcode</phrase></code>, to communicate
failure to its caller. This is straightforward to code in terms of <code><phrase
role="identifier">write_ec</phrase><phrase role="special">()</phrase></code>:
</para>
<para>
<programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">write</phrase><phrase role="special">(</phrase> <phrase role="identifier">AsyncAPI</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">api</phrase><phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">data</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
<phrase role="identifier">AsyncAPI</phrase><phrase role="special">::</phrase><phrase role="identifier">errorcode</phrase> <phrase role="identifier">ec</phrase> <phrase role="special">=</phrase> <phrase role="identifier">write_ec</phrase><phrase role="special">(</phrase> <phrase role="identifier">api</phrase><phrase role="special">,</phrase> <phrase role="identifier">data</phrase><phrase role="special">);</phrase>
<phrase role="keyword">if</phrase> <phrase role="special">(</phrase> <phrase role="identifier">ec</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
<phrase role="keyword">throw</phrase> <phrase role="identifier">make_exception</phrase><phrase role="special">(</phrase><phrase role="string">&quot;write&quot;</phrase><phrase role="special">,</phrase> <phrase role="identifier">ec</phrase><phrase role="special">);</phrase>
<phrase role="special">}</phrase>
<phrase role="special">}</phrase>
</programlisting>
</para>
<para>
The point is that since each fiber has its own stack, you need not repeat messy
boilerplate: normal encapsulation works.
</para>
<bridgehead renderas="sect3" id="fiber.callbacks.h3">
<phrase id="fiber.callbacks.return_errorcode_or_data"/><link linkend="fiber.callbacks.return_errorcode_or_data">Return
Errorcode or Data</link>
</bridgehead>
<para>
Things get a bit more interesting when the async operation's callback passes
multiple data items of interest. One approach would be to use <code><phrase
role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">pair</phrase><phrase
role="special">&lt;&gt;</phrase></code> to capture both:
</para>
<para>
<programlisting><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">pair</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">AsyncAPI</phrase><phrase role="special">::</phrase><phrase role="identifier">errorcode</phrase><phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">read_ec</phrase><phrase role="special">(</phrase> <phrase role="identifier">AsyncAPI</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">api</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
<phrase role="keyword">typedef</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">pair</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">AsyncAPI</phrase><phrase role="special">::</phrase><phrase role="identifier">errorcode</phrase><phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">result_pair</phrase><phrase role="special">;</phrase>
<phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">promise</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">result_pair</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">promise</phrase><phrase role="special">;</phrase>
<phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">future</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">result_pair</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">future</phrase><phrase role="special">(</phrase> <phrase role="identifier">promise</phrase><phrase role="special">.</phrase><phrase role="identifier">get_future</phrase><phrase role="special">()</phrase> <phrase role="special">);</phrase>
<phrase role="comment">// We promise that both 'promise' and 'future' will survive until our</phrase>
<phrase role="comment">// lambda has been called.</phrase>
<phrase role="identifier">api</phrase><phrase role="special">.</phrase><phrase role="identifier">init_read</phrase><phrase role="special">(</phrase> <phrase role="special">[&amp;</phrase><phrase role="identifier">promise</phrase><phrase role="special">](</phrase> <phrase role="identifier">AsyncAPI</phrase><phrase role="special">::</phrase><phrase role="identifier">errorcode</phrase> <phrase role="identifier">ec</phrase><phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">data</phrase><phrase role="special">){</phrase>
<phrase role="identifier">promise</phrase><phrase role="special">.</phrase><phrase role="identifier">set_value</phrase><phrase role="special">(</phrase> <phrase role="identifier">result_pair</phrase><phrase role="special">(</phrase> <phrase role="identifier">ec</phrase><phrase role="special">,</phrase> <phrase role="identifier">data</phrase><phrase role="special">)</phrase> <phrase role="special">);</phrase>
<phrase role="special">});</phrase>
<phrase role="keyword">return</phrase> <phrase role="identifier">future</phrase><phrase role="special">.</phrase><phrase role="identifier">get</phrase><phrase role="special">();</phrase>
<phrase role="special">}</phrase>
</programlisting>
</para>
<para>
Once you bundle the interesting data in <code><phrase role="identifier">std</phrase><phrase
role="special">::</phrase><phrase role="identifier">pair</phrase><phrase role="special">&lt;&gt;</phrase></code>,
the code is effectively identical to <code><phrase role="identifier">write_ec</phrase><phrase
role="special">()</phrase></code>. You can call it like this:
</para>
<para>
<programlisting><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">tie</phrase><phrase role="special">(</phrase> <phrase role="identifier">ec</phrase><phrase role="special">,</phrase> <phrase role="identifier">data</phrase><phrase role="special">)</phrase> <phrase role="special">=</phrase> <phrase role="identifier">read_ec</phrase><phrase role="special">(</phrase> <phrase role="identifier">api</phrase><phrase role="special">);</phrase>
</programlisting>
</para>
<anchor id="Data_or_Exception"/>
<bridgehead renderas="sect3" id="fiber.callbacks.h4">
<phrase id="fiber.callbacks.data_or_exception"/><link linkend="fiber.callbacks.data_or_exception">Data
or Exception</link>
</bridgehead>
<para>
But a more natural API for a function that obtains data is to return only the
data on success, throwing an exception on error.
</para>
<para>
As with <code><phrase role="identifier">write</phrase><phrase role="special">()</phrase></code>
above, it's certainly possible to code a <code><phrase role="identifier">read</phrase><phrase
role="special">()</phrase></code> wrapper in terms of <code><phrase role="identifier">read_ec</phrase><phrase
role="special">()</phrase></code>. But since a given application is unlikely
to need both, let's code <code><phrase role="identifier">read</phrase><phrase
role="special">()</phrase></code> from scratch, leveraging <link linkend="promise_set_exception"> <code>promise::set_exception()</code></link>:
</para>
<para>
<programlisting><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="identifier">read</phrase><phrase role="special">(</phrase> <phrase role="identifier">AsyncAPI</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">api</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
<phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">promise</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">promise</phrase><phrase role="special">;</phrase>
<phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">future</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">future</phrase><phrase role="special">(</phrase> <phrase role="identifier">promise</phrase><phrase role="special">.</phrase><phrase role="identifier">get_future</phrase><phrase role="special">()</phrase> <phrase role="special">);</phrase>
<phrase role="comment">// Both 'promise' and 'future' will survive until our lambda has been</phrase>
<phrase role="comment">// called.</phrase>
<phrase role="identifier">api</phrase><phrase role="special">.</phrase><phrase role="identifier">init_read</phrase><phrase role="special">(</phrase> <phrase role="special">[&amp;</phrase><phrase role="identifier">promise</phrase><phrase role="special">](</phrase> <phrase role="identifier">AsyncAPI</phrase><phrase role="special">::</phrase><phrase role="identifier">errorcode</phrase> <phrase role="identifier">ec</phrase><phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">data</phrase><phrase role="special">){</phrase>
<phrase role="keyword">if</phrase> <phrase role="special">(</phrase> <phrase role="special">!</phrase> <phrase role="identifier">ec</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
<phrase role="identifier">promise</phrase><phrase role="special">.</phrase><phrase role="identifier">set_value</phrase><phrase role="special">(</phrase> <phrase role="identifier">data</phrase><phrase role="special">);</phrase>
<phrase role="special">}</phrase> <phrase role="keyword">else</phrase> <phrase role="special">{</phrase>
<phrase role="identifier">promise</phrase><phrase role="special">.</phrase><phrase role="identifier">set_exception</phrase><phrase role="special">(</phrase>
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">make_exception_ptr</phrase><phrase role="special">(</phrase>
<phrase role="identifier">make_exception</phrase><phrase role="special">(</phrase><phrase role="string">&quot;read&quot;</phrase><phrase role="special">,</phrase> <phrase role="identifier">ec</phrase><phrase role="special">)</phrase> <phrase role="special">)</phrase> <phrase role="special">);</phrase>
<phrase role="special">}</phrase>
<phrase role="special">});</phrase>
<phrase role="keyword">return</phrase> <phrase role="identifier">future</phrase><phrase role="special">.</phrase><phrase role="identifier">get</phrase><phrase role="special">();</phrase>
<phrase role="special">}</phrase>
</programlisting>
</para>
<para>
<link linkend="future_get"> <code>future::get()</code></link> will do the right thing, either returning <code><phrase
role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase></code>
or throwing an exception.
</para>
<bridgehead renderas="sect3" id="fiber.callbacks.h5">
<phrase id="fiber.callbacks.success_error_virtual_methods"/><link linkend="fiber.callbacks.success_error_virtual_methods">Success/Error
Virtual Methods</link>
</bridgehead>
<para>
One classic approach to completion notification is to define an abstract base
class with <code><phrase role="identifier">success</phrase><phrase role="special">()</phrase></code>
and <code><phrase role="identifier">error</phrase><phrase role="special">()</phrase></code>
methods. Code wishing to perform async I/O must derive a subclass, override
each of these methods and pass the async operation a pointer to a subclass
instance. The abstract base class might look like this:
</para>
<para>
<programlisting><phrase role="comment">// every async operation receives a subclass instance of this abstract base</phrase>
<phrase role="comment">// class through which to communicate its result</phrase>
<phrase role="keyword">struct</phrase> <phrase role="identifier">Response</phrase> <phrase role="special">{</phrase>
<phrase role="keyword">typedef</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">shared_ptr</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Response</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">ptr</phrase><phrase role="special">;</phrase>
<phrase role="comment">// called if the operation succeeds</phrase>
<phrase role="keyword">virtual</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">success</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">data</phrase><phrase role="special">)</phrase> <phrase role="special">=</phrase> <phrase role="number">0</phrase><phrase role="special">;</phrase>
<phrase role="comment">// called if the operation fails</phrase>
<phrase role="keyword">virtual</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">error</phrase><phrase role="special">(</phrase> <phrase role="identifier">AsyncAPIBase</phrase><phrase role="special">::</phrase><phrase role="identifier">errorcode</phrase> <phrase role="identifier">ec</phrase><phrase role="special">)</phrase> <phrase role="special">=</phrase> <phrase role="number">0</phrase><phrase role="special">;</phrase>
<phrase role="special">};</phrase>
</programlisting>
</para>
<para>
Now the <code><phrase role="identifier">AsyncAPI</phrase></code> operation
might look more like this:
</para>
<para>
<programlisting><phrase role="comment">// derive Response subclass, instantiate, pass Response::ptr</phrase>
<phrase role="keyword">void</phrase> <phrase role="identifier">init_read</phrase><phrase role="special">(</phrase> <phrase role="identifier">Response</phrase><phrase role="special">::</phrase><phrase role="identifier">ptr</phrase><phrase role="special">);</phrase>
</programlisting>
</para>
<para>
We can address this by writing a one-size-fits-all <code><phrase role="identifier">PromiseResponse</phrase></code>:
</para>
<para>
<programlisting><phrase role="keyword">class</phrase> <phrase role="identifier">PromiseResponse</phrase><phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <phrase role="identifier">Response</phrase> <phrase role="special">{</phrase>
<phrase role="keyword">public</phrase><phrase role="special">:</phrase>
<phrase role="comment">// called if the operation succeeds</phrase>
<phrase role="keyword">virtual</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">success</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">data</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
<phrase role="identifier">promise_</phrase><phrase role="special">.</phrase><phrase role="identifier">set_value</phrase><phrase role="special">(</phrase> <phrase role="identifier">data</phrase><phrase role="special">);</phrase>
<phrase role="special">}</phrase>
<phrase role="comment">// called if the operation fails</phrase>
<phrase role="keyword">virtual</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">error</phrase><phrase role="special">(</phrase> <phrase role="identifier">AsyncAPIBase</phrase><phrase role="special">::</phrase><phrase role="identifier">errorcode</phrase> <phrase role="identifier">ec</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
<phrase role="identifier">promise_</phrase><phrase role="special">.</phrase><phrase role="identifier">set_exception</phrase><phrase role="special">(</phrase>
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">make_exception_ptr</phrase><phrase role="special">(</phrase>
<phrase role="identifier">make_exception</phrase><phrase role="special">(</phrase><phrase role="string">&quot;read&quot;</phrase><phrase role="special">,</phrase> <phrase role="identifier">ec</phrase><phrase role="special">)</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">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">future</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">get_future</phrase><phrase role="special">()</phrase> <phrase role="special">{</phrase>
<phrase role="keyword">return</phrase> <phrase role="identifier">promise_</phrase><phrase role="special">.</phrase><phrase role="identifier">get_future</phrase><phrase role="special">();</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">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">promise</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">promise_</phrase><phrase role="special">;</phrase>
<phrase role="special">};</phrase>
</programlisting>
</para>
<para>
Now we can simply obtain the <code><phrase role="identifier">future</phrase><phrase
role="special">&lt;&gt;</phrase></code> from that <code><phrase role="identifier">PromiseResponse</phrase></code>
and wait on its <code><phrase role="identifier">get</phrase><phrase role="special">()</phrase></code>:
</para>
<para>
<programlisting><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="identifier">read</phrase><phrase role="special">(</phrase> <phrase role="identifier">AsyncAPI</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">api</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
<phrase role="comment">// Because init_read() requires a shared_ptr, we must allocate our</phrase>
<phrase role="comment">// ResponsePromise on the heap, even though we know its lifespan.</phrase>
<phrase role="keyword">auto</phrase> <phrase role="identifier">promisep</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">make_shared</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">PromiseResponse</phrase> <phrase role="special">&gt;()</phrase> <phrase role="special">);</phrase>
<phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">future</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">future</phrase><phrase role="special">(</phrase> <phrase role="identifier">promisep</phrase><phrase role="special">-&gt;</phrase><phrase role="identifier">get_future</phrase><phrase role="special">()</phrase> <phrase role="special">);</phrase>
<phrase role="comment">// Both 'promisep' and 'future' will survive until our lambda has been</phrase>
<phrase role="comment">// called.</phrase>
<phrase role="identifier">api</phrase><phrase role="special">.</phrase><phrase role="identifier">init_read</phrase><phrase role="special">(</phrase> <phrase role="identifier">promisep</phrase><phrase role="special">);</phrase>
<phrase role="keyword">return</phrase> <phrase role="identifier">future</phrase><phrase role="special">.</phrase><phrase role="identifier">get</phrase><phrase role="special">();</phrase>
<phrase role="special">}</phrase>
</programlisting>
</para>
<para>
The source code above is found in <ulink url="../../examples/adapt_callbacks.cpp">adapt_callbacks.cpp</ulink>
and <ulink url="../../examples/adapt_method_calls.cpp">adapt_method_calls.cpp</ulink>.
</para>
<anchor id="callbacks_asio"/>
<bridgehead renderas="sect3" id="fiber.callbacks.h6">
<phrase id="fiber.callbacks.then_there_s__ulink_url__http___www_boost_org_doc_libs_release_libs_asio_index_html__boost_asio__ulink_"/><link
linkend="fiber.callbacks.then_there_s__ulink_url__http___www_boost_org_doc_libs_release_libs_asio_index_html__boost_asio__ulink_">Then
There's <ulink url="http://www.boost.org/doc/libs/release/libs/asio/index.html">Boost.Asio</ulink></link>
</bridgehead>
<para>
Since the simplest form of Boost.Asio asynchronous operation completion token
is a callback function, we could apply the same tactics for Asio as for our
hypothetical <code><phrase role="identifier">AsyncAPI</phrase></code> asynchronous
operations.
</para>
<para>
Fortunately we need not. Boost.Asio incorporates a mechanism by which the caller
can customize the notification behavior of every async operation. Therefore
we can construct a <emphasis>completion token</emphasis> which, when passed
to a <ulink url="http://www.boost.org/doc/libs/release/libs/asio/index.html">Boost.Asio</ulink>
async operation, requests blocking for the calling fiber. The underlying implementation
uses the same mechanism as described above.
</para>
<para>
<code><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase
role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase
role="identifier">asio</phrase><phrase role="special">::</phrase><phrase role="identifier">yield</phrase></code>
is such a completion token. <code><phrase role="identifier">yield</phrase></code>
is an instance of <code><phrase role="identifier">yield_t</phrase></code>:
</para>
<para>
<programlisting><phrase role="comment">/// A special value, similar to std::nothrow.</phrase>
<phrase role="identifier">BOOST_CONSTEXPR_OR_CONST</phrase> <phrase role="identifier">yield_t</phrase><phrase role="special">&lt;&gt;</phrase> <phrase role="identifier">yield</phrase><phrase role="special">;</phrase>
</programlisting>
</para>
<para>
which is a <code><phrase role="identifier">promise_completion_token</phrase></code>:
</para>
<para>
<programlisting><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Allocator</phrase> <phrase role="special">=</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">allocator</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">void</phrase> <phrase role="special">&gt;</phrase> <phrase role="special">&gt;</phrase>
<phrase role="keyword">class</phrase> <phrase role="identifier">yield_t</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <phrase role="identifier">promise_completion_token</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Allocator</phrase> <phrase role="special">&gt;</phrase> <phrase role="special">{</phrase>
<phrase role="keyword">public</phrase><phrase role="special">:</phrase>
<phrase role="comment">/// Construct with default-constructed allocator.</phrase>
<phrase role="identifier">BOOST_CONSTEXPR</phrase> <phrase role="identifier">yield_t</phrase><phrase role="special">()</phrase> <phrase role="special">{</phrase>
<phrase role="special">}</phrase>
<phrase role="comment">// ... ways to use an alternate allocator or bind an error_code ...</phrase>
<phrase role="special">};</phrase>
</programlisting>
</para>
<para>
<code><phrase role="identifier">promise_completion_token</phrase></code> is
common to both <code><phrase role="identifier">yield</phrase></code> and <code><phrase
role="identifier">use_future</phrase></code>. (The interested reader is encouraged
to learn more about <code><phrase role="identifier">use_future</phrase></code>
in <ulink url="../../examples/asio/use_future.hpp">example source code</ulink>.)
</para>
<para>
<code><phrase role="identifier">promise_completion_token</phrase></code> is
in fact only a placeholder, a way to trigger Boost.Asio customization. It can
bind a custom allocator or <ulink url="http://www.boost.org/doc/libs/release/libs/system/doc/reference.html#Class-error_code"><code><phrase
role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">system</phrase><phrase
role="special">::</phrase><phrase role="identifier">error_code</phrase></code></ulink>
for use by the actual handler.
</para>
<para>
<programlisting><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Allocator</phrase> <phrase role="special">&gt;</phrase>
<phrase role="keyword">class</phrase> <phrase role="identifier">promise_completion_token</phrase> <phrase role="special">{</phrase>
<phrase role="keyword">public</phrase><phrase role="special">:</phrase>
<phrase role="keyword">typedef</phrase> <phrase role="identifier">Allocator</phrase> <phrase role="identifier">allocator_type</phrase><phrase role="special">;</phrase>
<phrase role="comment">/// Construct using default-constructed allocator.</phrase>
<phrase role="identifier">BOOST_CONSTEXPR</phrase> <phrase role="identifier">promise_completion_token</phrase><phrase role="special">()</phrase> <phrase role="special">:</phrase>
<phrase role="identifier">ec_</phrase><phrase role="special">(</phrase> <phrase role="keyword">nullptr</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
<phrase role="special">}</phrase>
<phrase role="comment">/// Construct using specified allocator.</phrase>
<phrase role="keyword">explicit</phrase> <phrase role="identifier">promise_completion_token</phrase><phrase role="special">(</phrase> <phrase role="identifier">Allocator</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">allocator</phrase><phrase role="special">)</phrase> <phrase role="special">:</phrase>
<phrase role="identifier">ec_</phrase><phrase role="special">(</phrase> <phrase role="keyword">nullptr</phrase><phrase role="special">),</phrase>
<phrase role="identifier">allocator_</phrase><phrase role="special">(</phrase> <phrase role="identifier">allocator</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
<phrase role="special">}</phrase>
<phrase role="comment">/// Obtain allocator.</phrase>
<phrase role="identifier">allocator_type</phrase> <phrase role="identifier">get_allocator</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase> <phrase role="special">{</phrase>
<phrase role="keyword">return</phrase> <phrase role="identifier">allocator_</phrase><phrase role="special">;</phrase>
<phrase role="special">}</phrase>
<phrase role="comment">//private:</phrase>
<phrase role="comment">// used by some subclasses to bind an error_code to suppress exceptions</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="identifier">ec_</phrase><phrase role="special">;</phrase>
<phrase role="keyword">private</phrase><phrase role="special">:</phrase>
<phrase role="identifier">Allocator</phrase> <phrase role="identifier">allocator_</phrase><phrase role="special">;</phrase>
<phrase role="special">};</phrase>
</programlisting>
</para>
<para>
Asio customization is engaged by specializing <ulink url="http://www.boost.org/doc/libs/release/doc/html/boost_asio/reference/handler_type.html"><code><phrase
role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">asio</phrase><phrase
role="special">::</phrase><phrase role="identifier">handler_type</phrase><phrase
role="special">&lt;&gt;</phrase></code></ulink> for <code><phrase role="identifier">yield_t</phrase></code>:
</para>
<para>
<programlisting><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Allocator</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">ReturnType</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Arg2</phrase> <phrase role="special">&gt;</phrase>
<phrase role="keyword">struct</phrase> <phrase role="identifier">handler_type</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">asio</phrase><phrase role="special">::</phrase><phrase role="identifier">yield_t</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Allocator</phrase> <phrase role="special">&gt;,</phrase>
<phrase role="identifier">ReturnType</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="identifier">Arg2</phrase><phrase role="special">)</phrase> <phrase role="special">&gt;</phrase> <phrase role="special">{</phrase>
<phrase role="keyword">typedef</phrase> <phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">asio</phrase><phrase role="special">::</phrase><phrase role="identifier">detail</phrase><phrase role="special">::</phrase><phrase role="identifier">yield_handler</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Arg2</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">type</phrase><phrase role="special">;</phrase>
<phrase role="special">};</phrase>
</programlisting>
</para>
<para>
(There are actually four different specializations in <ulink url="../../examples/asio/detail/yield.hpp">detail/yield.hpp</ulink>,
one for each of the four Asio async callback signatures we expect to have to
support.)
</para>
<para>
The above directs Asio to use <code><phrase role="identifier">yield_handler</phrase></code>
as the actual handler for an async operation to which <code><phrase role="identifier">yield</phrase></code>
is passed.
</para>
<para>
<code><phrase role="identifier">yield_handler</phrase></code> is simply an
alias for <code><phrase role="identifier">promise_handler</phrase></code>,
because <code><phrase role="identifier">promise_handler</phrase></code> is
shared with the <code><phrase role="identifier">use_future</phrase></code>
machinery:
</para>
<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">using</phrase> <phrase role="identifier">yield_handler</phrase> <phrase role="special">=</phrase> <phrase role="identifier">promise_handler</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">T</phrase> <phrase role="special">&gt;;</phrase>
</programlisting>
</para>
<para>
<code><phrase role="identifier">promise_handler</phrase></code> isa <code><phrase
role="identifier">promise_handler_base</phrase></code>:
</para>
<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">promise_handler_base</phrase> <phrase role="special">{</phrase>
<phrase role="keyword">public</phrase><phrase role="special">:</phrase>
<phrase role="keyword">typedef</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">shared_ptr</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">promise</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">T</phrase> <phrase role="special">&gt;</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">promise_ptr</phrase><phrase role="special">;</phrase>
<phrase role="comment">// Construct from any promise_completion_token subclass special value.</phrase>
<phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Allocator</phrase> <phrase role="special">&gt;</phrase>
<phrase role="identifier">promise_handler_base</phrase><phrase role="special">(</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">asio</phrase><phrase role="special">::</phrase><phrase role="identifier">promise_completion_token</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Allocator</phrase> <phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">pct</phrase><phrase role="special">)</phrase> <phrase role="special">:</phrase>
<phrase role="identifier">promise_</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">make_shared</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">promise</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">T</phrase> <phrase role="special">&gt;</phrase> <phrase role="special">&gt;(</phrase>
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">allocator_arg</phrase><phrase role="special">,</phrase> <phrase role="identifier">pct</phrase><phrase role="special">.</phrase><phrase role="identifier">get_allocator</phrase><phrase role="special">()</phrase> <phrase role="special">)</phrase> <phrase role="special">)</phrase>
<phrase role="special">{}</phrase>
<phrase role="keyword">bool</phrase> <phrase role="identifier">should_set_value</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="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">ec</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">ec</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
<phrase role="comment">// whew, success</phrase>
<phrase role="keyword">return</phrase> <phrase role="keyword">true</phrase><phrase role="special">;</phrase>
<phrase role="special">}</phrase>
<phrase role="comment">// no bound error_code: cause promise_ to throw an exception</phrase>
<phrase role="identifier">promise_</phrase><phrase role="special">-&gt;</phrase><phrase role="identifier">set_exception</phrase><phrase role="special">(</phrase>
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">make_exception_ptr</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">system_error</phrase><phrase role="special">(</phrase> <phrase role="identifier">ec</phrase><phrase role="special">)</phrase> <phrase role="special">)</phrase> <phrase role="special">);</phrase>
<phrase role="comment">// caller should NOT call set_value()</phrase>
<phrase role="keyword">return</phrase> <phrase role="keyword">false</phrase><phrase role="special">;</phrase>
<phrase role="special">}</phrase>
<phrase role="identifier">promise_ptr</phrase> <phrase role="identifier">get_promise</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase> <phrase role="special">{</phrase>
<phrase role="keyword">return</phrase> <phrase role="identifier">promise_</phrase><phrase role="special">;</phrase>
<phrase role="special">}</phrase>
<phrase role="keyword">private</phrase><phrase role="special">:</phrase>
<phrase role="identifier">promise_ptr</phrase> <phrase role="identifier">promise_</phrase><phrase role="special">;</phrase>
<phrase role="special">};</phrase>
</programlisting>
</para>
<para>
As promised, <code><phrase role="identifier">promise_handler_base</phrase></code>
binds a <link linkend="class_promise"> <code>promise&lt;&gt;</code></link> of appropriate type. (We store a <code><phrase
role="identifier">shared_ptr</phrase><phrase role="special">&lt;</phrase>
<phrase role="identifier">promise</phrase><phrase role="special">&lt;</phrase>
<phrase role="identifier">T</phrase> <phrase role="special">&gt;</phrase>
<phrase role="special">&gt;</phrase></code> because the <code><phrase role="identifier">promise_handler</phrase></code>
instance is copied on its way into underlying Asio machinery.)
</para>
<para>
Asio, having consulted the <code><phrase role="identifier">handler_type</phrase><phrase
role="special">&lt;&gt;</phrase></code> traits specialization, instantiates
a <code><phrase role="identifier">yield_handler</phrase></code> (aka <code><phrase
role="identifier">promise_handler</phrase></code>) as the async operation's
callback:
</para>
<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">promise_handler</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <phrase role="identifier">promise_handler_base</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">T</phrase> <phrase role="special">&gt;</phrase> <phrase role="special">{</phrase>
<phrase role="keyword">private</phrase><phrase role="special">:</phrase>
<phrase role="keyword">public</phrase><phrase role="special">:</phrase>
<phrase role="comment">// Construct from any promise_completion_token subclass special value.</phrase>
<phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Allocator</phrase> <phrase role="special">&gt;</phrase>
<phrase role="identifier">promise_handler</phrase><phrase role="special">(</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">asio</phrase><phrase role="special">::</phrase><phrase role="identifier">promise_completion_token</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Allocator</phrase> <phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">pct</phrase><phrase role="special">)</phrase> <phrase role="special">:</phrase>
<phrase role="identifier">promise_handler_base</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">T</phrase> <phrase role="special">&gt;(</phrase> <phrase role="identifier">pct</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="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">ec</phrase><phrase role="special">,</phrase> <phrase role="identifier">T</phrase> <phrase role="identifier">t</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
<phrase role="keyword">if</phrase> <phrase role="special">(</phrase> <phrase role="identifier">should_set_value</phrase><phrase role="special">(</phrase> <phrase role="identifier">ec</phrase><phrase role="special">)</phrase> <phrase role="special">)</phrase> <phrase role="special">{</phrase>
<phrase role="identifier">get_promise</phrase><phrase role="special">()-&gt;</phrase><phrase role="identifier">set_value</phrase><phrase role="special">(</phrase> <phrase role="identifier">t</phrase><phrase role="special">);</phrase>
<phrase role="special">}</phrase>
<phrase role="special">}</phrase>
<phrase role="special">};</phrase>
</programlisting>
</para>
<para>
Like the lambda callback in our <link linkend="Data_or_Exception"><code><phrase
role="identifier">read</phrase><phrase role="special">(</phrase><phrase role="identifier">AsyncAPI</phrase><phrase
role="special">&amp;)</phrase></code></link> presented earlier, <code><phrase
role="identifier">promise_handler</phrase><phrase role="special">::</phrase><phrase
role="keyword">operator</phrase><phrase role="special">()()</phrase></code>
either calls <link linkend="promise_set_value"> <code>promise::set_value()</code></link> or <link linkend="promise_set_exception"> <code>promise::set_exception()</code></link> (via
<code><phrase role="identifier">promise_handler_base</phrase><phrase role="special">::</phrase><phrase
role="identifier">should_set_value</phrase><phrase role="special">()</phrase></code>).
</para>
<para>
The source code above is found in <ulink url="../../examples/asio/yield.hpp">yield.hpp</ulink>,
<ulink url="../../examples/asio/promise_completion_token.hpp">promise_completion_token.hpp</ulink>,
<ulink url="../../examples/asio/detail/yield.hpp">detail/yield.hpp</ulink>
and <ulink url="../../examples/asio/detail/promise_handler.hpp">detail/promise_handler.hpp</ulink>.
</para>
</section>
<section id="fiber.nonblocking">
<title><anchor id="nonblocking"/><link linkend="fiber.nonblocking">Integrating
Fibers with Nonblocking I/O</link></title>
<bridgehead renderas="sect3" id="fiber.nonblocking.h0">
<phrase id="fiber.nonblocking.overview"/><link linkend="fiber.nonblocking.overview">Overview</link>
</bridgehead>
<para>
<emphasis>Nonblocking</emphasis> I/O is distinct from <emphasis>asynchronous</emphasis>
I/O. A true async I/O operation promises to initiate the operation and notify
the caller on completion, usually via some sort of callback (as described in
<link linkend="callbacks">Integrating Fibers with Asynchronous Callbacks</link>).
</para>
<para>
In contrast, a nonblocking I/O operation refuses to start at all if it would
be necessary to block, returning an error code such as <ulink url="http://man7.org/linux/man-pages/man3/errno.3.html"><code><phrase
role="identifier">EWOULDBLOCK</phrase></code></ulink>. The operation is performed
only when it can complete immediately. In effect, the caller must repeatedly
retry the operation until it stops returning <code><phrase role="identifier">EWOULDBLOCK</phrase></code>.
</para>
<para>
In a classic event-driven program, it can be something of a headache to use
nonblocking I/O. At the point where the nonblocking I/O is attempted, a return
value of <code><phrase role="identifier">EWOULDBLOCK</phrase></code> requires
the caller to pass control back to the main event loop, arranging to retry
again on the next iteration.
</para>
<para>
Worse, a nonblocking I/O operation might <emphasis>partially</emphasis> succeed.
That means that the relevant business logic must continue receiving control
on every main loop iteration until all required data have been processed: a
doubly-nested loop, implemented as a callback-driven state machine.
</para>
<para>
<emphasis role="bold">Boost.Fiber</emphasis> can simplify this problem immensely.
Once you have integrated with the application's main loop as described in
<link linkend="integration">Sharing a Thread with Another Main Loop</link>,
waiting for the next main-loop iteration is as simple as calling <link linkend="this_fiber_yield"> <code>this_fiber::yield()</code></link>.
</para>
<bridgehead renderas="sect3" id="fiber.nonblocking.h1">
<phrase id="fiber.nonblocking.example_nonblocking_api"/><link linkend="fiber.nonblocking.example_nonblocking_api">Example
Nonblocking API</link>
</bridgehead>
<para>
For purposes of illustration, consider this API:
</para>
<para>
<programlisting><phrase role="keyword">class</phrase> <phrase role="identifier">NonblockingAPI</phrase> <phrase role="special">{</phrase>
<phrase role="keyword">public</phrase><phrase role="special">:</phrase>
<phrase role="identifier">NonblockingAPI</phrase><phrase role="special">();</phrase>
<phrase role="comment">// nonblocking operation: may return EWOULDBLOCK</phrase>
<phrase role="keyword">int</phrase> <phrase role="identifier">read</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">data</phrase><phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">desired</phrase><phrase role="special">);</phrase>
<phrase role="special">...</phrase>
<phrase role="special">};</phrase>
</programlisting>
</para>
<bridgehead renderas="sect3" id="fiber.nonblocking.h2">
<phrase id="fiber.nonblocking.polling_for_completion"/><link linkend="fiber.nonblocking.polling_for_completion">Polling
for Completion</link>
</bridgehead>
<para>
We can build a low-level wrapper around <code><phrase role="identifier">NonblockingAPI</phrase><phrase
role="special">::</phrase><phrase role="identifier">read</phrase><phrase role="special">()</phrase></code>
that shields its caller from ever having to deal with <code><phrase role="identifier">EWOULDBLOCK</phrase></code>:
</para>
<para>
<programlisting><phrase role="comment">// guaranteed not to return EWOULDBLOCK</phrase>
<phrase role="keyword">int</phrase> <phrase role="identifier">read_chunk</phrase><phrase role="special">(</phrase> <phrase role="identifier">NonblockingAPI</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">api</phrase><phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">data</phrase><phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">desired</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
<phrase role="keyword">int</phrase> <phrase role="identifier">error</phrase><phrase role="special">;</phrase>
<phrase role="keyword">while</phrase> <phrase role="special">(</phrase> <phrase role="identifier">EWOULDBLOCK</phrase> <phrase role="special">==</phrase> <phrase role="special">(</phrase> <phrase role="identifier">error</phrase> <phrase role="special">=</phrase> <phrase role="identifier">api</phrase><phrase role="special">.</phrase><phrase role="identifier">read</phrase><phrase role="special">(</phrase> <phrase role="identifier">data</phrase><phrase role="special">,</phrase> <phrase role="identifier">desired</phrase><phrase role="special">)</phrase> <phrase role="special">)</phrase> <phrase role="special">)</phrase> <phrase role="special">{</phrase>
<phrase role="comment">// not ready yet -- try again on the next iteration of the</phrase>
<phrase role="comment">// application's main loop</phrase>
<phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">this_fiber</phrase><phrase role="special">::</phrase><phrase role="identifier">yield</phrase><phrase role="special">();</phrase>
<phrase role="special">}</phrase>
<phrase role="keyword">return</phrase> <phrase role="identifier">error</phrase><phrase role="special">;</phrase>
<phrase role="special">}</phrase>
</programlisting>
</para>
<bridgehead renderas="sect3" id="fiber.nonblocking.h3">
<phrase id="fiber.nonblocking.filling_all_desired_data"/><link linkend="fiber.nonblocking.filling_all_desired_data">Filling
All Desired Data</link>
</bridgehead>
<para>
Given <code><phrase role="identifier">read_chunk</phrase><phrase role="special">()</phrase></code>,
we can straightforwardly iterate until we have all desired data:
</para>
<para>
<programlisting><phrase role="comment">// keep reading until desired length, EOF or error</phrase>
<phrase role="comment">// may return both partial data and nonzero error</phrase>
<phrase role="keyword">int</phrase> <phrase role="identifier">read_desired</phrase><phrase role="special">(</phrase> <phrase role="identifier">NonblockingAPI</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">api</phrase><phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">data</phrase><phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">desired</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
<phrase role="comment">// we're going to accumulate results into 'data'</phrase>
<phrase role="identifier">data</phrase><phrase role="special">.</phrase><phrase role="identifier">clear</phrase><phrase role="special">();</phrase>
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="identifier">chunk</phrase><phrase role="special">;</phrase>
<phrase role="keyword">int</phrase> <phrase role="identifier">error</phrase> <phrase role="special">=</phrase> <phrase role="number">0</phrase><phrase role="special">;</phrase>
<phrase role="keyword">while</phrase> <phrase role="special">(</phrase> <phrase role="identifier">data</phrase><phrase role="special">.</phrase><phrase role="identifier">length</phrase><phrase role="special">()</phrase> <phrase role="special">&lt;</phrase> <phrase role="identifier">desired</phrase> <phrase role="special">&amp;&amp;</phrase>
<phrase role="special">(</phrase> <phrase role="identifier">error</phrase> <phrase role="special">=</phrase> <phrase role="identifier">read_chunk</phrase><phrase role="special">(</phrase> <phrase role="identifier">api</phrase><phrase role="special">,</phrase> <phrase role="identifier">chunk</phrase><phrase role="special">,</phrase> <phrase role="identifier">desired</phrase> <phrase role="special">-</phrase> <phrase role="identifier">data</phrase><phrase role="special">.</phrase><phrase role="identifier">length</phrase><phrase role="special">()</phrase> <phrase role="special">)</phrase> <phrase role="special">)</phrase> <phrase role="special">==</phrase> <phrase role="number">0</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
<phrase role="identifier">data</phrase><phrase role="special">.</phrase><phrase role="identifier">append</phrase><phrase role="special">(</phrase> <phrase role="identifier">chunk</phrase><phrase role="special">);</phrase>
<phrase role="special">}</phrase>
<phrase role="keyword">return</phrase> <phrase role="identifier">error</phrase><phrase role="special">;</phrase>
<phrase role="special">}</phrase>
</programlisting>
</para>
<para>
(Of <emphasis>course</emphasis> there are more efficient ways to accumulate
string data. That's not the point of this example.)
</para>
<bridgehead renderas="sect3" id="fiber.nonblocking.h4">
<phrase id="fiber.nonblocking.wrapping_it_up"/><link linkend="fiber.nonblocking.wrapping_it_up">Wrapping
it Up</link>
</bridgehead>
<para>
Finally, we can define a relevant exception:
</para>
<para>
<programlisting><phrase role="comment">// exception class augmented with both partially-read data and errorcode</phrase>
<phrase role="keyword">class</phrase> <phrase role="identifier">IncompleteRead</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">runtime_error</phrase> <phrase role="special">{</phrase>
<phrase role="keyword">public</phrase><phrase role="special">:</phrase>
<phrase role="identifier">IncompleteRead</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">what</phrase><phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">partial</phrase><phrase role="special">,</phrase> <phrase role="keyword">int</phrase> <phrase role="identifier">ec</phrase><phrase role="special">)</phrase> <phrase role="special">:</phrase>
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">runtime_error</phrase><phrase role="special">(</phrase> <phrase role="identifier">what</phrase><phrase role="special">),</phrase>
<phrase role="identifier">partial_</phrase><phrase role="special">(</phrase> <phrase role="identifier">partial</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="special">{</phrase>
<phrase role="special">}</phrase>
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="identifier">get_partial</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase> <phrase role="special">{</phrase>
<phrase role="keyword">return</phrase> <phrase role="identifier">partial_</phrase><phrase role="special">;</phrase>
<phrase role="special">}</phrase>
<phrase role="keyword">int</phrase> <phrase role="identifier">get_errorcode</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase> <phrase role="special">{</phrase>
<phrase role="keyword">return</phrase> <phrase role="identifier">ec_</phrase><phrase role="special">;</phrase>
<phrase role="special">}</phrase>
<phrase role="keyword">private</phrase><phrase role="special">:</phrase>
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="identifier">partial_</phrase><phrase role="special">;</phrase>
<phrase role="keyword">int</phrase> <phrase role="identifier">ec_</phrase><phrase role="special">;</phrase>
<phrase role="special">};</phrase>
</programlisting>
</para>
<para>
and write a simple <code><phrase role="identifier">read</phrase><phrase role="special">()</phrase></code>
function that either returns all desired data or throws <code><phrase role="identifier">IncompleteRead</phrase></code>:
</para>
<para>
<programlisting><phrase role="comment">// read all desired data or throw IncompleteRead</phrase>
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="identifier">read</phrase><phrase role="special">(</phrase> <phrase role="identifier">NonblockingAPI</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">api</phrase><phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">desired</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="identifier">data</phrase><phrase role="special">;</phrase>
<phrase role="keyword">int</phrase> <phrase role="identifier">ec</phrase><phrase role="special">(</phrase> <phrase role="identifier">read_desired</phrase><phrase role="special">(</phrase> <phrase role="identifier">api</phrase><phrase role="special">,</phrase> <phrase role="identifier">data</phrase><phrase role="special">,</phrase> <phrase role="identifier">desired</phrase><phrase role="special">)</phrase> <phrase role="special">);</phrase>
<phrase role="comment">// for present purposes, EOF isn't a failure</phrase>
<phrase role="keyword">if</phrase> <phrase role="special">(</phrase> <phrase role="number">0</phrase> <phrase role="special">==</phrase> <phrase role="identifier">ec</phrase> <phrase role="special">||</phrase> <phrase role="identifier">EOF</phrase> <phrase role="special">==</phrase> <phrase role="identifier">ec</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
<phrase role="keyword">return</phrase> <phrase role="identifier">data</phrase><phrase role="special">;</phrase>
<phrase role="special">}</phrase>
<phrase role="comment">// oh oh, partial read</phrase>
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">ostringstream</phrase> <phrase role="identifier">msg</phrase><phrase role="special">;</phrase>
<phrase role="identifier">msg</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="string">&quot;NonblockingAPI::read() error &quot;</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="identifier">ec</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="string">&quot; after &quot;</phrase>
<phrase role="special">&lt;&lt;</phrase> <phrase role="identifier">data</phrase><phrase role="special">.</phrase><phrase role="identifier">length</phrase><phrase role="special">()</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="string">&quot; of &quot;</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="identifier">desired</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="string">&quot; characters&quot;</phrase><phrase role="special">;</phrase>
<phrase role="keyword">throw</phrase> <phrase role="identifier">IncompleteRead</phrase><phrase role="special">(</phrase> <phrase role="identifier">msg</phrase><phrase role="special">.</phrase><phrase role="identifier">str</phrase><phrase role="special">(),</phrase> <phrase role="identifier">data</phrase><phrase role="special">,</phrase> <phrase role="identifier">ec</phrase><phrase role="special">);</phrase>
<phrase role="special">}</phrase>
</programlisting>
</para>
<para>
Once we can transparently wait for the next main-loop iteration using <link linkend="this_fiber_yield"> <code>this_fiber::yield()</code></link>,
ordinary encapsulation Just Works.
</para>
<para>
The source code above is found in <ulink url="../../examples/adapt_nonblocking.cpp">adapt_nonblocking.cpp</ulink>.
</para>
</section>
<section id="fiber.when_any">
<title><anchor id="when_any"/><link linkend="fiber.when_any">when_any / when_all
functionality</link></title>
<bridgehead renderas="sect3" id="fiber.when_any.h0">
<phrase id="fiber.when_any.overview"/><link linkend="fiber.when_any.overview">Overview</link>
</bridgehead>
<para>
A bit of wisdom from the early days of computing still holds true today: prefer
to model program state using the instruction pointer rather than with Boolean
flags. In other words, if the program must &quot;do something&quot; and then
do something almost the same, but with minor changes... perhaps parts of that
something should be broken out as smaller separate functions, rather than introducing
flags to alter the internal behavior of a monolithic function.
</para>
<para>
To that we would add: prefer to describe control flow using C++ native constructs
such as function calls, <code><phrase role="keyword">if</phrase></code>, <code><phrase
role="keyword">while</phrase></code>, <code><phrase role="keyword">for</phrase></code>,
<code><phrase role="keyword">do</phrase></code> et al. rather than as chains
of callbacks.
</para>
<para>
One of the great strengths of <emphasis role="bold">Boost.Fiber</emphasis>
is the flexibility it confers on the coder to restructure an application from
chains of callbacks to straightforward C++ statement sequence, even when code
in that fiber is in fact interleaved with code running in other fibers.
</para>
<para>
There has been much recent discussion about the benefits of when_any and when_all
functionality. When dealing with asynchronous and possibly unreliable services,
these are valuable idioms. But of course when_any and when_all are closely
tied to the use of chains of callbacks.
</para>
<para>
This section presents recipes for achieving the same ends, in the context of
a fiber that wants to &quot;do something&quot; when one or more other independent
activities have completed. Accordingly, these are <code><phrase role="identifier">wait_something</phrase><phrase
role="special">()</phrase></code> functions rather than <code><phrase role="identifier">when_something</phrase><phrase
role="special">()</phrase></code> functions. The expectation is that the calling
fiber asks to launch those independent activities, then waits for them, then
sequentially proceeds with whatever processing depends on those results.
</para>
<para>
The function names shown (e.g. <link linkend="wait_first_simple"><code><phrase
role="identifier">wait_first_simple</phrase><phrase role="special">()</phrase></code></link>)
are for illustrative purposes only, because all these functions have been bundled
into a single source file. Presumably, if (say) <link linkend="wait_first_success"><code><phrase
role="identifier">wait_first_success</phrase><phrase role="special">()</phrase></code></link>
best suits your application needs, you could introduce that variant with the
name <code><phrase role="identifier">wait_any</phrase><phrase role="special">()</phrase></code>.
</para>
<note>
<para>
The functions presented in this section accept variadic argument lists of
task functions. Corresponding <code><phrase role="identifier">wait_something</phrase><phrase
role="special">()</phrase></code> functions accepting a container of task
functions are left as an exercise for the interested reader. Those should
actually be simpler. Most of the complexity would arise from overloading
the same name for both purposes.
</para>
</note>
<para>
All the source code for this section is found in <ulink url="../../examples/wait_stuff.cpp">wait_stuff.cpp</ulink>.
</para>
<bridgehead renderas="sect3" id="fiber.when_any.h1">
<phrase id="fiber.when_any.example_task_function"/><link linkend="fiber.when_any.example_task_function">Example
Task Function</link>
</bridgehead>
<para>
<anchor id="wait_sleeper"/>We found it convenient to model an asynchronous
task using this function:
</para>
<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="identifier">T</phrase> <phrase role="identifier">sleeper_impl</phrase><phrase role="special">(</phrase> <phrase role="identifier">T</phrase> <phrase role="identifier">item</phrase><phrase role="special">,</phrase> <phrase role="keyword">int</phrase> <phrase role="identifier">ms</phrase><phrase role="special">,</phrase> <phrase role="keyword">bool</phrase> <phrase role="identifier">thrw</phrase> <phrase role="special">=</phrase> <phrase role="keyword">false</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">ostringstream</phrase> <phrase role="identifier">descb</phrase><phrase role="special">,</phrase> <phrase role="identifier">funcb</phrase><phrase role="special">;</phrase>
<phrase role="identifier">descb</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="identifier">item</phrase><phrase role="special">;</phrase>
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="identifier">desc</phrase><phrase role="special">(</phrase> <phrase role="identifier">descb</phrase><phrase role="special">.</phrase><phrase role="identifier">str</phrase><phrase role="special">()</phrase> <phrase role="special">);</phrase>
<phrase role="identifier">funcb</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="string">&quot; sleeper(&quot;</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="identifier">item</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="string">&quot;)&quot;</phrase><phrase role="special">;</phrase>
<phrase role="identifier">Verbose</phrase> <phrase role="identifier">v</phrase><phrase role="special">(</phrase> <phrase role="identifier">funcb</phrase><phrase role="special">.</phrase><phrase role="identifier">str</phrase><phrase role="special">()</phrase> <phrase role="special">);</phrase>
<phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">this_fiber</phrase><phrase role="special">::</phrase><phrase role="identifier">sleep_for</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">milliseconds</phrase><phrase role="special">(</phrase> <phrase role="identifier">ms</phrase><phrase role="special">)</phrase> <phrase role="special">);</phrase>
<phrase role="keyword">if</phrase> <phrase role="special">(</phrase> <phrase role="identifier">thrw</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
<phrase role="keyword">throw</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">runtime_error</phrase><phrase role="special">(</phrase> <phrase role="identifier">desc</phrase><phrase role="special">);</phrase>
<phrase role="special">}</phrase>
<phrase role="keyword">return</phrase> <phrase role="identifier">item</phrase><phrase role="special">;</phrase>
<phrase role="special">}</phrase>
</programlisting>
</para>
<para>
with type-specific <code><phrase role="identifier">sleeper</phrase><phrase
role="special">()</phrase></code> &quot;front ends&quot; for <code><phrase
role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase></code>,
<code><phrase role="keyword">double</phrase></code> and <code><phrase role="keyword">int</phrase></code>.
</para>
<para>
<code><phrase role="identifier">Verbose</phrase></code> simply prints a message
to <code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase
role="identifier">cout</phrase></code> on construction and destruction.
</para>
<para>
Basically:
</para>
<orderedlist>
<listitem>
<simpara>
<code><phrase role="identifier">sleeper</phrase><phrase role="special">()</phrase></code>
prints a start message;
</simpara>
</listitem>
<listitem>
<simpara>
sleeps for the specified number of milliseconds;
</simpara>
</listitem>
<listitem>
<simpara>
if <code><phrase role="identifier">thrw</phrase></code> is passed as <code><phrase
role="keyword">true</phrase></code>, throws a string description of the
passed <code><phrase role="identifier">item</phrase></code>;
</simpara>
</listitem>
<listitem>
<simpara>
else returns the passed <code><phrase role="identifier">item</phrase></code>.
</simpara>
</listitem>
<listitem>
<simpara>
On the way out, <code><phrase role="identifier">sleeper</phrase><phrase
role="special">()</phrase></code> produces a stop message.
</simpara>
</listitem>
</orderedlist>
<para>
This function will feature in the example calls to the various functions presented
below.
</para>
<section id="fiber.when_any.when_any">
<title><link linkend="fiber.when_any.when_any">when_any</link></title>
<section id="fiber.when_any.when_any.when_any__simple_completion">
<title><anchor id="wait_first_simple_section"/><link linkend="fiber.when_any.when_any.when_any__simple_completion">when_any,
simple completion</link></title>
<para>
The simplest case is when you only need to know that the first of a set
of asynchronous tasks has completed &mdash; but you don't need to obtain a return
value, and you're confident that they will not throw exceptions.
</para>
<para>
<anchor id="wait_done"/>For this we introduce a <code><phrase role="identifier">Done</phrase></code>
class to wrap a <code><phrase role="keyword">bool</phrase></code> variable
with a <link linkend="class_condition_variable"> <code>condition_variable</code></link> and a <link linkend="class_mutex"> <code>mutex</code></link>:
</para>
<para>
<programlisting><phrase role="comment">// Wrap canonical pattern for condition_variable + bool flag</phrase>
<phrase role="keyword">struct</phrase> <phrase role="identifier">Done</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">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">condition_variable</phrase> <phrase role="identifier">cond</phrase><phrase role="special">;</phrase>
<phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">mutex</phrase> <phrase role="identifier">mutex</phrase><phrase role="special">;</phrase>
<phrase role="keyword">bool</phrase> <phrase role="identifier">ready</phrase> <phrase role="special">=</phrase> <phrase role="keyword">false</phrase><phrase role="special">;</phrase>
<phrase role="keyword">public</phrase><phrase role="special">:</phrase>
<phrase role="keyword">typedef</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">shared_ptr</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Done</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">ptr</phrase><phrase role="special">;</phrase>
<phrase role="keyword">void</phrase> <phrase role="identifier">wait</phrase><phrase role="special">()</phrase> <phrase role="special">{</phrase>
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">unique_lock</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">mutex</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">lock</phrase><phrase role="special">(</phrase> <phrase role="identifier">mutex</phrase><phrase role="special">);</phrase>
<phrase role="keyword">while</phrase> <phrase role="special">(</phrase> <phrase role="special">!</phrase> <phrase role="identifier">ready</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
<phrase role="identifier">cond</phrase><phrase role="special">.</phrase><phrase role="identifier">wait</phrase><phrase role="special">(</phrase> <phrase role="identifier">lock</phrase><phrase role="special">);</phrase>
<phrase role="special">}</phrase>
<phrase role="special">}</phrase>
<phrase role="keyword">void</phrase> <phrase role="identifier">notify</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">unique_lock</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">mutex</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">lock</phrase><phrase role="special">(</phrase> <phrase role="identifier">mutex</phrase><phrase role="special">);</phrase>
<phrase role="identifier">ready</phrase> <phrase role="special">=</phrase> <phrase role="keyword">true</phrase><phrase role="special">;</phrase>
<phrase role="special">}</phrase> <phrase role="comment">// release mutex</phrase>
<phrase role="identifier">cond</phrase><phrase role="special">.</phrase><phrase role="identifier">notify_one</phrase><phrase role="special">();</phrase>
<phrase role="special">}</phrase>
<phrase role="special">};</phrase>
</programlisting>
</para>
<para>
The pattern we follow throughout this section is to pass a <ulink url="http://www.cplusplus.com/reference/memory/shared_ptr/"><code><phrase
role="identifier">std</phrase><phrase role="special">::</phrase><phrase
role="identifier">shared_ptr</phrase><phrase role="special">&lt;&gt;</phrase></code></ulink>
to the relevant synchronization object to the various tasks' fiber functions.
This eliminates nagging questions about the lifespan of the synchronization
object relative to the last of the fibers.
</para>
<para>
<anchor id="wait_first_simple"/><code><phrase role="identifier">wait_first_simple</phrase><phrase
role="special">()</phrase></code> uses that tactic for <link linkend="wait_done"><code><phrase
role="identifier">Done</phrase></code></link>:
</para>
<para>
<programlisting><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="special">...</phrase> <phrase role="identifier">Fns</phrase> <phrase role="special">&gt;</phrase>
<phrase role="keyword">void</phrase> <phrase role="identifier">wait_first_simple</phrase><phrase role="special">(</phrase> <phrase role="identifier">Fns</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="special">...</phrase> <phrase role="identifier">functions</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
<phrase role="comment">// Use shared_ptr because each function's fiber will bind it separately,</phrase>
<phrase role="comment">// and we're going to return before the last of them completes.</phrase>
<phrase role="keyword">auto</phrase> <phrase role="identifier">done</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">make_shared</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Done</phrase> <phrase role="special">&gt;()</phrase> <phrase role="special">);</phrase>
<phrase role="identifier">wait_first_simple_impl</phrase><phrase role="special">(</phrase> <phrase role="identifier">done</phrase><phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">forward</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Fns</phrase> <phrase role="special">&gt;(</phrase> <phrase role="identifier">functions</phrase><phrase role="special">)</phrase> <phrase role="special">...</phrase> <phrase role="special">);</phrase>
<phrase role="identifier">done</phrase><phrase role="special">-&gt;</phrase><phrase role="identifier">wait</phrase><phrase role="special">();</phrase>
<phrase role="special">}</phrase>
</programlisting>
</para>
<para>
<anchor id="wait_first_simple_impl"/><code><phrase role="identifier">wait_first_simple_impl</phrase><phrase
role="special">()</phrase></code> is an ordinary recursion over the argument
pack, capturing <code><phrase role="identifier">Done</phrase><phrase role="special">::</phrase><phrase
role="identifier">ptr</phrase></code> for each new fiber:
</para>
<para>
<programlisting><phrase role="comment">// Degenerate case: when there are no functions to wait for, return</phrase>
<phrase role="comment">// immediately.</phrase>
<phrase role="keyword">void</phrase> <phrase role="identifier">wait_first_simple_impl</phrase><phrase role="special">(</phrase> <phrase role="identifier">Done</phrase><phrase role="special">::</phrase><phrase role="identifier">ptr</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
<phrase role="special">}</phrase>
<phrase role="comment">// When there's at least one function to wait for, launch it and recur to</phrase>
<phrase role="comment">// process the rest.</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="special">...</phrase> <phrase role="identifier">Fns</phrase> <phrase role="special">&gt;</phrase>
<phrase role="keyword">void</phrase> <phrase role="identifier">wait_first_simple_impl</phrase><phrase role="special">(</phrase> <phrase role="identifier">Done</phrase><phrase role="special">::</phrase><phrase role="identifier">ptr</phrase> <phrase role="identifier">done</phrase><phrase role="special">,</phrase> <phrase role="identifier">Fn</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="identifier">function</phrase><phrase role="special">,</phrase> <phrase role="identifier">Fns</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="special">...</phrase> <phrase role="identifier">functions</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
<phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">fiber</phrase><phrase role="special">(</phrase> <phrase role="special">[</phrase><phrase role="identifier">done</phrase><phrase role="special">,</phrase> <phrase role="identifier">function</phrase><phrase role="special">](){</phrase>
<phrase role="identifier">function</phrase><phrase role="special">();</phrase>
<phrase role="identifier">done</phrase><phrase role="special">-&gt;</phrase><phrase role="identifier">notify</phrase><phrase role="special">();</phrase>
<phrase role="special">}).</phrase><phrase role="identifier">detach</phrase><phrase role="special">();</phrase>
<phrase role="identifier">wait_first_simple_impl</phrase><phrase role="special">(</phrase> <phrase role="identifier">done</phrase><phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">forward</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Fns</phrase> <phrase role="special">&gt;(</phrase> <phrase role="identifier">functions</phrase><phrase role="special">)</phrase> <phrase role="special">...</phrase> <phrase role="special">);</phrase>
<phrase role="special">}</phrase>
</programlisting>
</para>
<para>
The body of the fiber's lambda is extremely simple, as promised: call the
function, notify <link linkend="wait_done"><code><phrase role="identifier">Done</phrase></code></link>
when it returns. The first fiber to do so allows <code><phrase role="identifier">wait_first_simple</phrase><phrase
role="special">()</phrase></code> to return &mdash; which is why it's useful to
have <code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase
role="identifier">shared_ptr</phrase><phrase role="special">&lt;</phrase><phrase
role="identifier">Done</phrase><phrase role="special">&gt;</phrase></code>
manage the lifespan of our <code><phrase role="identifier">Done</phrase></code>
object rather than declaring it as a stack variable in <code><phrase role="identifier">wait_first_simple</phrase><phrase
role="special">()</phrase></code>.
</para>
<para>
This is how you might call it:
</para>
<para>
<programlisting><phrase role="identifier">wait_first_simple</phrase><phrase role="special">(</phrase>
<phrase role="special">[](){</phrase> <phrase role="identifier">sleeper</phrase><phrase role="special">(</phrase><phrase role="string">&quot;wfs_long&quot;</phrase><phrase role="special">,</phrase> <phrase role="number">150</phrase><phrase role="special">);</phrase> <phrase role="special">},</phrase>
<phrase role="special">[](){</phrase> <phrase role="identifier">sleeper</phrase><phrase role="special">(</phrase><phrase role="string">&quot;wfs_medium&quot;</phrase><phrase role="special">,</phrase> <phrase role="number">100</phrase><phrase role="special">);</phrase> <phrase role="special">},</phrase>
<phrase role="special">[](){</phrase> <phrase role="identifier">sleeper</phrase><phrase role="special">(</phrase><phrase role="string">&quot;wfs_short&quot;</phrase><phrase role="special">,</phrase> <phrase role="number">50</phrase><phrase role="special">);</phrase> <phrase role="special">});</phrase>
</programlisting>
</para>
<para>
In this example, control resumes after <code><phrase role="identifier">wait_first_simple</phrase><phrase
role="special">()</phrase></code> when <link linkend="wait_sleeper"><code><phrase
role="identifier">sleeper</phrase><phrase role="special">(</phrase><phrase
role="string">&quot;wfs_short&quot;</phrase><phrase role="special">,</phrase>
<phrase role="number">50</phrase><phrase role="special">)</phrase></code></link>
completes &mdash; even though the other two <code><phrase role="identifier">sleeper</phrase><phrase
role="special">()</phrase></code> fibers are still running.
</para>
</section>
<section id="fiber.when_any.when_any.when_any__return_value">
<title><link linkend="fiber.when_any.when_any.when_any__return_value">when_any,
return value</link></title>
<para>
It seems more useful to add the ability to capture the return value from
the first of the task functions to complete. Again, we assume that none
will throw an exception.
</para>
<para>
One tactic would be to adapt our <link linkend="wait_done"><code><phrase
role="identifier">Done</phrase></code></link> class to store the first
of the return values, rather than a simple <code><phrase role="keyword">bool</phrase></code>.
However, we choose instead to use a <link linkend="class_bounded_channel"> <code>bounded_channel&lt;&gt;</code></link> of
size 1. We only need to enqueue the first value. All subsequent <link linkend="bounded_channel_push"> <code>bounded_channel::push()</code></link>
calls
can return <code><phrase role="identifier">full</phrase></code>.
</para>
<para>
In fact, once we've retrieved the first (only) value from the <code><phrase
role="identifier">bounded_channel</phrase></code>, we even <link linkend="bounded_channel_close"> <code>bounded_channel::close()</code></link> it.
We still have no need of any subsequent values. Subsequent <code><phrase
role="identifier">push</phrase><phrase role="special">()</phrase></code>
calls will return <code><phrase role="identifier">closed</phrase></code>.
</para>
<para>
<anchor id="wait_first_value"/>
<programlisting><phrase role="comment">// Assume that all passed functions have the same return type. The return type</phrase>
<phrase role="comment">// of wait_first_value() is the return type of the first passed function. It is</phrase>
<phrase role="comment">// simply invalid to pass NO functions.</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="special">...</phrase> <phrase role="identifier">Fns</phrase> <phrase role="special">&gt;</phrase>
<phrase role="keyword">typename</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">result_of</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Fn</phrase><phrase role="special">()</phrase> <phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase>
<phrase role="identifier">wait_first_value</phrase><phrase role="special">(</phrase> <phrase role="identifier">Fn</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="identifier">function</phrase><phrase role="special">,</phrase> <phrase role="identifier">Fns</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="special">...</phrase> <phrase role="identifier">functions</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
<phrase role="keyword">typedef</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">result_of</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Fn</phrase><phrase role="special">()</phrase> <phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase> <phrase role="identifier">return_t</phrase><phrase role="special">;</phrase>
<phrase role="keyword">typedef</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">bounded_channel</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">return_t</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">channel_t</phrase><phrase role="special">;</phrase>
<phrase role="comment">// bounded_channel of size 1: only store the first value</phrase>
<phrase role="keyword">auto</phrase> <phrase role="identifier">channelp</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">make_shared</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">channel_t</phrase> <phrase role="special">&gt;(</phrase> <phrase role="number">1</phrase><phrase role="special">)</phrase> <phrase role="special">);</phrase>
<phrase role="comment">// launch all the relevant fibers</phrase>
<phrase role="identifier">wait_first_value_impl</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">return_t</phrase> <phrase role="special">&gt;(</phrase> <phrase role="identifier">channelp</phrase><phrase role="special">,</phrase>
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">forward</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Fn</phrase> <phrase role="special">&gt;(</phrase> <phrase role="identifier">function</phrase><phrase role="special">),</phrase>
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">forward</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Fns</phrase> <phrase role="special">&gt;(</phrase> <phrase role="identifier">functions</phrase><phrase role="special">)</phrase> <phrase role="special">...</phrase> <phrase role="special">);</phrase>
<phrase role="comment">// retrieve the first value</phrase>
<phrase role="identifier">return_t</phrase> <phrase role="identifier">value</phrase><phrase role="special">(</phrase> <phrase role="identifier">channelp</phrase><phrase role="special">-&gt;</phrase><phrase role="identifier">value_pop</phrase><phrase role="special">()</phrase> <phrase role="special">);</phrase>
<phrase role="comment">// close the channel: no subsequent push() has to succeed</phrase>
<phrase role="identifier">channelp</phrase><phrase role="special">-&gt;</phrase><phrase role="identifier">close</phrase><phrase role="special">();</phrase>
<phrase role="keyword">return</phrase> <phrase role="identifier">value</phrase><phrase role="special">;</phrase>
<phrase role="special">}</phrase>
</programlisting>
</para>
<para>
<anchor id="wait_first_value_impl"/>The meat of the <code><phrase role="identifier">wait_first_value_impl</phrase><phrase
role="special">()</phrase></code> function is as you might expect:
</para>
<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">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Fn</phrase> <phrase role="special">&gt;</phrase>
<phrase role="keyword">void</phrase> <phrase role="identifier">wait_first_value_impl</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">shared_ptr</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">bounded_channel</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">T</phrase> <phrase role="special">&gt;</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">channel</phrase><phrase role="special">,</phrase>
<phrase role="identifier">Fn</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="identifier">function</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
<phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">fiber</phrase><phrase role="special">(</phrase> <phrase role="special">[</phrase><phrase role="identifier">channel</phrase><phrase role="special">,</phrase> <phrase role="identifier">function</phrase><phrase role="special">](){</phrase>
<phrase role="comment">// Ignore channel_op_status returned by push(): might be closed, might</phrase>
<phrase role="comment">// be full; we simply don't care.</phrase>
<phrase role="identifier">channel</phrase><phrase role="special">-&gt;</phrase><phrase role="identifier">push</phrase><phrase role="special">(</phrase> <phrase role="identifier">function</phrase><phrase role="special">()</phrase> <phrase role="special">);</phrase>
<phrase role="special">}).</phrase><phrase role="identifier">detach</phrase><phrase role="special">();</phrase>
<phrase role="special">}</phrase>
</programlisting>
</para>
<para>
It calls the passed function, pushes its return value and ignores the
<code><phrase role="identifier">push</phrase><phrase role="special">()</phrase></code>
result. You might call it like this:
</para>
<para>
<programlisting><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="identifier">result</phrase> <phrase role="special">=</phrase> <phrase role="identifier">wait_first_value</phrase><phrase role="special">(</phrase>
<phrase role="special">[](){</phrase> <phrase role="keyword">return</phrase> <phrase role="identifier">sleeper</phrase><phrase role="special">(</phrase><phrase role="string">&quot;wfv_third&quot;</phrase><phrase role="special">,</phrase> <phrase role="number">150</phrase><phrase role="special">);</phrase> <phrase role="special">},</phrase>
<phrase role="special">[](){</phrase> <phrase role="keyword">return</phrase> <phrase role="identifier">sleeper</phrase><phrase role="special">(</phrase><phrase role="string">&quot;wfv_second&quot;</phrase><phrase role="special">,</phrase> <phrase role="number">100</phrase><phrase role="special">);</phrase> <phrase role="special">},</phrase>
<phrase role="special">[](){</phrase> <phrase role="keyword">return</phrase> <phrase role="identifier">sleeper</phrase><phrase role="special">(</phrase><phrase role="string">&quot;wfv_first&quot;</phrase><phrase role="special">,</phrase> <phrase role="number">50</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;wait_first_value() =&gt; &quot;</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="identifier">result</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">assert</phrase><phrase role="special">(</phrase><phrase role="identifier">result</phrase> <phrase role="special">==</phrase> <phrase role="string">&quot;wfv_first&quot;</phrase><phrase role="special">);</phrase>
</programlisting>
</para>
</section>
<section id="fiber.when_any.when_any.when_any__produce_first_outcome__whether_result_or_exception">
<title><link linkend="fiber.when_any.when_any.when_any__produce_first_outcome__whether_result_or_exception">when_any,
produce first outcome, whether result or exception</link></title>
<para>
We may not be running in an environment in which we can guarantee no exception
will be thrown by any of our task functions. In that case, the above implementations
of <code><phrase role="identifier">wait_first_something</phrase><phrase
role="special">()</phrase></code> would be naïve: as mentioned in <link
linkend="exceptions">the section on Fiber Management</link>, an uncaught
exception in one of our task fibers would cause <code><phrase role="identifier">std</phrase><phrase
role="special">::</phrase><phrase role="identifier">terminate</phrase><phrase
role="special">()</phrase></code> to be called.
</para>
<para>
Let's at least ensure that such an exception would propagate to the fiber
awaiting the first result. We can use <link linkend="class_future"> <code>future&lt;&gt;</code></link> to transport
either a return value or an exception. Therefore, we will change <link
linkend="wait_first_value"><code><phrase role="identifier">wait_first_value</phrase><phrase
role="special">()</phrase></code></link>'s <link linkend="class_bounded_channel"> <code>bounded_channel&lt;&gt;</code></link> to
hold <code><phrase role="identifier">future</phrase><phrase role="special">&lt;</phrase>
<phrase role="identifier">T</phrase> <phrase role="special">&gt;</phrase></code>
items instead of simply <code><phrase role="identifier">T</phrase></code>.
</para>
<para>
Once we have a <code><phrase role="identifier">future</phrase><phrase role="special">&lt;&gt;</phrase></code>
in hand, all we need do is call <link linkend="future_get"> <code>future::get()</code></link>, which will either
return the value or rethrow the exception.
</para>
<para>
<anchor id="wait_first_outcome"/>
<programlisting><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="special">...</phrase> <phrase role="identifier">Fns</phrase> <phrase role="special">&gt;</phrase>
<phrase role="keyword">typename</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">result_of</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Fn</phrase><phrase role="special">()</phrase> <phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase>
<phrase role="identifier">wait_first_outcome</phrase><phrase role="special">(</phrase> <phrase role="identifier">Fn</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="identifier">function</phrase><phrase role="special">,</phrase> <phrase role="identifier">Fns</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="special">...</phrase> <phrase role="identifier">functions</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
<phrase role="comment">// In this case, the value we pass through the channel is actually a</phrase>
<phrase role="comment">// future -- which is already ready. future can carry either a value or an</phrase>
<phrase role="comment">// exception.</phrase>
<phrase role="keyword">typedef</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">result_of</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Fn</phrase><phrase role="special">()</phrase> <phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase> <phrase role="identifier">return_t</phrase><phrase role="special">;</phrase>
<phrase role="keyword">typedef</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">future</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">return_t</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">future_t</phrase><phrase role="special">;</phrase>
<phrase role="keyword">typedef</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">bounded_channel</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">future_t</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">channel_t</phrase><phrase role="special">;</phrase>
<phrase role="comment">// bounded_channel of size 1: only store the first future</phrase>
<phrase role="keyword">auto</phrase> <phrase role="identifier">channelp</phrase><phrase role="special">(</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">make_shared</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">channel_t</phrase> <phrase role="special">&gt;(</phrase> <phrase role="number">1</phrase><phrase role="special">)</phrase> <phrase role="special">);</phrase>
<phrase role="comment">// launch all the relevant fibers</phrase>
<phrase role="identifier">wait_first_outcome_impl</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">return_t</phrase> <phrase role="special">&gt;(</phrase> <phrase role="identifier">channelp</phrase><phrase role="special">,</phrase>
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">forward</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Fn</phrase> <phrase role="special">&gt;(</phrase> <phrase role="identifier">function</phrase><phrase role="special">),</phrase>
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">forward</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Fns</phrase> <phrase role="special">&gt;(</phrase> <phrase role="identifier">functions</phrase><phrase role="special">)</phrase> <phrase role="special">...</phrase> <phrase role="special">);</phrase>
<phrase role="comment">// retrieve the first future</phrase>
<phrase role="identifier">future_t</phrase> <phrase role="identifier">future</phrase><phrase role="special">(</phrase> <phrase role="identifier">channelp</phrase><phrase role="special">-&gt;</phrase><phrase role="identifier">value_pop</phrase><phrase role="special">()</phrase> <phrase role="special">);</phrase>
<phrase role="comment">// close the channel: no subsequent push() has to succeed</phrase>
<phrase role="identifier">channelp</phrase><phrase role="special">-&gt;</phrase><phrase role="identifier">close</phrase><phrase role="special">();</phrase>
<phrase role="comment">// either return value or throw exception</phrase>
<phrase role="keyword">return</phrase> <phrase role="identifier">future</phrase><phrase role="special">.</phrase><phrase role="identifier">get</phrase><phrase role="special">();</phrase>
<phrase role="special">}</phrase>
</programlisting>
</para>
<para>
So far so good &mdash; but there's a timing issue. How should we obtain the <code><phrase
role="identifier">future</phrase><phrase role="special">&lt;&gt;</phrase></code>
to <link linkend="bounded_channel_push"> <code>bounded_channel::push()</code></link> on the channel?
</para>
<para>
We could call <link linkend="fibers_async"> <code>fibers::async()</code></link>. That would certainly produce
a <code><phrase role="identifier">future</phrase><phrase role="special">&lt;&gt;</phrase></code>
for the task function. The trouble is that it would return too quickly!
We only want <code><phrase role="identifier">future</phrase><phrase role="special">&lt;&gt;</phrase></code>
items for <emphasis>completed</emphasis> tasks on our <code><phrase role="identifier">bounded_channel</phrase><phrase
role="special">&lt;&gt;</phrase></code>. In fact, we only want the <code><phrase
role="identifier">future</phrase><phrase role="special">&lt;&gt;</phrase></code>
for the one that completes first. If each fiber launched by <code><phrase
role="identifier">wait_first_outcome</phrase><phrase role="special">()</phrase></code>
were to <code><phrase role="identifier">push</phrase><phrase role="special">()</phrase></code>
the result of calling <code><phrase role="identifier">async</phrase><phrase
role="special">()</phrase></code>, the channel would only ever report the
result of the leftmost task item &mdash; <emphasis>not</emphasis> the one that
completes most quickly.
</para>
<para>
Calling <link linkend="future_get"> <code>future::get()</code></link> on the future returned by <code><phrase
role="identifier">async</phrase><phrase role="special">()</phrase></code>
wouldn't be right. You can only call <code><phrase role="identifier">get</phrase><phrase
role="special">()</phrase></code> once per <code><phrase role="identifier">future</phrase><phrase
role="special">&lt;&gt;</phrase></code> instance! And if there were an
exception, it would be rethrown inside the helper fiber at the producer
end of the channel, rather than propagated to the consumer end.
</para>
<para>
We could call <link linkend="future_wait"> <code>future::wait()</code></link>. That would block the helper fiber
until the <code><phrase role="identifier">future</phrase><phrase role="special">&lt;&gt;</phrase></code>
became ready, at which point we could <code><phrase role="identifier">push</phrase><phrase
role="special">()</phrase></code> it to be retrieved by <code><phrase role="identifier">wait_first_outcome</phrase><phrase
role="special">()</phrase></code>.
</para>
<para>
That would work &mdash; but there's a simpler tactic that avoids creating an extra
fiber. We can wrap the task function in a <link linkend="class_packaged_task"> <code>packaged_task&lt;&gt;</code></link>.
While one naturally thinks of passing a <code><phrase role="identifier">packaged_task</phrase><phrase
role="special">&lt;&gt;</phrase></code> to a new fiber &mdash; that is, in fact,
what <code><phrase role="identifier">async</phrase><phrase role="special">()</phrase></code>
does &mdash; in this case, we're already running in the helper fiber at the producer
end of the channel! We can simply <emphasis>call</emphasis> the <code><phrase
role="identifier">packaged_task</phrase><phrase role="special">&lt;&gt;</phrase></code>.
On return from that call, the task function has completed, meaning that
the <code><phrase role="identifier">future</phrase><phrase role="special">&lt;&gt;</phrase></code>
obtained from the <code><phrase role="identifier">packaged_task</phrase><phrase
role="special">&lt;&gt;</phrase></code> is certain to be ready. At that
point we can simply <code><phrase role="identifier">push</phrase><phrase
role="special">()</phrase></code> it to the channel.
</para>
<para>
<anchor id="wait_first_outcome_impl"/>
<programlisting><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Fn</phrase> <phrase role="special">&gt;</phrase>
<phrase role="keyword">void</phrase> <phrase role="identifier">wait_first_outcome_impl</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">shared_ptr</phrase><phrase role="special">&lt;</phrase>
<phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">bounded_channel</phrase><phrase role="special">&lt;</phrase>
<phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">future</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">T</phrase> <phrase role="special">&gt;</phrase> <phrase role="special">&gt;</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">channel</phrase><phrase role="special">,</phrase>
<phrase role="identifier">Fn</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="identifier">function</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
<phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">fiber</phrase><phrase role="special">(</phrase> <phrase role="special">[</phrase><phrase role="identifier">channel</phrase><phrase role="special">,</phrase> <phrase role="identifier">function</phrase><phrase role="special">](){</phrase>
<phrase role="comment">// Instantiate a packaged_task to capture any exception thrown by</phrase>
<phrase role="comment">// function.</phrase>
<phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">packaged_task</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">T</phrase><phrase role="special">()</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">task</phrase><phrase role="special">(</phrase> <phrase role="identifier">function</phrase><phrase role="special">);</phrase>
<phrase role="comment">// Immediately run this packaged_task on same fiber. We want</phrase>
<phrase role="comment">// function() to have completed BEFORE we push the future.</phrase>
<phrase role="identifier">task</phrase><phrase role="special">();</phrase>
<phrase role="comment">// Pass the corresponding future to consumer. Ignore channel_op_status</phrase>
<phrase role="comment">// returned by push(): might be closed, might be full; we simply don't</phrase>
<phrase role="comment">// care.</phrase>
<phrase role="identifier">channel</phrase><phrase role="special">-&gt;</phrase><phrase role="identifier">push</phrase><phrase role="special">(</phrase> <phrase role="identifier">task</phrase><phrase role="special">.</phrase><phrase role="identifier">get_future</phrase><phrase role="special">()</phrase> <phrase role="special">);</phrase>
<phrase role="special">}).</phrase><phrase role="identifier">detach</phrase><phrase role="special">();</phrase>
<phrase role="special">}</phrase>
</programlisting>
</para>
<para>
Calling it might look like this:
</para>
<para>
<programlisting><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="identifier">result</phrase> <phrase role="special">=</phrase> <phrase role="identifier">wait_first_outcome</phrase><phrase role="special">(</phrase>
<phrase role="special">[](){</phrase> <phrase role="keyword">return</phrase> <phrase role="identifier">sleeper</phrase><phrase role="special">(</phrase><phrase role="string">&quot;wfos_first&quot;</phrase><phrase role="special">,</phrase> <phrase role="number">50</phrase><phrase role="special">);</phrase> <phrase role="special">},</phrase>
<phrase role="special">[](){</phrase> <phrase role="keyword">return</phrase> <phrase role="identifier">sleeper</phrase><phrase role="special">(</phrase><phrase role="string">&quot;wfos_second&quot;</phrase><phrase role="special">,</phrase> <phrase role="number">100</phrase><phrase role="special">);</phrase> <phrase role="special">},</phrase>
<phrase role="special">[](){</phrase> <phrase role="keyword">return</phrase> <phrase role="identifier">sleeper</phrase><phrase role="special">(</phrase><phrase role="string">&quot;wfos_third&quot;</phrase><phrase role="special">,</phrase> <phrase role="number">150</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;wait_first_outcome(success) =&gt; &quot;</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="identifier">result</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">assert</phrase><phrase role="special">(</phrase><phrase role="identifier">result</phrase> <phrase role="special">==</phrase> <phrase role="string">&quot;wfos_first&quot;</phrase><phrase role="special">);</phrase>
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="identifier">thrown</phrase><phrase role="special">;</phrase>
<phrase role="keyword">try</phrase> <phrase role="special">{</phrase>
<phrase role="identifier">result</phrase> <phrase role="special">=</phrase> <phrase role="identifier">wait_first_outcome</phrase><phrase role="special">(</phrase>
<phrase role="special">[](){</phrase> <phrase role="keyword">return</phrase> <phrase role="identifier">sleeper</phrase><phrase role="special">(</phrase><phrase role="string">&quot;wfof_first&quot;</phrase><phrase role="special">,</phrase> <phrase role="number">50</phrase><phrase role="special">,</phrase> <phrase role="keyword">true</phrase><phrase role="special">);</phrase> <phrase role="special">},</phrase>
<phrase role="special">[](){</phrase> <phrase role="keyword">return</phrase> <phrase role="identifier">sleeper</phrase><phrase role="special">(</phrase><phrase role="string">&quot;wfof_second&quot;</phrase><phrase role="special">,</phrase> <phrase role="number">100</phrase><phrase role="special">);</phrase> <phrase role="special">},</phrase>
<phrase role="special">[](){</phrase> <phrase role="keyword">return</phrase> <phrase role="identifier">sleeper</phrase><phrase role="special">(</phrase><phrase role="string">&quot;wfof_third&quot;</phrase><phrase role="special">,</phrase> <phrase role="number">150</phrase><phrase role="special">);</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">thrown</phrase> <phrase role="special">=</phrase> <phrase role="identifier">e</phrase><phrase role="special">.</phrase><phrase role="identifier">what</phrase><phrase role="special">();</phrase>
<phrase role="special">}</phrase>
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cout</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="string">&quot;wait_first_outcome(fail) threw '&quot;</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="identifier">thrown</phrase>
<phrase role="special">&lt;&lt;</phrase> <phrase role="string">&quot;'&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">assert</phrase><phrase role="special">(</phrase><phrase role="identifier">thrown</phrase> <phrase role="special">==</phrase> <phrase role="string">&quot;wfof_first&quot;</phrase><phrase role="special">);</phrase>
</programlisting>
</para>
</section>
<section id="fiber.when_any.when_any.when_any__produce_first_success">
<title><link linkend="fiber.when_any.when_any.when_any__produce_first_success">when_any,
produce first success</link></title>
<para>
One scenario for &quot;when_any&quot; functionality is when we're redundantly
contacting some number of possibly-unreliable web services. Not only might
they be slow &mdash; any one of them might produce a failure rather than the desired
result.
</para>
<para>
In such a case, <link linkend="wait_first_outcome"><code><phrase role="identifier">wait_first_outcome</phrase><phrase
role="special">()</phrase></code></link> isn't the right approach. If one
of the services produces an error quickly, while another follows up with
a real answer, we don't want to prefer the error just because it arrived
first!
</para>
<para>
Given the <code><phrase role="identifier">bounded_queue</phrase><phrase
role="special">&lt;</phrase> <phrase role="identifier">future</phrase><phrase
role="special">&lt;</phrase> <phrase role="identifier">T</phrase> <phrase
role="special">&gt;</phrase> <phrase role="special">&gt;</phrase></code>
we already constructed for <code><phrase role="identifier">wait_first_outcome</phrase><phrase
role="special">()</phrase></code>, though, we can readily recast the interface
function to deliver the first <emphasis>successful</emphasis> result.
</para>
<para>
That does beg the question: what if <emphasis>all</emphasis> the task functions
throw an exception? In that case we'd probably better know about it.
</para>
<para>
<anchor id="exception_list"/>The <ulink url="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4407.html#parallel.exceptions.synopsis">C++
Parallelism Draft Technical Specification</ulink> proposes a <code><phrase
role="identifier">std</phrase><phrase role="special">::</phrase><phrase
role="identifier">exception_list</phrase></code> exception capable of delivering
a collection of <code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase
role="identifier">exception_ptr</phrase></code>s. Until that becomes universally
available, let's fake up an <code><phrase role="identifier">exception_list</phrase></code>
of our own:
</para>
<para>
<programlisting><phrase role="keyword">class</phrase> <phrase role="identifier">exception_list</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">runtime_error</phrase> <phrase role="special">{</phrase>
<phrase role="keyword">public</phrase><phrase role="special">:</phrase>
<phrase role="identifier">exception_list</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">what</phrase><phrase role="special">)</phrase> <phrase role="special">:</phrase>
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">runtime_error</phrase><phrase role="special">(</phrase> <phrase role="identifier">what</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
<phrase role="special">}</phrase>
<phrase role="keyword">typedef</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">vector</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">exception_ptr</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">bundle_t</phrase><phrase role="special">;</phrase>
<phrase role="comment">// N4407 proposed std::exception_list API</phrase>
<phrase role="keyword">typedef</phrase> <phrase role="identifier">bundle_t</phrase><phrase role="special">::</phrase><phrase role="identifier">const_iterator</phrase> <phrase role="identifier">iterator</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="keyword">const</phrase> <phrase role="keyword">noexcept</phrase> <phrase role="special">{</phrase>
<phrase role="keyword">return</phrase> <phrase role="identifier">bundle_</phrase><phrase role="special">.</phrase><phrase role="identifier">size</phrase><phrase role="special">();</phrase>
<phrase role="special">}</phrase>
<phrase role="identifier">iterator</phrase> <phrase role="identifier">begin</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase> <phrase role="special">{</phrase>
<phrase role="keyword">return</phrase> <phrase role="identifier">bundle_</phrase><phrase role="special">.</phrase><phrase role="identifier">begin</phrase><phrase role="special">();</phrase>
<phrase role="special">}</phrase>
<phrase role="identifier">iterator</phrase> <phrase role="identifier">end</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase> <phrase role="special">{</phrase>
<phrase role="keyword">return</phrase> <phrase role="identifier">bundle_</phrase><phrase role="special">.</phrase><phrase role="identifier">end</phrase><phrase role="special">();</phrase>
<phrase role="special">}</phrase>
<phrase role="comment">// extension to populate</phrase>
<phrase role="keyword">void</phrase> <phrase role="identifier">add</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">exception_ptr</phrase> <phrase role="identifier">ep</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
<phrase role="identifier">bundle_</phrase><phrase role="special">.</phrase><phrase role="identifier">push_back</phrase><phrase role="special">(</phrase> <phrase role="identifier">ep</phrase><phrase role="special">);</phrase>
<phrase role="special">}</phrase>
<phrase role="keyword">private</phrase><phrase role="special">:</phrase>
<phrase role="identifier">bundle_t</phrase> <phrase role="identifier">bundle_</phrase><phrase role="special">;</phrase>
<phrase role="special">};</phrase>
</programlisting>
</para>
<para>
Now we can build <code><phrase role="identifier">wait_first_success</phrase><phrase
role="special">()</phrase></code>. We must enlarge our <code><phrase role="identifier">bounded_channel</phrase><phrase
role="special">&lt;&gt;</phrase></code>: it might need to hold a <code><phrase
role="identifier">future</phrase><phrase role="special">&lt;&gt;</phrase></code>
for every one of our task functions. (As noted in comments, we could use
<link linkend="class_unbounded_channel"> <code>unbounded_channel&lt;&gt;</code></link>, but this tactic allows
us to reuse <link linkend="wait_first_outcome_impl"><code><phrase role="identifier">wait_first_outcome_impl</phrase><phrase
role="special">()</phrase></code></link>.)
</para>
<para>
Instead of retrieving only the first <code><phrase role="identifier">future</phrase><phrase
role="special">&lt;&gt;</phrase></code> from the channel, we must now loop
over <code><phrase role="identifier">future</phrase><phrase role="special">&lt;&gt;</phrase></code>
items. Of course we must limit that iteration! If we launch only <code><phrase
role="identifier">count</phrase></code> producer fibers, the <code><phrase
role="special">(</phrase><phrase role="identifier">count</phrase><phrase
role="special">+</phrase><phrase role="number">1</phrase><phrase role="special">)</phrase></code>
<superscript>st</superscript>
<link linkend="bounded_channel_pop"> <code>bounded_channel::pop()</code></link> call would block forever.
</para>
<para>
Given a ready <code><phrase role="identifier">future</phrase><phrase role="special">&lt;&gt;</phrase></code>,
we can distinguish failure by calling <link linkend="future_get_exception_ptr"> <code>future::get_exception_ptr()</code></link>.
If the <code><phrase role="identifier">future</phrase><phrase role="special">&lt;&gt;</phrase></code>
in fact contains a result rather than an exception, <code><phrase role="identifier">get_exception_ptr</phrase><phrase
role="special">()</phrase></code> returns a <code><phrase role="identifier">std</phrase><phrase
role="special">::</phrase><phrase role="identifier">exception_ptr</phrase></code>
which is <code><phrase role="keyword">nullptr</phrase></code>. In that
case, we can confidently call <link linkend="future_get"> <code>future::get()</code></link>
to return that result
to our caller.
</para>
<para>
If the <code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase
role="identifier">exception_ptr</phrase></code> is <emphasis>not</emphasis>
<code><phrase role="keyword">nullptr</phrase></code>, though, we collect
it into our pending <code><phrase role="identifier">exception_list</phrase></code>
and loop back for the next <code><phrase role="identifier">future</phrase><phrase
role="special">&lt;&gt;</phrase></code> from the channel.
</para>
<para>
If we fall out of the loop &mdash; if every single task fiber threw an exception
&mdash; we throw the <code><phrase role="identifier">exception_list</phrase></code>
exception into which we've been collecting those <code><phrase role="identifier">std</phrase><phrase
role="special">::</phrase><phrase role="identifier">exception_ptr</phrase></code>s.
</para>
<para>
<anchor id="wait_first_success"/>
<programlisting><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="special">...</phrase> <phrase role="identifier">Fns</phrase> <phrase role="special">&gt;</phrase>
<phrase role="keyword">typename</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">result_of</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Fn</phrase><phrase role="special">()</phrase> <phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase>
<phrase role="identifier">wait_first_success</phrase><phrase role="special">(</phrase> <phrase role="identifier">Fn</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="identifier">function</phrase><phrase role="special">,</phrase> <phrase role="identifier">Fns</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="special">...</phrase> <phrase role="identifier">functions</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">count</phrase><phrase role="special">(</phrase> <phrase role="number">1</phrase> <phrase role="special">+</phrase> <phrase role="keyword">sizeof</phrase> <phrase role="special">...</phrase> <phrase role="special">(</phrase> <phrase role="identifier">functions</phrase><phrase role="special">)</phrase> <phrase role="special">);</phrase>
<phrase role="comment">// In this case, the value we pass through the channel is actually a</phrase>
<phrase role="comment">// future -- which is already ready. future can carry either a value or an</phrase>
<phrase role="comment">// exception.</phrase>
<phrase role="keyword">typedef</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">result_of</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Fn</phrase><phrase role="special">()</phrase> <phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase> <phrase role="identifier">return_t</phrase><phrase role="special">;</phrase>
<phrase role="keyword">typedef</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">future</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">return_t</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">future_t</phrase><phrase role="special">;</phrase>
<phrase role="keyword">typedef</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">bounded_channel</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">future_t</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">channel_t</phrase><phrase role="special">;</phrase>
<phrase role="comment">// make bounded_channel big enough to hold all results if need be</phrase>
<phrase role="comment">// (could use unbounded_channel this time, but let's just share</phrase>
<phrase role="comment">// wait_first_outcome_impl())</phrase>
<phrase role="keyword">auto</phrase> <phrase role="identifier">channelp</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">make_shared</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">channel_t</phrase> <phrase role="special">&gt;(</phrase> <phrase role="identifier">count</phrase><phrase role="special">)</phrase> <phrase role="special">);</phrase>
<phrase role="comment">// launch all the relevant fibers</phrase>
<phrase role="identifier">wait_first_outcome_impl</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">return_t</phrase> <phrase role="special">&gt;(</phrase> <phrase role="identifier">channelp</phrase><phrase role="special">,</phrase>
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">forward</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Fn</phrase> <phrase role="special">&gt;(</phrase> <phrase role="identifier">function</phrase><phrase role="special">),</phrase>
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">forward</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Fns</phrase> <phrase role="special">&gt;(</phrase> <phrase role="identifier">functions</phrase><phrase role="special">)</phrase> <phrase role="special">...</phrase> <phrase role="special">);</phrase>
<phrase role="comment">// instantiate exception_list, just in case</phrase>
<phrase role="identifier">exception_list</phrase> <phrase role="identifier">exceptions</phrase><phrase role="special">(</phrase><phrase role="string">&quot;wait_first_success() produced only errors&quot;</phrase><phrase role="special">);</phrase>
<phrase role="comment">// retrieve up to 'count' results -- but stop there!</phrase>
<phrase role="keyword">for</phrase> <phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</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">count</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">// retrieve the next future</phrase>
<phrase role="identifier">future_t</phrase> <phrase role="identifier">future</phrase><phrase role="special">(</phrase> <phrase role="identifier">channelp</phrase><phrase role="special">-&gt;</phrase><phrase role="identifier">value_pop</phrase><phrase role="special">()</phrase> <phrase role="special">);</phrase>
<phrase role="comment">// retrieve exception_ptr if any</phrase>
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">exception_ptr</phrase> <phrase role="identifier">error</phrase><phrase role="special">(</phrase> <phrase role="identifier">future</phrase><phrase role="special">.</phrase><phrase role="identifier">get_exception_ptr</phrase><phrase role="special">()</phrase> <phrase role="special">);</phrase>
<phrase role="comment">// if no error, then yay, return value</phrase>
<phrase role="keyword">if</phrase> <phrase role="special">(</phrase> <phrase role="special">!</phrase> <phrase role="identifier">error</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
<phrase role="comment">// close the channel: no subsequent push() has to succeed</phrase>
<phrase role="identifier">channelp</phrase><phrase role="special">-&gt;</phrase><phrase role="identifier">close</phrase><phrase role="special">();</phrase>
<phrase role="comment">// show caller the value we got</phrase>
<phrase role="keyword">return</phrase> <phrase role="identifier">future</phrase><phrase role="special">.</phrase><phrase role="identifier">get</phrase><phrase role="special">();</phrase>
<phrase role="special">}</phrase>
<phrase role="comment">// error is non-null: collect</phrase>
<phrase role="identifier">exceptions</phrase><phrase role="special">.</phrase><phrase role="identifier">add</phrase><phrase role="special">(</phrase> <phrase role="identifier">error</phrase><phrase role="special">);</phrase>
<phrase role="special">}</phrase>
<phrase role="comment">// We only arrive here when every passed function threw an exception.</phrase>
<phrase role="comment">// Throw our collection to inform caller.</phrase>
<phrase role="keyword">throw</phrase> <phrase role="identifier">exceptions</phrase><phrase role="special">;</phrase>
<phrase role="special">}</phrase>
</programlisting>
</para>
<para>
A call might look like this:
</para>
<para>
<programlisting><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="identifier">result</phrase> <phrase role="special">=</phrase> <phrase role="identifier">wait_first_success</phrase><phrase role="special">(</phrase>
<phrase role="special">[](){</phrase> <phrase role="keyword">return</phrase> <phrase role="identifier">sleeper</phrase><phrase role="special">(</phrase><phrase role="string">&quot;wfss_first&quot;</phrase><phrase role="special">,</phrase> <phrase role="number">50</phrase><phrase role="special">,</phrase> <phrase role="keyword">true</phrase><phrase role="special">);</phrase> <phrase role="special">},</phrase>
<phrase role="special">[](){</phrase> <phrase role="keyword">return</phrase> <phrase role="identifier">sleeper</phrase><phrase role="special">(</phrase><phrase role="string">&quot;wfss_second&quot;</phrase><phrase role="special">,</phrase> <phrase role="number">100</phrase><phrase role="special">);</phrase> <phrase role="special">},</phrase>
<phrase role="special">[](){</phrase> <phrase role="keyword">return</phrase> <phrase role="identifier">sleeper</phrase><phrase role="special">(</phrase><phrase role="string">&quot;wfss_third&quot;</phrase><phrase role="special">,</phrase> <phrase role="number">150</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;wait_first_success(success) =&gt; &quot;</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="identifier">result</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">assert</phrase><phrase role="special">(</phrase><phrase role="identifier">result</phrase> <phrase role="special">==</phrase> <phrase role="string">&quot;wfss_second&quot;</phrase><phrase role="special">);</phrase>
</programlisting>
</para>
</section>
<section id="fiber.when_any.when_any.when_any__heterogeneous_types">
<title><link linkend="fiber.when_any.when_any.when_any__heterogeneous_types">when_any,
heterogeneous types</link></title>
<para>
We would be remiss to ignore the case in which the various task functions
have distinct return types. That means that the value returned by the first
of them might have any one of those types. We can express that with <ulink
url="http://www.boost.org/doc/libs/release/doc/html/variant.html">Boost.Variant</ulink>.
</para>
<para>
To keep the example simple, we'll revert to pretending that none of them
can throw an exception. That makes <code><phrase role="identifier">wait_first_value_het</phrase><phrase
role="special">()</phrase></code> strongly resemble <link linkend="wait_first_value"><code><phrase
role="identifier">wait_first_value</phrase><phrase role="special">()</phrase></code></link>.
We can actually reuse <link linkend="wait_first_value_impl"><code><phrase
role="identifier">wait_first_value_impl</phrase><phrase role="special">()</phrase></code></link>,
merely passing <code><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase
role="identifier">variant</phrase><phrase role="special">&lt;</phrase><phrase
role="identifier">T0</phrase><phrase role="special">,</phrase> <phrase
role="identifier">T1</phrase><phrase role="special">,</phrase> <phrase
role="special">...&gt;</phrase></code> as the channel's value type rather
than the common <code><phrase role="identifier">T</phrase></code>!
</para>
<para>
Naturally this could be extended to use <link linkend="wait_first_success"><code><phrase
role="identifier">wait_first_success</phrase><phrase role="special">()</phrase></code></link>
semantics instead.
</para>
<para>
<programlisting><phrase role="comment">// No need to break out the first Fn for interface function: let the compiler</phrase>
<phrase role="comment">// complain if empty.</phrase>
<phrase role="comment">// Our functions have different return types, and we might have to return any</phrase>
<phrase role="comment">// of them. Use a variant, expanding std::result_of&lt;Fn()&gt;::type for each Fn in</phrase>
<phrase role="comment">// parameter pack.</phrase>
<phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="special">...</phrase> <phrase role="identifier">Fns</phrase> <phrase role="special">&gt;</phrase>
<phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">variant</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">result_of</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Fns</phrase><phrase role="special">()</phrase> <phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase> <phrase role="special">...</phrase> <phrase role="special">&gt;</phrase>
<phrase role="identifier">wait_first_value_het</phrase><phrase role="special">(</phrase> <phrase role="identifier">Fns</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="special">...</phrase> <phrase role="identifier">functions</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
<phrase role="comment">// Use bounded_channel&lt;boost::variant&lt;T1, T2, ...&gt;&gt;; see remarks above.</phrase>
<phrase role="keyword">typedef</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">variant</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">result_of</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Fns</phrase><phrase role="special">()</phrase> <phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase> <phrase role="special">...</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">return_t</phrase><phrase role="special">;</phrase>
<phrase role="keyword">typedef</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">bounded_channel</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">return_t</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">channel_t</phrase><phrase role="special">;</phrase>
<phrase role="comment">// bounded_channel of size 1: only store the first value</phrase>
<phrase role="keyword">auto</phrase> <phrase role="identifier">channelp</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">make_shared</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">channel_t</phrase> <phrase role="special">&gt;(</phrase> <phrase role="number">1</phrase><phrase role="special">)</phrase> <phrase role="special">);</phrase>
<phrase role="comment">// launch all the relevant fibers</phrase>
<phrase role="identifier">wait_first_value_impl</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">return_t</phrase> <phrase role="special">&gt;(</phrase> <phrase role="identifier">channelp</phrase><phrase role="special">,</phrase>
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">forward</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Fns</phrase> <phrase role="special">&gt;(</phrase> <phrase role="identifier">functions</phrase><phrase role="special">)</phrase> <phrase role="special">...</phrase> <phrase role="special">);</phrase>
<phrase role="comment">// retrieve the first value</phrase>
<phrase role="identifier">return_t</phrase> <phrase role="identifier">value</phrase><phrase role="special">(</phrase> <phrase role="identifier">channelp</phrase><phrase role="special">-&gt;</phrase><phrase role="identifier">value_pop</phrase><phrase role="special">()</phrase> <phrase role="special">);</phrase>
<phrase role="comment">// close the channel: no subsequent push() has to succeed</phrase>
<phrase role="identifier">channelp</phrase><phrase role="special">-&gt;</phrase><phrase role="identifier">close</phrase><phrase role="special">();</phrase>
<phrase role="keyword">return</phrase> <phrase role="identifier">value</phrase><phrase role="special">;</phrase>
<phrase role="special">}</phrase>
</programlisting>
</para>
<para>
It might be called like this:
</para>
<para>
<programlisting><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">variant</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase><phrase role="special">,</phrase> <phrase role="keyword">double</phrase><phrase role="special">,</phrase> <phrase role="keyword">int</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">result</phrase> <phrase role="special">=</phrase>
<phrase role="identifier">wait_first_value_het</phrase><phrase role="special">(</phrase>
<phrase role="special">[](){</phrase> <phrase role="keyword">return</phrase> <phrase role="identifier">sleeper</phrase><phrase role="special">(</phrase><phrase role="string">&quot;wfvh_third&quot;</phrase><phrase role="special">,</phrase> <phrase role="number">150</phrase><phrase role="special">);</phrase> <phrase role="special">},</phrase>
<phrase role="special">[](){</phrase> <phrase role="keyword">return</phrase> <phrase role="identifier">sleeper</phrase><phrase role="special">(</phrase><phrase role="number">3.14</phrase><phrase role="special">,</phrase> <phrase role="number">100</phrase><phrase role="special">);</phrase> <phrase role="special">},</phrase>
<phrase role="special">[](){</phrase> <phrase role="keyword">return</phrase> <phrase role="identifier">sleeper</phrase><phrase role="special">(</phrase><phrase role="number">17</phrase><phrase role="special">,</phrase> <phrase role="number">50</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;wait_first_value_het() =&gt; &quot;</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="identifier">result</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">assert</phrase><phrase role="special">(</phrase><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">get</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">int</phrase> <phrase role="special">&gt;(</phrase> <phrase role="identifier">result</phrase><phrase role="special">)</phrase> <phrase role="special">==</phrase> <phrase role="number">17</phrase><phrase role="special">);</phrase>
</programlisting>
</para>
</section>
</section>
<section id="fiber.when_any.when_all_functionality">
<title><link linkend="fiber.when_any.when_all_functionality">when_all functionality</link></title>
<section id="fiber.when_any.when_all_functionality.when_all__simple_completion">
<title><link linkend="fiber.when_any.when_all_functionality.when_all__simple_completion">when_all,
simple completion</link></title>
<para>
For the case in which we must wait for <emphasis>all</emphasis> task functions
to complete &mdash; but we don't need results (or expect exceptions) from any of
them &mdash; we can write <code><phrase role="identifier">wait_all_simple</phrase><phrase
role="special">()</phrase></code> that looks remarkably like <link linkend="wait_first_simple"><code><phrase
role="identifier">wait_first_simple</phrase><phrase role="special">()</phrase></code></link>.
The difference is that instead of our <link linkend="wait_done"><code><phrase
role="identifier">Done</phrase></code></link> class, we instantiate a <link linkend="class_barrier"> <code>barrier</code></link> and
call its <link linkend="barrier_wait"> <code>barrier::wait()</code></link>.
</para>
<para>
We initialize the <code><phrase role="identifier">barrier</phrase></code>
with <code><phrase role="special">(</phrase><phrase role="identifier">count</phrase><phrase
role="special">+</phrase><phrase role="number">1</phrase><phrase role="special">)</phrase></code>
because we are launching <code><phrase role="identifier">count</phrase></code>
fibers, plus the <code><phrase role="identifier">wait</phrase><phrase role="special">()</phrase></code>
call within <code><phrase role="identifier">wait_all_simple</phrase><phrase
role="special">()</phrase></code> itself.
</para>
<para>
<programlisting><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="special">...</phrase> <phrase role="identifier">Fns</phrase> <phrase role="special">&gt;</phrase>
<phrase role="keyword">void</phrase> <phrase role="identifier">wait_all_simple</phrase><phrase role="special">(</phrase> <phrase role="identifier">Fns</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="special">...</phrase> <phrase role="identifier">functions</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">count</phrase><phrase role="special">(</phrase> <phrase role="keyword">sizeof</phrase> <phrase role="special">...</phrase> <phrase role="special">(</phrase> <phrase role="identifier">functions</phrase><phrase role="special">)</phrase> <phrase role="special">);</phrase>
<phrase role="comment">// Initialize a barrier(count+1) because we'll immediately wait on it. We</phrase>
<phrase role="comment">// don't want to wake up until 'count' more fibers wait on it. Even though</phrase>
<phrase role="comment">// we'll stick around until the last of them completes, use shared_ptr</phrase>
<phrase role="comment">// anyway because it's easier to be confident about lifespan issues.</phrase>
<phrase role="keyword">auto</phrase> <phrase role="identifier">barrier</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">make_shared</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">barrier</phrase> <phrase role="special">&gt;(</phrase> <phrase role="identifier">count</phrase> <phrase role="special">+</phrase> <phrase role="number">1</phrase><phrase role="special">)</phrase> <phrase role="special">);</phrase>
<phrase role="identifier">wait_all_simple_impl</phrase><phrase role="special">(</phrase> <phrase role="identifier">barrier</phrase><phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">forward</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Fns</phrase> <phrase role="special">&gt;(</phrase> <phrase role="identifier">functions</phrase><phrase role="special">)</phrase> <phrase role="special">...</phrase> <phrase role="special">);</phrase>
<phrase role="identifier">barrier</phrase><phrase role="special">-&gt;</phrase><phrase role="identifier">wait</phrase><phrase role="special">();</phrase>
<phrase role="special">}</phrase>
</programlisting>
</para>
<para>
As stated above, the only difference between <code><phrase role="identifier">wait_all_simple_impl</phrase><phrase
role="special">()</phrase></code> and <link linkend="wait_first_simple_impl"><code><phrase
role="identifier">wait_first_simple_impl</phrase><phrase role="special">()</phrase></code></link>
is that the former calls <code><phrase role="identifier">barrier</phrase><phrase
role="special">::</phrase><phrase role="identifier">wait</phrase><phrase
role="special">()</phrase></code> rather than <code><phrase role="identifier">Done</phrase><phrase
role="special">::</phrase><phrase role="identifier">notify</phrase><phrase
role="special">()</phrase></code>:
</para>
<para>
<programlisting><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="special">...</phrase> <phrase role="identifier">Fns</phrase> <phrase role="special">&gt;</phrase>
<phrase role="keyword">void</phrase> <phrase role="identifier">wait_all_simple_impl</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">shared_ptr</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">barrier</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">barrier</phrase><phrase role="special">,</phrase>
<phrase role="identifier">Fn</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="identifier">function</phrase><phrase role="special">,</phrase> <phrase role="identifier">Fns</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="special">...</phrase> <phrase role="identifier">functions</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
<phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">fiber</phrase><phrase role="special">(</phrase> <phrase role="special">[</phrase><phrase role="identifier">barrier</phrase><phrase role="special">,</phrase> <phrase role="identifier">function</phrase><phrase role="special">](){</phrase>
<phrase role="identifier">function</phrase><phrase role="special">();</phrase>
<phrase role="identifier">barrier</phrase><phrase role="special">-&gt;</phrase><phrase role="identifier">wait</phrase><phrase role="special">();</phrase>
<phrase role="special">}).</phrase><phrase role="identifier">detach</phrase><phrase role="special">();</phrase>
<phrase role="identifier">wait_all_simple_impl</phrase><phrase role="special">(</phrase> <phrase role="identifier">barrier</phrase><phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">forward</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Fns</phrase> <phrase role="special">&gt;(</phrase> <phrase role="identifier">functions</phrase><phrase role="special">)</phrase> <phrase role="special">...</phrase> <phrase role="special">);</phrase>
<phrase role="special">}</phrase>
</programlisting>
</para>
<para>
You might call it like this:
</para>
<para>
<programlisting><phrase role="identifier">wait_all_simple</phrase><phrase role="special">(</phrase>
<phrase role="special">[](){</phrase> <phrase role="identifier">sleeper</phrase><phrase role="special">(</phrase><phrase role="string">&quot;was_long&quot;</phrase><phrase role="special">,</phrase> <phrase role="number">150</phrase><phrase role="special">);</phrase> <phrase role="special">},</phrase>
<phrase role="special">[](){</phrase> <phrase role="identifier">sleeper</phrase><phrase role="special">(</phrase><phrase role="string">&quot;was_medium&quot;</phrase><phrase role="special">,</phrase> <phrase role="number">100</phrase><phrase role="special">);</phrase> <phrase role="special">},</phrase>
<phrase role="special">[](){</phrase> <phrase role="identifier">sleeper</phrase><phrase role="special">(</phrase><phrase role="string">&quot;was_short&quot;</phrase><phrase role="special">,</phrase> <phrase role="number">50</phrase><phrase role="special">);</phrase> <phrase role="special">});</phrase>
</programlisting>
</para>
<para>
Control will not return from the <code><phrase role="identifier">wait_all_simple</phrase><phrase
role="special">()</phrase></code> call until the last of its task functions
has completed.
</para>
</section>
<section id="fiber.when_any.when_all_functionality.when_all__return_values">
<title><link linkend="fiber.when_any.when_all_functionality.when_all__return_values">when_all,
return values</link></title>
<para>
As soon as we want to collect return values from all the task functions,
we can see right away how to reuse <link linkend="wait_first_value"><code><phrase
role="identifier">wait_first_value</phrase><phrase role="special">()</phrase></code></link>'s
channel&lt;T&gt; for the purpose. All we have to do is avoid closing it
after the first value!
</para>
<para>
But in fact, collecting multiple values raises an interesting question:
do we <emphasis>really</emphasis> want to wait until the slowest of them
has arrived? Wouldn't we rather process each result as soon as it becomes
available?
</para>
<para>
Fortunately we can present both APIs. Let's define <code><phrase role="identifier">wait_all_values_source</phrase><phrase
role="special">()</phrase></code> to return <code><phrase role="identifier">shared_ptr</phrase><phrase
role="special">&lt;</phrase><phrase role="identifier">unbounded_channel</phrase><phrase
role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase
role="special">&gt;&gt;</phrase></code>.<footnote id="fiber.when_any.when_all_functionality.when_all__return_values.f0">
<para>
We could have used either <link linkend="class_bounded_channel"> <code>bounded_channel&lt;&gt;</code></link> or
<link linkend="class_unbounded_channel"> <code>unbounded_channel&lt;&gt;</code></link>. We chose <code><phrase
role="identifier">unbounded_channel</phrase><phrase role="special">&lt;&gt;</phrase></code>
on the assumption that its simpler semantics imply a cheaper implementation.
</para>
</footnote>
</para>
<para>
<anchor id="wait_all_values"/>Given <code><phrase role="identifier">wait_all_values_source</phrase><phrase
role="special">()</phrase></code>, it's straightforward to implement <code><phrase
role="identifier">wait_all_values</phrase><phrase role="special">()</phrase></code>:
</para>
<para>
<programlisting><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="special">...</phrase> <phrase role="identifier">Fns</phrase> <phrase role="special">&gt;</phrase>
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">vector</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">result_of</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Fn</phrase><phrase role="special">()</phrase> <phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase> <phrase role="special">&gt;</phrase>
<phrase role="identifier">wait_all_values</phrase><phrase role="special">(</phrase> <phrase role="identifier">Fn</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="identifier">function</phrase><phrase role="special">,</phrase> <phrase role="identifier">Fns</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="special">...</phrase> <phrase role="identifier">functions</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">count</phrase><phrase role="special">(</phrase> <phrase role="number">1</phrase> <phrase role="special">+</phrase> <phrase role="keyword">sizeof</phrase> <phrase role="special">...</phrase> <phrase role="special">(</phrase> <phrase role="identifier">functions</phrase><phrase role="special">)</phrase> <phrase role="special">);</phrase>
<phrase role="keyword">typedef</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">result_of</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Fn</phrase><phrase role="special">()</phrase> <phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase> <phrase role="identifier">return_t</phrase><phrase role="special">;</phrase>
<phrase role="keyword">typedef</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">vector</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">return_t</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">vector_t</phrase><phrase role="special">;</phrase>
<phrase role="identifier">vector_t</phrase> <phrase role="identifier">results</phrase><phrase role="special">;</phrase>
<phrase role="identifier">results</phrase><phrase role="special">.</phrase><phrase role="identifier">reserve</phrase><phrase role="special">(</phrase> <phrase role="identifier">count</phrase><phrase role="special">);</phrase>
<phrase role="comment">// get channel</phrase>
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">shared_ptr</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">unbounded_channel</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">return_t</phrase> <phrase role="special">&gt;</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">channel</phrase> <phrase role="special">=</phrase>
<phrase role="identifier">wait_all_values_source</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">forward</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Fn</phrase> <phrase role="special">&gt;(</phrase> <phrase role="identifier">function</phrase><phrase role="special">),</phrase>
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">forward</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Fns</phrase> <phrase role="special">&gt;(</phrase> <phrase role="identifier">functions</phrase><phrase role="special">)</phrase> <phrase role="special">...</phrase> <phrase role="special">);</phrase>
<phrase role="comment">// fill results vector</phrase>
<phrase role="identifier">return_t</phrase> <phrase role="identifier">value</phrase><phrase role="special">;</phrase>
<phrase role="keyword">while</phrase> <phrase role="special">(</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">channel_op_status</phrase><phrase role="special">::</phrase><phrase role="identifier">success</phrase> <phrase role="special">==</phrase> <phrase role="identifier">channel</phrase><phrase role="special">-&gt;</phrase><phrase role="identifier">pop</phrase><phrase role="special">(</phrase><phrase role="identifier">value</phrase><phrase role="special">)</phrase> <phrase role="special">)</phrase> <phrase role="special">{</phrase>
<phrase role="identifier">results</phrase><phrase role="special">.</phrase><phrase role="identifier">push_back</phrase><phrase role="special">(</phrase> <phrase role="identifier">value</phrase><phrase role="special">);</phrase>
<phrase role="special">}</phrase>
<phrase role="comment">// return vector to caller</phrase>
<phrase role="keyword">return</phrase> <phrase role="identifier">results</phrase><phrase role="special">;</phrase>
<phrase role="special">}</phrase>
</programlisting>
</para>
<para>
It might be called like this:
</para>
<para>
<programlisting><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">vector</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">values</phrase> <phrase role="special">=</phrase>
<phrase role="identifier">wait_all_values</phrase><phrase role="special">(</phrase>
<phrase role="special">[](){</phrase> <phrase role="keyword">return</phrase> <phrase role="identifier">sleeper</phrase><phrase role="special">(</phrase><phrase role="string">&quot;wav_late&quot;</phrase><phrase role="special">,</phrase> <phrase role="number">150</phrase><phrase role="special">);</phrase> <phrase role="special">},</phrase>
<phrase role="special">[](){</phrase> <phrase role="keyword">return</phrase> <phrase role="identifier">sleeper</phrase><phrase role="special">(</phrase><phrase role="string">&quot;wav_middle&quot;</phrase><phrase role="special">,</phrase> <phrase role="number">100</phrase><phrase role="special">);</phrase> <phrase role="special">},</phrase>
<phrase role="special">[](){</phrase> <phrase role="keyword">return</phrase> <phrase role="identifier">sleeper</phrase><phrase role="special">(</phrase><phrase role="string">&quot;wav_early&quot;</phrase><phrase role="special">,</phrase> <phrase role="number">50</phrase><phrase role="special">);</phrase> <phrase role="special">});</phrase>
</programlisting>
</para>
<para>
As you can see from the loop in <code><phrase role="identifier">wait_all_values</phrase><phrase
role="special">()</phrase></code>, instead of requiring its caller to count
values, we define <code><phrase role="identifier">wait_all_values_source</phrase><phrase
role="special">()</phrase></code> to <link linkend="unbounded_channel_close"> <code>unbounded_channel::close()</code></link> the
channel when done. But how do we do that? Each producer fiber is independent.
It has no idea whether it is the last one to <link linkend="unbounded_channel_push"> <code>unbounded_channel::push()</code></link> a
value.
</para>
<para>
<anchor id="wait_nchannel"/>We can address that problem with a counting
façade for the <code><phrase role="identifier">unbounded_channel</phrase><phrase
role="special">&lt;&gt;</phrase></code>. In fact, our façade need only
support the producer end of the channel.
</para>
<para>
<programlisting><phrase role="comment">// Introduce a channel facade that closes the channel once a specific number</phrase>
<phrase role="comment">// of items has been pushed. This allows an arbitrary consumer to read until</phrase>
<phrase role="comment">// 'closed' without itself having to count items.</phrase>
<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">nchannel</phrase> <phrase role="special">{</phrase>
<phrase role="keyword">public</phrase><phrase role="special">:</phrase>
<phrase role="identifier">nchannel</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">shared_ptr</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">unbounded_channel</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">T</phrase> <phrase role="special">&gt;</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">cp</phrase><phrase role="special">,</phrase>
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">lm</phrase><phrase role="special">):</phrase>
<phrase role="identifier">channel_</phrase><phrase role="special">(</phrase> <phrase role="identifier">cp</phrase><phrase role="special">),</phrase>
<phrase role="identifier">limit_</phrase><phrase role="special">(</phrase> <phrase role="identifier">lm</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
<phrase role="identifier">assert</phrase><phrase role="special">(</phrase><phrase role="identifier">channel_</phrase><phrase role="special">);</phrase>
<phrase role="keyword">if</phrase> <phrase role="special">(</phrase> <phrase role="number">0</phrase> <phrase role="special">==</phrase> <phrase role="identifier">limit_</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
<phrase role="identifier">channel_</phrase><phrase role="special">-&gt;</phrase><phrase role="identifier">close</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">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">channel_op_status</phrase> <phrase role="identifier">push</phrase><phrase role="special">(</phrase> <phrase role="identifier">T</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="identifier">va</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
<phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">channel_op_status</phrase> <phrase role="identifier">ok</phrase> <phrase role="special">=</phrase>
<phrase role="identifier">channel_</phrase><phrase role="special">-&gt;</phrase><phrase role="identifier">push</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">forward</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">T</phrase> <phrase role="special">&gt;(</phrase> <phrase role="identifier">va</phrase><phrase role="special">)</phrase> <phrase role="special">);</phrase>
<phrase role="keyword">if</phrase> <phrase role="special">(</phrase> <phrase role="identifier">ok</phrase> <phrase role="special">==</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">channel_op_status</phrase><phrase role="special">::</phrase><phrase role="identifier">success</phrase> <phrase role="special">&amp;&amp;</phrase>
<phrase role="special">--</phrase><phrase role="identifier">limit_</phrase> <phrase role="special">==</phrase> <phrase role="number">0</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
<phrase role="comment">// after the 'limit_'th successful push, close the channel</phrase>
<phrase role="identifier">channel_</phrase><phrase role="special">-&gt;</phrase><phrase role="identifier">close</phrase><phrase role="special">();</phrase>
<phrase role="special">}</phrase>
<phrase role="keyword">return</phrase> <phrase role="identifier">ok</phrase><phrase role="special">;</phrase>
<phrase role="special">}</phrase>
<phrase role="keyword">private</phrase><phrase role="special">:</phrase>
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">shared_ptr</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">unbounded_channel</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">T</phrase> <phrase role="special">&gt;</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">channel_</phrase><phrase role="special">;</phrase>
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">limit_</phrase><phrase role="special">;</phrase>
<phrase role="special">};</phrase>
</programlisting>
</para>
<para>
<anchor id="wait_all_values_source"/>Armed with <code><phrase role="identifier">nchannel</phrase><phrase
role="special">&lt;&gt;</phrase></code>, we can implement <code><phrase
role="identifier">wait_all_values_source</phrase><phrase role="special">()</phrase></code>.
It starts just like <link linkend="wait_first_value"><code><phrase role="identifier">wait_first_value</phrase><phrase
role="special">()</phrase></code></link>. The difference is that we wrap
the <code><phrase role="identifier">unbounded_channel</phrase><phrase role="special">&lt;</phrase><phrase
role="identifier">T</phrase><phrase role="special">&gt;</phrase></code>
with an <code><phrase role="identifier">nchannel</phrase><phrase role="special">&lt;</phrase><phrase
role="identifier">T</phrase><phrase role="special">&gt;</phrase></code>
to pass to the producer fibers.
</para>
<para>
Then, of course, instead of popping the first value, closing the channel
and returning it, we simply return the <code><phrase role="identifier">shared_ptr</phrase><phrase
role="special">&lt;</phrase><phrase role="identifier">unbounded_channel</phrase><phrase
role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase
role="special">&gt;&gt;</phrase></code>.
</para>
<para>
<programlisting><phrase role="comment">// Return a shared_ptr&lt;unbounded_channel&lt;T&gt;&gt; from which the caller can</phrase>
<phrase role="comment">// retrieve each new result as it arrives, until 'closed'.</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="special">...</phrase> <phrase role="identifier">Fns</phrase> <phrase role="special">&gt;</phrase>
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">shared_ptr</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">unbounded_channel</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">result_of</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Fn</phrase><phrase role="special">()</phrase> <phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase> <phrase role="special">&gt;</phrase> <phrase role="special">&gt;</phrase>
<phrase role="identifier">wait_all_values_source</phrase><phrase role="special">(</phrase> <phrase role="identifier">Fn</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="identifier">function</phrase><phrase role="special">,</phrase> <phrase role="identifier">Fns</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="special">...</phrase> <phrase role="identifier">functions</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">count</phrase><phrase role="special">(</phrase> <phrase role="number">1</phrase> <phrase role="special">+</phrase> <phrase role="keyword">sizeof</phrase> <phrase role="special">...</phrase> <phrase role="special">(</phrase> <phrase role="identifier">functions</phrase><phrase role="special">)</phrase> <phrase role="special">);</phrase>
<phrase role="keyword">typedef</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">result_of</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Fn</phrase><phrase role="special">()</phrase> <phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase> <phrase role="identifier">return_t</phrase><phrase role="special">;</phrase>
<phrase role="keyword">typedef</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">unbounded_channel</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">return_t</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">channel_t</phrase><phrase role="special">;</phrase>
<phrase role="comment">// make the channel</phrase>
<phrase role="keyword">auto</phrase> <phrase role="identifier">channelp</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">make_shared</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">channel_t</phrase> <phrase role="special">&gt;()</phrase> <phrase role="special">);</phrase>
<phrase role="comment">// and make an nchannel facade to close it after 'count' items</phrase>
<phrase role="keyword">auto</phrase> <phrase role="identifier">ncp</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">make_shared</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">nchannel</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">return_t</phrase> <phrase role="special">&gt;</phrase> <phrase role="special">&gt;(</phrase> <phrase role="identifier">channelp</phrase><phrase role="special">,</phrase> <phrase role="identifier">count</phrase><phrase role="special">)</phrase> <phrase role="special">);</phrase>
<phrase role="comment">// pass that nchannel facade to all the relevant fibers</phrase>
<phrase role="identifier">wait_all_values_impl</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">return_t</phrase> <phrase role="special">&gt;(</phrase> <phrase role="identifier">ncp</phrase><phrase role="special">,</phrase>
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">forward</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Fn</phrase> <phrase role="special">&gt;(</phrase> <phrase role="identifier">function</phrase><phrase role="special">),</phrase>
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">forward</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Fns</phrase> <phrase role="special">&gt;(</phrase> <phrase role="identifier">functions</phrase><phrase role="special">)</phrase> <phrase role="special">...</phrase> <phrase role="special">);</phrase>
<phrase role="comment">// then return the channel for consumer</phrase>
<phrase role="keyword">return</phrase> <phrase role="identifier">channelp</phrase><phrase role="special">;</phrase>
<phrase role="special">}</phrase>
</programlisting>
</para>
<para>
For example:
</para>
<para>
<programlisting><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">shared_ptr</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">unbounded_channel</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="special">&gt;</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">channel</phrase> <phrase role="special">=</phrase>
<phrase role="identifier">wait_all_values_source</phrase><phrase role="special">(</phrase>
<phrase role="special">[](){</phrase> <phrase role="keyword">return</phrase> <phrase role="identifier">sleeper</phrase><phrase role="special">(</phrase><phrase role="string">&quot;wavs_third&quot;</phrase><phrase role="special">,</phrase> <phrase role="number">150</phrase><phrase role="special">);</phrase> <phrase role="special">},</phrase>
<phrase role="special">[](){</phrase> <phrase role="keyword">return</phrase> <phrase role="identifier">sleeper</phrase><phrase role="special">(</phrase><phrase role="string">&quot;wavs_second&quot;</phrase><phrase role="special">,</phrase> <phrase role="number">100</phrase><phrase role="special">);</phrase> <phrase role="special">},</phrase>
<phrase role="special">[](){</phrase> <phrase role="keyword">return</phrase> <phrase role="identifier">sleeper</phrase><phrase role="special">(</phrase><phrase role="string">&quot;wavs_first&quot;</phrase><phrase role="special">,</phrase> <phrase role="number">50</phrase><phrase role="special">);</phrase> <phrase role="special">});</phrase>
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="identifier">value</phrase><phrase role="special">;</phrase>
<phrase role="keyword">while</phrase> <phrase role="special">(</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">channel_op_status</phrase><phrase role="special">::</phrase><phrase role="identifier">success</phrase> <phrase role="special">==</phrase> <phrase role="identifier">channel</phrase><phrase role="special">-&gt;</phrase><phrase role="identifier">pop</phrase><phrase role="special">(</phrase><phrase role="identifier">value</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;wait_all_values_source() =&gt; '&quot;</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="identifier">value</phrase>
<phrase role="special">&lt;&lt;</phrase> <phrase role="string">&quot;'&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>
</programlisting>
</para>
<para>
<anchor id="wait_all_values_impl"/><code><phrase role="identifier">wait_all_values_impl</phrase><phrase
role="special">()</phrase></code> really is just like <link linkend="wait_first_value_impl"><code><phrase
role="identifier">wait_first_value_impl</phrase><phrase role="special">()</phrase></code></link>
except for the use of <code><phrase role="identifier">nchannel</phrase><phrase
role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase
role="special">&gt;</phrase></code> rather than <code><phrase role="identifier">bounded_channel</phrase><phrase
role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase
role="special">&gt;</phrase></code>:
</para>
<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">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Fn</phrase> <phrase role="special">&gt;</phrase>
<phrase role="keyword">void</phrase> <phrase role="identifier">wait_all_values_impl</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">shared_ptr</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">nchannel</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">T</phrase> <phrase role="special">&gt;</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">channel</phrase><phrase role="special">,</phrase>
<phrase role="identifier">Fn</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="identifier">function</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
<phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">fiber</phrase><phrase role="special">(</phrase> <phrase role="special">[</phrase><phrase role="identifier">channel</phrase><phrase role="special">,</phrase> <phrase role="identifier">function</phrase><phrase role="special">](){</phrase>
<phrase role="identifier">channel</phrase><phrase role="special">-&gt;</phrase><phrase role="identifier">push</phrase><phrase role="special">(</phrase><phrase role="identifier">function</phrase><phrase role="special">());</phrase>
<phrase role="special">}).</phrase><phrase role="identifier">detach</phrase><phrase role="special">();</phrase>
<phrase role="special">}</phrase>
</programlisting>
</para>
</section>
<section id="fiber.when_any.when_all_functionality.when_all_until_first_exception">
<title><link linkend="fiber.when_any.when_all_functionality.when_all_until_first_exception">when_all
until first exception</link></title>
<para>
Naturally, just as with <link linkend="wait_first_outcome"><code><phrase
role="identifier">wait_first_outcome</phrase><phrase role="special">()</phrase></code></link>,
we can elaborate <link linkend="wait_all_values"><code><phrase role="identifier">wait_all_values</phrase><phrase
role="special">()</phrase></code></link> and <link linkend="wait_all_values_source"><code><phrase
role="identifier">wait_all_values_source</phrase><phrase role="special">()</phrase></code></link>
by passing <code><phrase role="identifier">future</phrase><phrase role="special">&lt;</phrase>
<phrase role="identifier">T</phrase> <phrase role="special">&gt;</phrase></code>
instead of plain <code><phrase role="identifier">T</phrase></code>.
</para>
<para>
<anchor id="wait_all_until_error"/><code><phrase role="identifier">wait_all_until_error</phrase><phrase
role="special">()</phrase></code> pops that <code><phrase role="identifier">future</phrase><phrase
role="special">&lt;</phrase> <phrase role="identifier">T</phrase> <phrase
role="special">&gt;</phrase></code> and calls its <link linkend="future_get"> <code>future::get()</code></link>:
</para>
<para>
<programlisting><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="special">...</phrase> <phrase role="identifier">Fns</phrase> <phrase role="special">&gt;</phrase>
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">vector</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">result_of</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Fn</phrase><phrase role="special">()</phrase> <phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase> <phrase role="special">&gt;</phrase>
<phrase role="identifier">wait_all_until_error</phrase><phrase role="special">(</phrase> <phrase role="identifier">Fn</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="identifier">function</phrase><phrase role="special">,</phrase> <phrase role="identifier">Fns</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="special">...</phrase> <phrase role="identifier">functions</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">count</phrase><phrase role="special">(</phrase> <phrase role="number">1</phrase> <phrase role="special">+</phrase> <phrase role="keyword">sizeof</phrase> <phrase role="special">...</phrase> <phrase role="special">(</phrase> <phrase role="identifier">functions</phrase><phrase role="special">)</phrase> <phrase role="special">);</phrase>
<phrase role="keyword">typedef</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">result_of</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Fn</phrase><phrase role="special">()</phrase> <phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase> <phrase role="identifier">return_t</phrase><phrase role="special">;</phrase>
<phrase role="keyword">typedef</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">future</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">return_t</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">future_t</phrase><phrase role="special">;</phrase>
<phrase role="keyword">typedef</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">vector</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">return_t</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">vector_t</phrase><phrase role="special">;</phrase>
<phrase role="identifier">vector_t</phrase> <phrase role="identifier">results</phrase><phrase role="special">;</phrase>
<phrase role="identifier">results</phrase><phrase role="special">.</phrase><phrase role="identifier">reserve</phrase><phrase role="special">(</phrase> <phrase role="identifier">count</phrase><phrase role="special">);</phrase>
<phrase role="comment">// get channel</phrase>
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">shared_ptr</phrase><phrase role="special">&lt;</phrase>
<phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">unbounded_channel</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">future_t</phrase> <phrase role="special">&gt;</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">channel</phrase><phrase role="special">(</phrase>
<phrase role="identifier">wait_all_until_error_source</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">forward</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Fn</phrase> <phrase role="special">&gt;(</phrase> <phrase role="identifier">function</phrase><phrase role="special">),</phrase>
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">forward</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Fns</phrase> <phrase role="special">&gt;(</phrase> <phrase role="identifier">functions</phrase><phrase role="special">)</phrase> <phrase role="special">...</phrase> <phrase role="special">)</phrase> <phrase role="special">);</phrase>
<phrase role="comment">// fill results vector</phrase>
<phrase role="identifier">future_t</phrase> <phrase role="identifier">future</phrase><phrase role="special">;</phrase>
<phrase role="keyword">while</phrase> <phrase role="special">(</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">channel_op_status</phrase><phrase role="special">::</phrase><phrase role="identifier">success</phrase> <phrase role="special">==</phrase> <phrase role="identifier">channel</phrase><phrase role="special">-&gt;</phrase><phrase role="identifier">pop</phrase><phrase role="special">(</phrase> <phrase role="identifier">future</phrase><phrase role="special">)</phrase> <phrase role="special">)</phrase> <phrase role="special">{</phrase>
<phrase role="identifier">results</phrase><phrase role="special">.</phrase><phrase role="identifier">push_back</phrase><phrase role="special">(</phrase> <phrase role="identifier">future</phrase><phrase role="special">.</phrase><phrase role="identifier">get</phrase><phrase role="special">()</phrase> <phrase role="special">);</phrase>
<phrase role="special">}</phrase>
<phrase role="comment">// return vector to caller</phrase>
<phrase role="keyword">return</phrase> <phrase role="identifier">results</phrase><phrase role="special">;</phrase>
<phrase role="special">}</phrase>
</programlisting>
</para>
<para>
For example:
</para>
<para>
<programlisting><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="identifier">thrown</phrase><phrase role="special">;</phrase>
<phrase role="keyword">try</phrase> <phrase role="special">{</phrase>
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">vector</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">values</phrase> <phrase role="special">=</phrase> <phrase role="identifier">wait_all_until_error</phrase><phrase role="special">(</phrase>
<phrase role="special">[](){</phrase> <phrase role="keyword">return</phrase> <phrase role="identifier">sleeper</phrase><phrase role="special">(</phrase><phrase role="string">&quot;waue_late&quot;</phrase><phrase role="special">,</phrase> <phrase role="number">150</phrase><phrase role="special">);</phrase> <phrase role="special">},</phrase>
<phrase role="special">[](){</phrase> <phrase role="keyword">return</phrase> <phrase role="identifier">sleeper</phrase><phrase role="special">(</phrase><phrase role="string">&quot;waue_middle&quot;</phrase><phrase role="special">,</phrase> <phrase role="number">100</phrase><phrase role="special">,</phrase> <phrase role="keyword">true</phrase><phrase role="special">);</phrase> <phrase role="special">},</phrase>
<phrase role="special">[](){</phrase> <phrase role="keyword">return</phrase> <phrase role="identifier">sleeper</phrase><phrase role="special">(</phrase><phrase role="string">&quot;waue_early&quot;</phrase><phrase role="special">,</phrase> <phrase role="number">50</phrase><phrase role="special">);</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">thrown</phrase> <phrase role="special">=</phrase> <phrase role="identifier">e</phrase><phrase role="special">.</phrase><phrase role="identifier">what</phrase><phrase role="special">();</phrase>
<phrase role="special">}</phrase>
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cout</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="string">&quot;wait_all_until_error(fail) threw '&quot;</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="identifier">thrown</phrase>
<phrase role="special">&lt;&lt;</phrase> <phrase role="string">&quot;'&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>
</programlisting>
</para>
<para>
<anchor id="wait_all_until_error_source"/>Naturally this complicates the
API for <code><phrase role="identifier">wait_all_until_error_source</phrase><phrase
role="special">()</phrase></code>. The caller must both retrieve a <code><phrase
role="identifier">future</phrase><phrase role="special">&lt;</phrase>
<phrase role="identifier">T</phrase> <phrase role="special">&gt;</phrase></code>
and call its <code><phrase role="identifier">get</phrase><phrase role="special">()</phrase></code>
method. It would, of course, be possible to return a façade over the consumer
end of the channel that would implicitly perform the <code><phrase role="identifier">get</phrase><phrase
role="special">()</phrase></code> and return a simple <code><phrase role="identifier">T</phrase></code>
(or throw).
</para>
<para>
The implementation is just as you would expect.
</para>
<para>
<programlisting><phrase role="comment">// Return a shared_ptr&lt;unbounded_channel&lt;future&lt;T&gt;&gt;&gt; from which the caller can</phrase>
<phrase role="comment">// get() each new result as it arrives, until 'closed'.</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="special">...</phrase> <phrase role="identifier">Fns</phrase> <phrase role="special">&gt;</phrase>
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">shared_ptr</phrase><phrase role="special">&lt;</phrase>
<phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">unbounded_channel</phrase><phrase role="special">&lt;</phrase>
<phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">future</phrase><phrase role="special">&lt;</phrase>
<phrase role="keyword">typename</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">result_of</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Fn</phrase><phrase role="special">()</phrase> <phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase> <phrase role="special">&gt;</phrase> <phrase role="special">&gt;</phrase> <phrase role="special">&gt;</phrase>
<phrase role="identifier">wait_all_until_error_source</phrase><phrase role="special">(</phrase> <phrase role="identifier">Fn</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="identifier">function</phrase><phrase role="special">,</phrase> <phrase role="identifier">Fns</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="special">...</phrase> <phrase role="identifier">functions</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">count</phrase><phrase role="special">(</phrase> <phrase role="number">1</phrase> <phrase role="special">+</phrase> <phrase role="keyword">sizeof</phrase> <phrase role="special">...</phrase> <phrase role="special">(</phrase> <phrase role="identifier">functions</phrase><phrase role="special">)</phrase> <phrase role="special">);</phrase>
<phrase role="keyword">typedef</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">result_of</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Fn</phrase><phrase role="special">()</phrase> <phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase> <phrase role="identifier">return_t</phrase><phrase role="special">;</phrase>
<phrase role="keyword">typedef</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">future</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">return_t</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">future_t</phrase><phrase role="special">;</phrase>
<phrase role="keyword">typedef</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">unbounded_channel</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">future_t</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">channel_t</phrase><phrase role="special">;</phrase>
<phrase role="comment">// make the channel</phrase>
<phrase role="keyword">auto</phrase> <phrase role="identifier">channelp</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">make_shared</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">channel_t</phrase> <phrase role="special">&gt;()</phrase> <phrase role="special">);</phrase>
<phrase role="comment">// and make an nchannel facade to close it after 'count' items</phrase>
<phrase role="keyword">auto</phrase> <phrase role="identifier">ncp</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">make_shared</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">nchannel</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">future_t</phrase> <phrase role="special">&gt;</phrase> <phrase role="special">&gt;(</phrase> <phrase role="identifier">channelp</phrase><phrase role="special">,</phrase> <phrase role="identifier">count</phrase><phrase role="special">)</phrase> <phrase role="special">);</phrase>
<phrase role="comment">// pass that nchannel facade to all the relevant fibers</phrase>
<phrase role="identifier">wait_all_until_error_impl</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">return_t</phrase> <phrase role="special">&gt;(</phrase> <phrase role="identifier">ncp</phrase><phrase role="special">,</phrase>
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">forward</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Fn</phrase> <phrase role="special">&gt;(</phrase> <phrase role="identifier">function</phrase><phrase role="special">),</phrase>
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">forward</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Fns</phrase> <phrase role="special">&gt;(</phrase> <phrase role="identifier">functions</phrase><phrase role="special">)</phrase> <phrase role="special">...</phrase> <phrase role="special">);</phrase>
<phrase role="comment">// then return the channel for consumer</phrase>
<phrase role="keyword">return</phrase> <phrase role="identifier">channelp</phrase><phrase role="special">;</phrase>
<phrase role="special">}</phrase>
</programlisting>
</para>
<para>
For example:
</para>
<para>
<programlisting><phrase role="keyword">typedef</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">future</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">future_t</phrase><phrase role="special">;</phrase>
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">shared_ptr</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">unbounded_channel</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">future_t</phrase> <phrase role="special">&gt;</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">channel</phrase> <phrase role="special">=</phrase>
<phrase role="identifier">wait_all_until_error_source</phrase><phrase role="special">(</phrase>
<phrase role="special">[](){</phrase> <phrase role="keyword">return</phrase> <phrase role="identifier">sleeper</phrase><phrase role="special">(</phrase><phrase role="string">&quot;wauess_third&quot;</phrase><phrase role="special">,</phrase> <phrase role="number">150</phrase><phrase role="special">);</phrase> <phrase role="special">},</phrase>
<phrase role="special">[](){</phrase> <phrase role="keyword">return</phrase> <phrase role="identifier">sleeper</phrase><phrase role="special">(</phrase><phrase role="string">&quot;wauess_second&quot;</phrase><phrase role="special">,</phrase> <phrase role="number">100</phrase><phrase role="special">);</phrase> <phrase role="special">},</phrase>
<phrase role="special">[](){</phrase> <phrase role="keyword">return</phrase> <phrase role="identifier">sleeper</phrase><phrase role="special">(</phrase><phrase role="string">&quot;wauess_first&quot;</phrase><phrase role="special">,</phrase> <phrase role="number">50</phrase><phrase role="special">);</phrase> <phrase role="special">});</phrase>
<phrase role="identifier">future_t</phrase> <phrase role="identifier">future</phrase><phrase role="special">;</phrase>
<phrase role="keyword">while</phrase> <phrase role="special">(</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">channel_op_status</phrase><phrase role="special">::</phrase><phrase role="identifier">success</phrase> <phrase role="special">==</phrase> <phrase role="identifier">channel</phrase><phrase role="special">-&gt;</phrase><phrase role="identifier">pop</phrase><phrase role="special">(</phrase> <phrase role="identifier">future</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">string</phrase> <phrase role="identifier">value</phrase><phrase role="special">(</phrase> <phrase role="identifier">future</phrase><phrase role="special">.</phrase><phrase role="identifier">get</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;wait_all_until_error_source(success) =&gt; '&quot;</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="identifier">value</phrase>
<phrase role="special">&lt;&lt;</phrase> <phrase role="string">&quot;'&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>
</programlisting>
</para>
<para>
<anchor id="wait_all_until_error_impl"/><code><phrase role="identifier">wait_all_until_error_impl</phrase><phrase
role="special">()</phrase></code> is just like <link linkend="wait_first_outcome_impl"><code><phrase
role="identifier">wait_first_outcome_impl</phrase><phrase role="special">()</phrase></code></link>,
but using <link linkend="wait_nchannel"><code><phrase role="identifier">nchannel</phrase><phrase
role="special">&lt;&gt;</phrase></code></link> instead of <code><phrase
role="identifier">bounded_channel</phrase><phrase role="special">&lt;&gt;</phrase></code>.
</para>
<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">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Fn</phrase> <phrase role="special">&gt;</phrase>
<phrase role="keyword">void</phrase> <phrase role="identifier">wait_all_until_error_impl</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">shared_ptr</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">nchannel</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">future</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">T</phrase> <phrase role="special">&gt;</phrase> <phrase role="special">&gt;</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">channel</phrase><phrase role="special">,</phrase>
<phrase role="identifier">Fn</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="identifier">function</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
<phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">fiber</phrase><phrase role="special">(</phrase> <phrase role="special">[</phrase><phrase role="identifier">channel</phrase><phrase role="special">,</phrase> <phrase role="identifier">function</phrase><phrase role="special">](){</phrase>
<phrase role="comment">// Instantiate a packaged_task to capture any exception thrown by</phrase>
<phrase role="comment">// function.</phrase>
<phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">packaged_task</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">T</phrase><phrase role="special">()</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">task</phrase><phrase role="special">(</phrase> <phrase role="identifier">function</phrase><phrase role="special">);</phrase>
<phrase role="comment">// Immediately run this packaged_task on same fiber. We want</phrase>
<phrase role="comment">// function() to have completed BEFORE we push the future.</phrase>
<phrase role="identifier">task</phrase><phrase role="special">();</phrase>
<phrase role="comment">// Pass the corresponding future to consumer.</phrase>
<phrase role="identifier">channel</phrase><phrase role="special">-&gt;</phrase><phrase role="identifier">push</phrase><phrase role="special">(</phrase> <phrase role="identifier">task</phrase><phrase role="special">.</phrase><phrase role="identifier">get_future</phrase><phrase role="special">()</phrase> <phrase role="special">);</phrase>
<phrase role="special">}).</phrase><phrase role="identifier">detach</phrase><phrase role="special">();</phrase>
<phrase role="special">}</phrase>
</programlisting>
</para>
</section>
<section id="fiber.when_any.when_all_functionality.wait_all__collecting_all_exceptions">
<title><link linkend="fiber.when_any.when_all_functionality.wait_all__collecting_all_exceptions">wait_all,
collecting all exceptions</link></title>
<para>
<anchor id="wait_all_collect_errors"/>Given <link linkend="wait_all_until_error_source"><code><phrase
role="identifier">wait_all_until_error_source</phrase><phrase role="special">()</phrase></code></link>,
it might be more reasonable to make a <code><phrase role="identifier">wait_all_</phrase><phrase
role="special">...()</phrase></code> that collects <emphasis>all</emphasis>
errors instead of presenting only the first:
</para>
<para>
<programlisting><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="special">...</phrase> <phrase role="identifier">Fns</phrase> <phrase role="special">&gt;</phrase>
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">vector</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">result_of</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Fn</phrase><phrase role="special">()</phrase> <phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase> <phrase role="special">&gt;</phrase>
<phrase role="identifier">wait_all_collect_errors</phrase><phrase role="special">(</phrase> <phrase role="identifier">Fn</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="identifier">function</phrase><phrase role="special">,</phrase> <phrase role="identifier">Fns</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="special">...</phrase> <phrase role="identifier">functions</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">count</phrase><phrase role="special">(</phrase> <phrase role="number">1</phrase> <phrase role="special">+</phrase> <phrase role="keyword">sizeof</phrase> <phrase role="special">...</phrase> <phrase role="special">(</phrase> <phrase role="identifier">functions</phrase><phrase role="special">)</phrase> <phrase role="special">);</phrase>
<phrase role="keyword">typedef</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">result_of</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Fn</phrase><phrase role="special">()</phrase> <phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase> <phrase role="identifier">return_t</phrase><phrase role="special">;</phrase>
<phrase role="keyword">typedef</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">future</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">return_t</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">future_t</phrase><phrase role="special">;</phrase>
<phrase role="keyword">typedef</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">vector</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">return_t</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">vector_t</phrase><phrase role="special">;</phrase>
<phrase role="identifier">vector_t</phrase> <phrase role="identifier">results</phrase><phrase role="special">;</phrase>
<phrase role="identifier">results</phrase><phrase role="special">.</phrase><phrase role="identifier">reserve</phrase><phrase role="special">(</phrase> <phrase role="identifier">count</phrase><phrase role="special">);</phrase>
<phrase role="identifier">exception_list</phrase> <phrase role="identifier">exceptions</phrase><phrase role="special">(</phrase><phrase role="string">&quot;wait_all_collect_errors() exceptions&quot;</phrase><phrase role="special">);</phrase>
<phrase role="comment">// get channel</phrase>
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">shared_ptr</phrase><phrase role="special">&lt;</phrase>
<phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">unbounded_channel</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">future_t</phrase> <phrase role="special">&gt;</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">channel</phrase><phrase role="special">(</phrase>
<phrase role="identifier">wait_all_until_error_source</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">forward</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Fn</phrase> <phrase role="special">&gt;(</phrase> <phrase role="identifier">function</phrase><phrase role="special">),</phrase>
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">forward</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Fns</phrase> <phrase role="special">&gt;(</phrase> <phrase role="identifier">functions</phrase><phrase role="special">)</phrase> <phrase role="special">...</phrase> <phrase role="special">)</phrase> <phrase role="special">);</phrase>
<phrase role="comment">// fill results and/or exceptions vectors</phrase>
<phrase role="identifier">future_t</phrase> <phrase role="identifier">future</phrase><phrase role="special">;</phrase>
<phrase role="keyword">while</phrase> <phrase role="special">(</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">channel_op_status</phrase><phrase role="special">::</phrase><phrase role="identifier">success</phrase> <phrase role="special">==</phrase> <phrase role="identifier">channel</phrase><phrase role="special">-&gt;</phrase><phrase role="identifier">pop</phrase><phrase role="special">(</phrase> <phrase role="identifier">future</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">exception_ptr</phrase> <phrase role="identifier">exp</phrase> <phrase role="special">=</phrase> <phrase role="identifier">future</phrase><phrase role="special">.</phrase><phrase role="identifier">get_exception_ptr</phrase><phrase role="special">();</phrase>
<phrase role="keyword">if</phrase> <phrase role="special">(</phrase> <phrase role="special">!</phrase> <phrase role="identifier">exp</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
<phrase role="identifier">results</phrase><phrase role="special">.</phrase><phrase role="identifier">push_back</phrase><phrase role="special">(</phrase> <phrase role="identifier">future</phrase><phrase role="special">.</phrase><phrase role="identifier">get</phrase><phrase role="special">()</phrase> <phrase role="special">);</phrase>
<phrase role="special">}</phrase> <phrase role="keyword">else</phrase> <phrase role="special">{</phrase>
<phrase role="identifier">exceptions</phrase><phrase role="special">.</phrase><phrase role="identifier">add</phrase><phrase role="special">(</phrase> <phrase role="identifier">exp</phrase><phrase role="special">);</phrase>
<phrase role="special">}</phrase>
<phrase role="special">}</phrase>
<phrase role="comment">// if there were any exceptions, throw</phrase>
<phrase role="keyword">if</phrase> <phrase role="special">(</phrase> <phrase role="identifier">exceptions</phrase><phrase role="special">.</phrase><phrase role="identifier">size</phrase><phrase role="special">()</phrase> <phrase role="special">)</phrase> <phrase role="special">{</phrase>
<phrase role="keyword">throw</phrase> <phrase role="identifier">exceptions</phrase><phrase role="special">;</phrase>
<phrase role="special">}</phrase>
<phrase role="comment">// no exceptions: return vector to caller</phrase>
<phrase role="keyword">return</phrase> <phrase role="identifier">results</phrase><phrase role="special">;</phrase>
<phrase role="special">}</phrase>
</programlisting>
</para>
<para>
The implementation is a simple variation on <link linkend="wait_first_success"><code><phrase
role="identifier">wait_first_success</phrase><phrase role="special">()</phrase></code></link>,
using the same <link linkend="exception_list"><code><phrase role="identifier">exception_list</phrase></code></link>
exception class.
</para>
</section>
<section id="fiber.when_any.when_all_functionality.when_all__heterogeneous_types">
<title><link linkend="fiber.when_any.when_all_functionality.when_all__heterogeneous_types">when_all,
heterogeneous types</link></title>
<para>
But what about the case when we must wait for all results of different
types?
</para>
<para>
We can present an API that is frankly quite cool. Consider a sample struct:
</para>
<para>
<programlisting><phrase role="keyword">struct</phrase> <phrase role="identifier">Data</phrase> <phrase role="special">{</phrase>
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="identifier">str</phrase><phrase role="special">;</phrase>
<phrase role="keyword">double</phrase> <phrase role="identifier">inexact</phrase><phrase role="special">;</phrase>
<phrase role="keyword">int</phrase> <phrase role="identifier">exact</phrase><phrase role="special">;</phrase>
<phrase role="keyword">friend</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">ostream</phrase><phrase role="special">&amp;</phrase> <phrase role="keyword">operator</phrase><phrase role="special">&lt;&lt;(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">ostream</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">out</phrase><phrase role="special">,</phrase> <phrase role="identifier">Data</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">data</phrase><phrase role="special">)</phrase>
<phrase role="special">...</phrase>
<phrase role="special">};</phrase>
</programlisting>
</para>
<para>
Let's fill its members from task functions all running concurrently:
</para>
<para>
<programlisting><phrase role="identifier">Data</phrase> <phrase role="identifier">data</phrase> <phrase role="special">=</phrase> <phrase role="identifier">wait_all_members</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Data</phrase> <phrase role="special">&gt;(</phrase>
<phrase role="special">[](){</phrase> <phrase role="keyword">return</phrase> <phrase role="identifier">sleeper</phrase><phrase role="special">(</phrase><phrase role="string">&quot;wams_left&quot;</phrase><phrase role="special">,</phrase> <phrase role="number">100</phrase><phrase role="special">);</phrase> <phrase role="special">},</phrase>
<phrase role="special">[](){</phrase> <phrase role="keyword">return</phrase> <phrase role="identifier">sleeper</phrase><phrase role="special">(</phrase><phrase role="number">3.14</phrase><phrase role="special">,</phrase> <phrase role="number">150</phrase><phrase role="special">);</phrase> <phrase role="special">},</phrase>
<phrase role="special">[](){</phrase> <phrase role="keyword">return</phrase> <phrase role="identifier">sleeper</phrase><phrase role="special">(</phrase><phrase role="number">17</phrase><phrase role="special">,</phrase> <phrase role="number">50</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;wait_all_members&lt;Data&gt;(success) =&gt; &quot;</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="identifier">data</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>
</programlisting>
</para>
<para>
Note that for this case, we abandon the notion of capturing the earliest
result first, and so on: we must fill exactly the passed struct in left-to-right
order.
</para>
<para>
That permits a beautifully simple implementation:
</para>
<para>
<programlisting><phrase role="comment">// Explicitly pass Result. This can be any type capable of being initialized</phrase>
<phrase role="comment">// from the results of the passed functions, such as a struct.</phrase>
<phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Result</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="special">...</phrase> <phrase role="identifier">Fns</phrase> <phrase role="special">&gt;</phrase>
<phrase role="identifier">Result</phrase> <phrase role="identifier">wait_all_members</phrase><phrase role="special">(</phrase> <phrase role="identifier">Fns</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="special">...</phrase> <phrase role="identifier">functions</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
<phrase role="comment">// Run each of the passed functions on a separate fiber, passing all their</phrase>
<phrase role="comment">// futures to helper function for processing.</phrase>
<phrase role="keyword">return</phrase> <phrase role="identifier">wait_all_members_get</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Result</phrase> <phrase role="special">&gt;(</phrase>
<phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">async</phrase><phrase role="special">(</phrase> <phrase role="identifier">functions</phrase><phrase role="special">)</phrase> <phrase role="special">...</phrase> <phrase role="special">);</phrase>
<phrase role="special">}</phrase>
</programlisting>
</para>
<para>
<programlisting><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Result</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="special">...</phrase> <phrase role="identifier">Futures</phrase> <phrase role="special">&gt;</phrase>
<phrase role="identifier">Result</phrase> <phrase role="identifier">wait_all_members_get</phrase><phrase role="special">(</phrase> <phrase role="identifier">Futures</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="special">...</phrase> <phrase role="identifier">futures</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
<phrase role="comment">// Fetch the results from the passed futures into Result's initializer</phrase>
<phrase role="comment">// list. It's true that the get() calls here will block the implicit</phrase>
<phrase role="comment">// iteration over futures -- but that doesn't matter because we won't be</phrase>
<phrase role="comment">// done until the slowest of them finishes anyway. As results are</phrase>
<phrase role="comment">// processed in argument-list order rather than order of completion, the</phrase>
<phrase role="comment">// leftmost get() to throw an exception will cause that exception to</phrase>
<phrase role="comment">// propagate to the caller.</phrase>
<phrase role="keyword">return</phrase> <phrase role="identifier">Result</phrase><phrase role="special">{</phrase> <phrase role="identifier">futures</phrase><phrase role="special">.</phrase><phrase role="identifier">get</phrase><phrase role="special">()</phrase> <phrase role="special">...</phrase> <phrase role="special">};</phrase>
<phrase role="special">}</phrase>
</programlisting>
</para>
<para>
It is tempting to try to implement <code><phrase role="identifier">wait_all_members</phrase><phrase
role="special">()</phrase></code> as a one-liner like this:
</para>
<programlisting><phrase role="keyword">return</phrase> <phrase role="identifier">Result</phrase><phrase role="special">{</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">async</phrase><phrase role="special">(</phrase><phrase role="identifier">functions</phrase><phrase role="special">).</phrase><phrase role="identifier">get</phrase><phrase role="special">()...</phrase> <phrase role="special">};</phrase>
</programlisting>
<para>
The trouble with this tactic is that it would serialize all the task functions.
The runtime makes a single pass through <code><phrase role="identifier">functions</phrase></code>,
calling <link linkend="fibers_async"> <code>fibers::async()</code></link> for each and then immediately calling
<link linkend="future_get"> <code>future::get()</code></link> on its returned <code><phrase role="identifier">future</phrase><phrase
role="special">&lt;&gt;</phrase></code>. That blocks the implicit loop.
The above is almost equivalent to writing:
</para>
<programlisting><phrase role="keyword">return</phrase> <phrase role="identifier">Result</phrase><phrase role="special">{</phrase> <phrase role="identifier">functions</phrase><phrase role="special">()...</phrase> <phrase role="special">};</phrase>
</programlisting>
<para>
in which, of course, there is no concurrency at all.
</para>
<para>
Passing the argument pack through a function-call boundary (<code><phrase
role="identifier">wait_all_members_get</phrase><phrase role="special">()</phrase></code>)
forces the runtime to make <emphasis>two</emphasis> passes: one in <code><phrase
role="identifier">wait_all_members</phrase><phrase role="special">()</phrase></code>
to collect the <code><phrase role="identifier">future</phrase><phrase role="special">&lt;&gt;</phrase></code>s
from all the <code><phrase role="identifier">async</phrase><phrase role="special">()</phrase></code>
calls, the second in <code><phrase role="identifier">wait_all_members_get</phrase><phrase
role="special">()</phrase></code> to fetch each of the results.
</para>
<para>
As noted in comments, within the <code><phrase role="identifier">wait_all_members_get</phrase><phrase
role="special">()</phrase></code> parameter pack expansion pass, the blocking
behavior of <code><phrase role="identifier">get</phrase><phrase role="special">()</phrase></code>
becomes irrelevant. Along the way, we will hit the <code><phrase role="identifier">get</phrase><phrase
role="special">()</phrase></code> for the slowest task function; after
that every subsequent <code><phrase role="identifier">get</phrase><phrase
role="special">()</phrase></code> will complete in trivial time.
</para>
<para>
By the way, we could also use this same API to fill a vector or other collection:
</para>
<para>
<programlisting><phrase role="comment">// If we don't care about obtaining results as soon as they arrive, and we</phrase>
<phrase role="comment">// prefer a result vector in passed argument order rather than completion</phrase>
<phrase role="comment">// order, wait_all_members() is another possible implementation of</phrase>
<phrase role="comment">// wait_all_until_error().</phrase>
<phrase role="keyword">auto</phrase> <phrase role="identifier">strings</phrase> <phrase role="special">=</phrase> <phrase role="identifier">wait_all_members</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">vector</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="special">&gt;</phrase> <phrase role="special">&gt;(</phrase>
<phrase role="special">[](){</phrase> <phrase role="keyword">return</phrase> <phrase role="identifier">sleeper</phrase><phrase role="special">(</phrase><phrase role="string">&quot;wamv_left&quot;</phrase><phrase role="special">,</phrase> <phrase role="number">150</phrase><phrase role="special">);</phrase> <phrase role="special">},</phrase>
<phrase role="special">[](){</phrase> <phrase role="keyword">return</phrase> <phrase role="identifier">sleeper</phrase><phrase role="special">(</phrase><phrase role="string">&quot;wamv_middle&quot;</phrase><phrase role="special">,</phrase> <phrase role="number">100</phrase><phrase role="special">);</phrase> <phrase role="special">},</phrase>
<phrase role="special">[](){</phrase> <phrase role="keyword">return</phrase> <phrase role="identifier">sleeper</phrase><phrase role="special">(</phrase><phrase role="string">&quot;wamv_right&quot;</phrase><phrase role="special">,</phrase> <phrase role="number">50</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;wait_all_members&lt;vector&gt;() =&gt;&quot;</phrase><phrase role="special">;</phrase>
<phrase role="keyword">for</phrase> <phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">str</phrase> <phrase role="special">:</phrase> <phrase role="identifier">strings</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; '&quot;</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="identifier">str</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="string">&quot;'&quot;</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">std</phrase><phrase role="special">::</phrase><phrase role="identifier">endl</phrase><phrase role="special">;</phrase>
</programlisting>
</para>
</section>
</section>
</section>
<section id="fiber.integration">
<title><anchor id="integration"/><link linkend="fiber.integration">Sharing a
Thread with Another Main Loop</link></title>
<bridgehead renderas="sect3" id="fiber.integration.h0">
<phrase id="fiber.integration.overview"/><link linkend="fiber.integration.overview">Overview</link>
</bridgehead>
<para>
As always with cooperative concurrency, it is important not to let any one
fiber monopolize the processor too long: that could &quot;starve&quot; other
ready fibers. This section discusses a couple of solutions.
</para>
<bridgehead renderas="sect3" id="fiber.integration.h1">
<phrase id="fiber.integration.event_driven_program"/><link linkend="fiber.integration.event_driven_program">Event-Driven
Program</link>
</bridgehead>
<para>
Consider a classic event-driven program, organized around a main loop that
fetches and dispatches incoming I/O events. You are introducing <emphasis role="bold">Boost.Fiber</emphasis>
because certain asynchronous I/O sequences are logically sequential, and for
those you want to write and maintain code that looks and acts sequential.
</para>
<para>
You are launching fibers on the application's main thread because certain of
their actions will affect its user interface, and the application's UI framework
permits UI operations only on the main thread. Or perhaps those fibers need
access to main-thread data, and it would be too expensive in runtime (or development
time) to robustly defend every such data item with thread synchronization primitives.
</para>
<para>
You must ensure that the application's main loop <emphasis>itself</emphasis>
doesn't monopolize the processor: that the fibers it launches will get the
CPU cycles they need.
</para>
<para>
The solution is the same as for any fiber that might claim the CPU for an extended
time: introduce calls to <link linkend="this_fiber_yield"> <code>this_fiber::yield()</code></link>. The most straightforward
approach is to call <code><phrase role="identifier">yield</phrase><phrase role="special">()</phrase></code>
on every iteration of your existing main loop. In effect, this unifies the
application's main loop with <emphasis role="bold">Boost.Fiber</emphasis>'s
internal main loop. <code><phrase role="identifier">yield</phrase><phrase role="special">()</phrase></code>
allows the fiber manager to run any fibers that have become ready since the
previous iteration of the application's main loop. When these fibers have had
a turn, control passes to the thread's main fiber, which returns from <code><phrase
role="identifier">yield</phrase><phrase role="special">()</phrase></code> and
resumes the application's main loop.
</para>
<bridgehead renderas="sect3" id="fiber.integration.h2">
<phrase id="fiber.integration.integrating_with__ulink_url__http___www_boost_org_doc_libs_release_libs_asio_index_html__boost_asio__ulink_"/><link
linkend="fiber.integration.integrating_with__ulink_url__http___www_boost_org_doc_libs_release_libs_asio_index_html__boost_asio__ulink_">Integrating
with <ulink url="http://www.boost.org/doc/libs/release/libs/asio/index.html">Boost.Asio</ulink></link>
</bridgehead>
<para>
More challenging is when the application's main loop is embedded in some other
library or framework. Such an application will typically, after performing
all necessary setup, pass control to some form of <code><phrase role="identifier">run</phrase><phrase
role="special">()</phrase></code> function from which control does not return
until application shutdown.
</para>
<para>
A <ulink url="http://www.boost.org/doc/libs/release/libs/asio/index.html">Boost.Asio</ulink>
program might call <ulink url="http://www.boost.org/doc/libs/release/doc/html/boost_asio/reference/io_service/run.html"><code><phrase
role="identifier">io_service</phrase><phrase role="special">::</phrase><phrase
role="identifier">run</phrase><phrase role="special">()</phrase></code></ulink>
in this way.
</para>
<para>
The trick here is to arrange to pass control to <link linkend="this_fiber_yield"> <code>this_fiber::yield()</code></link> frequently.
You can use an <ulink url="http://www.boost.org/doc/libs/1_59_0/doc/html/boost_asio/reference/high_resolution_timer.html">Asio
timer</ulink> for this purpose. Instantiate the timer, arranging to call a
handler function when the timer expires:
</para>
<para>
<programlisting><phrase role="keyword">inline</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">run_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">io_service</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">io_service</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">high_resolution_timer</phrase> <phrase role="identifier">timer</phrase><phrase role="special">(</phrase> <phrase role="identifier">io_service</phrase><phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">seconds</phrase><phrase role="special">(</phrase><phrase role="number">0</phrase><phrase role="special">)</phrase> <phrase role="special">);</phrase>
<phrase role="identifier">timer</phrase><phrase role="special">.</phrase><phrase role="identifier">async_wait</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">bind</phrase><phrase role="special">(</phrase> <phrase role="identifier">timer_handler</phrase><phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">ref</phrase><phrase role="special">(</phrase> <phrase role="identifier">timer</phrase><phrase role="special">)</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>
</programlisting>
</para>
<para>
The handler function calls <code><phrase role="identifier">yield</phrase><phrase
role="special">()</phrase></code>, then resets the timer and arranges to wake
up again on expiration:
</para>
<para>
<programlisting><phrase role="keyword">inline</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">timer_handler</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">high_resolution_timer</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">timer</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
<phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">this_fiber</phrase><phrase role="special">::</phrase><phrase role="identifier">yield</phrase><phrase role="special">();</phrase>
<phrase role="identifier">timer</phrase><phrase role="special">.</phrase><phrase role="identifier">expires_from_now</phrase><phrase role="special">(</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">wait_interval</phrase><phrase role="special">()</phrase> <phrase role="special">);</phrase>
<phrase role="identifier">timer</phrase><phrase role="special">.</phrase><phrase role="identifier">async_wait</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">bind</phrase><phrase role="special">(</phrase> <phrase role="identifier">timer_handler</phrase><phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">ref</phrase><phrase role="special">(</phrase> <phrase role="identifier">timer</phrase><phrase role="special">)</phrase> <phrase role="special">)</phrase> <phrase role="special">);</phrase>
<phrase role="special">}</phrase>
</programlisting>
</para>
<para>
Then instead of directly calling <code><phrase role="identifier">io_service</phrase><phrase
role="special">::</phrase><phrase role="identifier">run</phrase><phrase role="special">()</phrase></code>,
your application would call the above <code><phrase role="identifier">run_service</phrase><phrase
role="special">(</phrase><phrase role="identifier">io_service</phrase><phrase
role="special">&amp;)</phrase></code> wrapper.
</para>
<para>
Note the use of <link linkend="wait_interval"> <code>wait_interval()</code></link> to reset the timer. This replicates
the default behavior of the fiber manager: when all fibers on the current thread
are blocked, the fiber manager sleeps for <code><phrase role="identifier">wait_interval</phrase><phrase
role="special">()</phrase></code> to permit real work to proceed on other threads.
</para>
<para>
Since, in this example, we always pass control to the fiber manager via <code><phrase
role="identifier">yield</phrase><phrase role="special">()</phrase></code>,
the calling fiber is never blocked. Therefore there is always at least one
ready fiber. Therefore the fiber manager never sleeps.
</para>
<para>
Using <code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase
role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase
role="identifier">seconds</phrase><phrase role="special">(</phrase><phrase
role="number">0</phrase><phrase role="special">)</phrase></code> for <emphasis>every</emphasis>
timer interval would be unfriendly to other threads. When all I/O is pending
and all fibers are blocked, the io_service and the fiber manager would simply
spin the CPU, passing control back and forth to each other. Resetting the timer
for <code><phrase role="identifier">wait_interval</phrase><phrase role="special">()</phrase></code>
allows tuning the responsiveness of this thread relative to others in the same
way as when <emphasis role="bold">Boost.Fiber</emphasis> is running without
<ulink url="http://www.boost.org/doc/libs/release/libs/asio/index.html">Boost.Asio</ulink>.
</para>
<para>
The source code above is found in <ulink url="../../examples/asio/loop.hpp">loop.hpp</ulink>.
</para>
</section>
<section id="fiber.performance">
<title><link linkend="fiber.performance">Performance</link></title>
<para>
Performance measurements were taken using <code><phrase role="identifier">std</phrase><phrase
role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase
role="special">::</phrase><phrase role="identifier">highresolution_clock</phrase></code>,
with overhead corrections. The code was compiled using the build options: variant
= release, optimization = speed <footnote id="fiber.performance.f0">
<para>
Intel Core2 Q6700, x86_64, 3GHz
</para>
</footnote>.
</para>
<para>
The columns labeled <emphasis role="bold">fiber (atomics)</emphasis> were compiled
with default fiber synchronization, capable of synchronizing fibers running
on different threads. The columns labeled <emphasis role="bold">fiber (raw)</emphasis>
were compiled with <link linkend="cross_thread_sync"><code><phrase role="identifier">BOOST_FIBERS_NO_ATOMICS</phrase></code></link>.
</para>
<table frame="all" id="fiber.performance.overhead_of_join__contains_fiber_context_destruction__fiber_stack_deallocation_">
<title>Overhead of join (contains fiber-context destruction, fiber-stack deallocation)</title>
<tgroup cols="5">
<thead>
<row>
<entry>
<para>
thread
</para>
</entry>
<entry>
<para>
fiber (atomics)
</para>
</entry>
<entry>
<para>
fiber (raw)
</para>
</entry>
<entry>
<para>
tbb
</para>
</entry>
<entry>
<para>
qthread
</para>
</entry>
</row>
</thead>
<tbody>
<row>
<entry>
<para>
18 &#xb5;s
</para>
</entry>
<entry>
<para>
950 ns
</para>
</entry>
<entry>
<para>
850 ns
</para>
</entry>
<entry>
<para>
570 ns
</para>
</entry>
<entry>
<para>
620 ns
</para>
</entry>
</row>
</tbody>
</tgroup>
</table>
<para>
(from <ulink url="../../performance/fiber/overhead_join.cpp">overhead_join.cpp</ulink>)
</para>
<table frame="all" id="fiber.performance.overhead_of_detach">
<title>Overhead of detach</title>
<tgroup cols="3">
<thead>
<row>
<entry>
<para>
thread
</para>
</entry>
<entry>
<para>
fiber (atomics)
</para>
</entry>
<entry>
<para>
fiber (raw)
</para>
</entry>
</row>
</thead>
<tbody>
<row>
<entry>
<para>
126 ns
</para>
</entry>
<entry>
<para>
21 ns
</para>
</entry>
<entry>
<para>
15 ns
</para>
</entry>
</row>
</tbody>
</tgroup>
</table>
<para>
(from <ulink url="../../performance/fiber/overhead_detach.cpp">overhead_detach.cpp</ulink>)
</para>
<table frame="all" id="fiber.performance.overhead_of_yield">
<title>Overhead of yield</title>
<tgroup cols="3">
<thead>
<row>
<entry>
<para>
thread
</para>
</entry>
<entry>
<para>
fiber (atomics)
</para>
</entry>
<entry>
<para>
fiber (raw)
</para>
</entry>
</row>
</thead>
<tbody>
<row>
<entry>
<para>
1.5 &#xb5;s
</para>
</entry>
<entry>
<para>
189 ns
</para>
</entry>
<entry>
<para>
168 ns
</para>
</entry>
</row>
</tbody>
</tgroup>
</table>
<para>
(from <ulink url="../../performance/fiber/overhead_yield.cpp">overhead_yield.cpp</ulink>)
</para>
<table frame="all" id="fiber.performance.overhead_of_waiting_on_a_future">
<title>Overhead of waiting on a future</title>
<tgroup cols="3">
<thead>
<row>
<entry>
<para>
thread
</para>
</entry>
<entry>
<para>
fiber (atomics)
</para>
</entry>
<entry>
<para>
fiber (raw)
</para>
</entry>
</row>
</thead>
<tbody>
<row>
<entry>
<para>
16 &#xb5;s
</para>
</entry>
<entry>
<para>
1.4 &#xb5;s
</para>
</entry>
<entry>
<para>
1.4 &#xb5;s
</para>
</entry>
</row>
</tbody>
</tgroup>
</table>
<para>
(from <ulink url="../../performance/fiber/overhead_future.cpp">overhead_future.cpp</ulink>)
</para>
<table frame="all" id="fiber.performance.overhead_of_fiber_creation__contains_fiber_stack_allocation_and_preparation__fiber_context_construction__scheduler_handling_">
<title>Overhead of fiber creation (contains fiber-stack allocation and preparation,
fiber-context construction, scheduler handling)</title>
<tgroup cols="3">
<thead>
<row>
<entry>
<para>
thread
</para>
</entry>
<entry>
<para>
fiber (atomics)
</para>
</entry>
<entry>
<para>
fiber (raw)
</para>
</entry>
</row>
</thead>
<tbody>
<row>
<entry>
<para>
18 &#xb5;s
</para>
</entry>
<entry>
<para>
210 ns
</para>
</entry>
<entry>
<para>
205 ns
</para>
</entry>
</row>
</tbody>
</tgroup>
</table>
<para>
(from <ulink url="../../performance/fiber/overhead_create.cpp">overhead_create.cpp</ulink>)
</para>
<table frame="all" id="fiber.performance.scaling_of_creating_and_joining">
<title>Scaling of creating and joining</title>
<tgroup cols="4">
<thead>
<row>
<entry>
<para>
average of
</para>
</entry>
<entry>
<para>
thread
</para>
</entry>
<entry>
<para>
fiber (atomics)
</para>
</entry>
<entry>
<para>
fiber (raw)
</para>
</entry>
</row>
</thead>
<tbody>
<row>
<entry>
<para>
10
</para>
</entry>
<entry>
<para>
8.21 &#xb5;s
</para>
</entry>
<entry>
<para>
1.96 &#xb5;s
</para>
</entry>
<entry>
<para>
1.85 &#xb5;s
</para>
</entry>
</row>
<row>
<entry>
<para>
50
</para>
</entry>
<entry>
<para>
6.67 &#xb5;s
</para>
</entry>
<entry>
<para>
1.40 &#xb5;s
</para>
</entry>
<entry>
<para>
1.27 &#xb5;s
</para>
</entry>
</row>
<row>
<entry>
<para>
100
</para>
</entry>
<entry>
<para>
6.79 &#xb5;s
</para>
</entry>
<entry>
<para>
1.84 &#xb5;s
</para>
</entry>
<entry>
<para>
1.81 &#xb5;s
</para>
</entry>
</row>
<row>
<entry>
<para>
500
</para>
</entry>
<entry>
<para>
8.25 &#xb5;s
</para>
</entry>
<entry>
<para>
1.13 &#xb5;s
</para>
</entry>
<entry>
<para>
1.10 &#xb5;s
</para>
</entry>
</row>
<row>
<entry>
<para>
1000
</para>
</entry>
<entry>
<para>
7.71 &#xb5;s
</para>
</entry>
<entry>
<para>
1.46 &#xb5;s
</para>
</entry>
<entry>
<para>
1.26 &#xb5;s
</para>
</entry>
</row>
<row>
<entry>
<para>
5000
</para>
</entry>
<entry>
<para>
5.67 &#xb5;s
</para>
</entry>
<entry>
<para>
2.11 &#xb5;s
</para>
</entry>
<entry>
<para>
1.90 &#xb5;s
</para>
</entry>
</row>
<row>
<entry>
<para>
10000
</para>
</entry>
<entry>
<para>
5.25 &#xb5;s
</para>
</entry>
<entry>
<para>
2.36 &#xb5;s
</para>
</entry>
<entry>
<para>
1.89 &#xb5;s
</para>
</entry>
</row>
</tbody>
</tgroup>
</table>
<para>
(from <ulink url="../../performance/fiber/scale_join.cpp">scale_join.cpp</ulink>)
</para>
</section>
<section id="fiber.custom">
<title><anchor id="custom"/><link linkend="fiber.custom">Customization</link></title>
<bridgehead renderas="sect3" id="fiber.custom.h0">
<phrase id="fiber.custom.overview"/><link linkend="fiber.custom.overview">Overview</link>
</bridgehead>
<para>
As noted in the <link linkend="scheduling">Scheduling</link> section, by default
<emphasis role="bold">Boost.Fiber</emphasis> uses its own <link linkend="class_round_robin"> <code>round_robin</code></link> scheduler
for each thread. To control the way <emphasis role="bold">Boost.Fiber</emphasis>
schedules ready fibers on a particular thread, in general you must follow several
steps. This section discusses those steps, whereas <link linkend="scheduling">Scheduling</link>
serves as a reference for the classes involved.
</para>
<para>
The library's fiber manager keeps track of suspended (blocked) fibers. Only
when a fiber becomes ready to run is it passed to the scheduler. Of course,
if there are fewer than two ready fibers, the scheduler's job is trivial. Only
when there are two or more ready fibers does the particular scheduler implementation
start to influence the overall sequence of fiber execution.
</para>
<para>
In this section we illustrate a simple custom scheduler that honors an integer
fiber priority. We will implement it such that a fiber with higher priority
is preferred over a fiber with lower priority. Any fibers with equal priority
values are serviced on a round-robin basis.
</para>
<para>
The full source code for the examples below is found in <ulink url="../../examples/priority.cpp">priority.cpp</ulink>.
</para>
<bridgehead renderas="sect3" id="fiber.custom.h1">
<phrase id="fiber.custom.custom_property_class"/><link linkend="fiber.custom.custom_property_class">Custom
Property Class</link>
</bridgehead>
<para>
The first essential point is that we must associate an integer priority with
each fiber.<footnote id="fiber.custom.f0">
<para>
A previous version of the Fiber library implicitly tracked an int priority
for each fiber, even though the default scheduler ignored it. This has been
dropped, since the library now supports arbitrary scheduler-specific fiber
properties.
</para>
</footnote>
</para>
<para>
One might suggest deriving a custom <link linkend="class_fiber"> <code>fiber</code></link> subclass to store such
properties. There are a couple of reasons for the present mechanism.
</para>
<orderedlist>
<listitem>
<simpara>
<emphasis role="bold">Boost.Fiber</emphasis> provides a number of different
ways to launch a fiber. (Consider <link linkend="fibers_async"> <code>fibers::async()</code></link>.) Higher-level
libraries might introduce additional such wrapper functions. A custom scheduler
must associate its custom properties with <emphasis>every</emphasis> fiber
in the thread, not only the ones explicitly launched by instantiating a
custom <code><phrase role="identifier">fiber</phrase></code> subclass.
</simpara>
</listitem>
<listitem>
<simpara>
Consider a large existing program that launches fibers in many different
places in the code. We discover a need to introduce a custom scheduler
for a particular thread. If supporting that scheduler's custom properties
required a particular <code><phrase role="identifier">fiber</phrase></code>
subclass, we would have to hunt down and modify every place that launches
a fiber on that thread.
</simpara>
</listitem>
</orderedlist>
<para>
The present mechanism allows you to &quot;drop in&quot; a custom scheduler
with its attendant custom properties <emphasis>without</emphasis> altering
the rest of your application.
</para>
<para>
Instead of deriving a custom scheduler fiber properties subclass from <link linkend="class_fiber"> <code>fiber</code></link>,
you must instead derive it from <link linkend="class_fiber_properties"> <code>fiber_properties</code></link>.
</para>
<para>
<programlisting><phrase role="keyword">class</phrase> <phrase role="identifier">priority_props</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">fiber_properties</phrase> <phrase role="special">{</phrase>
<phrase role="keyword">public</phrase><phrase role="special">:</phrase>
<phrase role="identifier">priority_props</phrase><phrase role="special">(</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">context</phrase> <phrase role="special">*</phrase> <phrase role="identifier">p</phrase><phrase role="special">):</phrase>
<phrase role="identifier">fiber_properties</phrase><phrase role="special">(</phrase> <phrase role="identifier">p</phrase><phrase role="special">),</phrase> <co id="fiber.custom.c0" linkends="fiber.custom.c1" />
<phrase role="identifier">priority_</phrase><phrase role="special">(</phrase> <phrase role="number">0</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
<phrase role="special">}</phrase>
<phrase role="keyword">int</phrase> <phrase role="identifier">get_priority</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase> <phrase role="special">{</phrase>
<phrase role="keyword">return</phrase> <phrase role="identifier">priority_</phrase><phrase role="special">;</phrase> <co id="fiber.custom.c2" linkends="fiber.custom.c3" />
<phrase role="special">}</phrase>
<phrase role="comment">// Call this method to alter priority, because we must notify</phrase>
<phrase role="comment">// priority_scheduler of any change.</phrase>
<phrase role="keyword">void</phrase> <phrase role="identifier">set_priority</phrase><phrase role="special">(</phrase> <phrase role="keyword">int</phrase> <phrase role="identifier">p</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
<co id="fiber.custom.c4" linkends="fiber.custom.c5" />
<phrase role="comment">// Of course, it's only worth reshuffling the queue and all if we're</phrase>
<phrase role="comment">// actually changing the priority.</phrase>
<phrase role="keyword">if</phrase> <phrase role="special">(</phrase> <phrase role="identifier">p</phrase> <phrase role="special">!=</phrase> <phrase role="identifier">priority_</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
<phrase role="identifier">priority_</phrase> <phrase role="special">=</phrase> <phrase role="identifier">p</phrase><phrase role="special">;</phrase>
<phrase role="identifier">notify</phrase><phrase role="special">();</phrase>
<phrase role="special">}</phrase>
<phrase role="special">}</phrase>
<phrase role="comment">// The fiber name of course is solely for purposes of this example</phrase>
<phrase role="comment">// program; it has nothing to do with implementing scheduler priority.</phrase>
<phrase role="comment">// This is a public data member -- not requiring set/get access methods --</phrase>
<phrase role="comment">// because we need not inform the scheduler of any change.</phrase>
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="identifier">name</phrase><phrase role="special">;</phrase> <co id="fiber.custom.c6" linkends="fiber.custom.c7" />
<phrase role="keyword">private</phrase><phrase role="special">:</phrase>
<phrase role="keyword">int</phrase> <phrase role="identifier">priority_</phrase><phrase role="special">;</phrase>
<phrase role="special">};</phrase>
</programlisting>
</para>
<calloutlist>
<callout arearefs="fiber.custom.c0" id="fiber.custom.c1">
<para>
Your subclass constructor must accept a <literal> <link linkend="class_context"> <code>context</code></link>*</literal>
and pass it to the <code><phrase role="identifier">fiber_properties</phrase></code>
constructor.
</para>
</callout>
<callout arearefs="fiber.custom.c2" id="fiber.custom.c3">
<para>
Provide read access methods at your own discretion.
</para>
</callout>
<callout arearefs="fiber.custom.c4" id="fiber.custom.c5">
<para>
It's important to call notify() on any change in a property that can affect
the scheduler's behavior. Therefore, such modifications should only be
performed through an access method.
</para>
</callout>
<callout arearefs="fiber.custom.c6" id="fiber.custom.c7">
<para>
A property that does not affect the scheduler does not need access methods.
</para>
</callout>
</calloutlist>
<bridgehead renderas="sect3" id="fiber.custom.h2">
<phrase id="fiber.custom.custom_scheduler_class"/><link linkend="fiber.custom.custom_scheduler_class">Custom
Scheduler Class</link>
</bridgehead>
<para>
Now we can derive a custom scheduler from <link linkend="class_sched_algorithm_with_properties"> <code>sched_algorithm_with_properties&lt;&gt;</code></link>,
specifying our custom property class <code><phrase role="identifier">priority_props</phrase></code>
as the template parameter.
</para>
<para>
Your custom scheduler can track ready <literal> <link linkend="class_context"> <code>context</code></link>*</literal>s
using whatever container tactic you prefer. In this example, we use <link linkend="context_nxt"> <code>context::nxt</code></link> to
hand-implement an intrusive singly-linked list.
</para>
<para>
<programlisting><phrase role="keyword">class</phrase> <phrase role="identifier">priority_scheduler</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">sched_algorithm_with_properties</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">priority_props</phrase> <phrase role="special">&gt;</phrase> <phrase role="special">{</phrase>
<phrase role="keyword">private</phrase><phrase role="special">:</phrase>
<phrase role="comment">// Much as we would like, we don't use std::priority_queue because it</phrase>
<phrase role="comment">// doesn't appear to provide any way to alter the priority (and hence</phrase>
<phrase role="comment">// queue position) of a particular item.</phrase>
<phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">context</phrase> <phrase role="special">*</phrase> <phrase role="identifier">head_</phrase><phrase role="special">;</phrase>
<phrase role="keyword">public</phrase><phrase role="special">:</phrase>
<phrase role="identifier">priority_scheduler</phrase><phrase role="special">()</phrase> <phrase role="special">:</phrase>
<phrase role="identifier">head_</phrase><phrase role="special">(</phrase> <phrase role="keyword">nullptr</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
<phrase role="special">}</phrase>
<phrase role="comment">// For a subclass of sched_algorithm_with_properties&lt;&gt;, it's important to</phrase>
<phrase role="comment">// override the correct awakened() overload.</phrase>
<co id="fiber.custom.c8" linkends="fiber.custom.c9" /><phrase role="keyword">virtual</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">awakened</phrase><phrase role="special">(</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">context</phrase> <phrase role="special">*</phrase> <phrase role="identifier">f</phrase><phrase role="special">,</phrase> <phrase role="identifier">priority_props</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">props</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
<phrase role="keyword">int</phrase> <phrase role="identifier">f_priority</phrase> <phrase role="special">=</phrase> <phrase role="identifier">props</phrase><phrase role="special">.</phrase><phrase role="identifier">get_priority</phrase><phrase role="special">();</phrase> <co id="fiber.custom.c10" linkends="fiber.custom.c11" />
<phrase role="comment">// With this scheduler, fibers with higher priority values are</phrase>
<phrase role="comment">// preferred over fibers with lower priority values. But fibers with</phrase>
<phrase role="comment">// equal priority values are processed in round-robin fashion. So when</phrase>
<phrase role="comment">// we're handed a new context*, put it at the end of the fibers</phrase>
<phrase role="comment">// with that same priority. In other words: search for the first fiber</phrase>
<phrase role="comment">// in the queue with LOWER priority, and insert before that one.</phrase>
<phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">context</phrase> <phrase role="special">**</phrase> <phrase role="identifier">fp</phrase> <phrase role="special">=</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">head_</phrase><phrase role="special">;</phrase>
<phrase role="keyword">for</phrase> <phrase role="special">(</phrase> <phrase role="special">;</phrase> <phrase role="special">*</phrase> <phrase role="identifier">fp</phrase><phrase role="special">;</phrase> <phrase role="identifier">fp</phrase> <phrase role="special">=</phrase> <phrase role="special">&amp;</phrase> <phrase role="special">(</phrase> <phrase role="special">*</phrase> <phrase role="identifier">fp</phrase><phrase role="special">)-&gt;</phrase><phrase role="identifier">nxt</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
<phrase role="keyword">if</phrase> <phrase role="special">(</phrase> <phrase role="identifier">properties</phrase><phrase role="special">(</phrase> <phrase role="special">*</phrase> <phrase role="identifier">fp</phrase><phrase role="special">).</phrase><phrase role="identifier">get_priority</phrase><phrase role="special">()</phrase> <phrase role="special">&lt;</phrase> <phrase role="identifier">f_priority</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
<co id="fiber.custom.c12" linkends="fiber.custom.c13" />
<phrase role="keyword">break</phrase><phrase role="special">;</phrase>
<phrase role="special">}</phrase>
<phrase role="special">}</phrase>
<phrase role="comment">// It doesn't matter whether we hit the end of the list or found</phrase>
<phrase role="comment">// another fiber with lower priority. Either way, insert f here.</phrase>
<phrase role="identifier">f</phrase><phrase role="special">-&gt;</phrase><phrase role="identifier">nxt</phrase> <phrase role="special">=</phrase> <phrase role="special">*</phrase> <phrase role="identifier">fp</phrase><phrase role="special">;</phrase> <co id="fiber.custom.c14" linkends="fiber.custom.c15" />
<phrase role="special">*</phrase> <phrase role="identifier">fp</phrase> <phrase role="special">=</phrase> <phrase role="identifier">f</phrase><phrase role="special">;</phrase>
<phrase role="special">}</phrase>
<co id="fiber.custom.c16" linkends="fiber.custom.c17" /><phrase role="keyword">virtual</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">context</phrase> <phrase role="special">*</phrase> <phrase role="identifier">pick_next</phrase><phrase role="special">()</phrase> <phrase role="special">{</phrase>
<phrase role="comment">// if ready queue is empty, just tell caller</phrase>
<phrase role="keyword">if</phrase> <phrase role="special">(</phrase> <phrase role="special">!</phrase> <phrase role="identifier">head_</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
<phrase role="keyword">return</phrase> <phrase role="keyword">nullptr</phrase><phrase role="special">;</phrase>
<phrase role="special">}</phrase>
<phrase role="comment">// Here we have at least one ready fiber. Unlink and return that.</phrase>
<phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">context</phrase> <phrase role="special">*</phrase> <phrase role="identifier">f</phrase> <phrase role="special">=</phrase> <phrase role="identifier">head_</phrase><phrase role="special">;</phrase>
<phrase role="identifier">head_</phrase> <phrase role="special">=</phrase> <phrase role="identifier">f</phrase><phrase role="special">-&gt;</phrase><phrase role="identifier">nxt</phrase><phrase role="special">;</phrase>
<phrase role="identifier">f</phrase><phrase role="special">-&gt;</phrase><phrase role="identifier">nxt</phrase> <phrase role="special">=</phrase> <phrase role="keyword">nullptr</phrase><phrase role="special">;</phrase>
<phrase role="keyword">return</phrase> <phrase role="identifier">f</phrase><phrase role="special">;</phrase>
<phrase role="special">}</phrase>
<co id="fiber.custom.c18" linkends="fiber.custom.c19" /><phrase role="keyword">virtual</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">ready_fibers</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase> <phrase role="special">{</phrase>
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">count</phrase> <phrase role="special">=</phrase> <phrase role="number">0</phrase><phrase role="special">;</phrase>
<phrase role="keyword">for</phrase> <phrase role="special">(</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">context</phrase> <phrase role="special">*</phrase> <phrase role="identifier">f</phrase> <phrase role="special">=</phrase> <phrase role="identifier">head_</phrase><phrase role="special">;</phrase> <phrase role="identifier">f</phrase><phrase role="special">;</phrase> <phrase role="identifier">f</phrase> <phrase role="special">=</phrase> <phrase role="identifier">f</phrase><phrase role="special">-&gt;</phrase><phrase role="identifier">nxt</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
<phrase role="special">++</phrase><phrase role="identifier">count</phrase><phrase role="special">;</phrase>
<phrase role="special">}</phrase>
<phrase role="keyword">return</phrase> <phrase role="identifier">count</phrase><phrase role="special">;</phrase>
<phrase role="special">}</phrase>
<co id="fiber.custom.c20" linkends="fiber.custom.c21" /><phrase role="keyword">virtual</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">property_change</phrase><phrase role="special">(</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">context</phrase> <phrase role="special">*</phrase> <phrase role="identifier">f</phrase><phrase role="special">,</phrase> <phrase role="identifier">priority_props</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">props</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
<phrase role="comment">// Although our priority_props class defines multiple properties, only</phrase>
<phrase role="comment">// one of them (priority) actually calls notify() when changed. The</phrase>
<phrase role="comment">// point of a property_change() override is to reshuffle the ready</phrase>
<phrase role="comment">// queue according to the updated priority value.</phrase>
<phrase role="comment">// Find 'f' in the queue. Note that it might not be in our queue at</phrase>
<phrase role="comment">// all, if caller is changing the priority of (say) the running fiber.</phrase>
<phrase role="keyword">bool</phrase> <phrase role="identifier">found</phrase> <phrase role="special">=</phrase> <phrase role="keyword">false</phrase><phrase role="special">;</phrase>
<phrase role="keyword">for</phrase> <phrase role="special">(</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">context</phrase> <phrase role="special">**</phrase> <phrase role="identifier">fp</phrase> <phrase role="special">=</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">head_</phrase><phrase role="special">;</phrase> <phrase role="special">*</phrase> <phrase role="identifier">fp</phrase><phrase role="special">;</phrase> <phrase role="identifier">fp</phrase> <phrase role="special">=</phrase> <phrase role="special">&amp;</phrase> <phrase role="special">(</phrase> <phrase role="special">*</phrase> <phrase role="identifier">fp</phrase><phrase role="special">)-&gt;</phrase><phrase role="identifier">nxt</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">fp</phrase> <phrase role="special">==</phrase> <phrase role="identifier">f</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
<phrase role="comment">// found the passed fiber in our list -- unlink it</phrase>
<phrase role="identifier">found</phrase> <phrase role="special">=</phrase> <phrase role="keyword">true</phrase><phrase role="special">;</phrase>
<phrase role="special">*</phrase> <phrase role="identifier">fp</phrase> <phrase role="special">=</phrase> <phrase role="special">(</phrase> <phrase role="special">*</phrase> <phrase role="identifier">fp</phrase><phrase role="special">)-&gt;</phrase><phrase role="identifier">nxt</phrase><phrase role="special">;</phrase>
<phrase role="identifier">f</phrase><phrase role="special">-&gt;</phrase><phrase role="identifier">nxt</phrase> <phrase role="special">=</phrase> <phrase role="keyword">nullptr</phrase><phrase role="special">;</phrase>
<phrase role="keyword">break</phrase><phrase role="special">;</phrase>
<phrase role="special">}</phrase>
<phrase role="special">}</phrase>
<phrase role="comment">// It's possible to get a property_change() call for a fiber that is</phrase>
<phrase role="comment">// not on our ready queue. If it's not there, no need to move it:</phrase>
<phrase role="comment">// we'll handle it next time it hits awakened().</phrase>
<phrase role="keyword">if</phrase> <phrase role="special">(</phrase> <phrase role="special">!</phrase> <phrase role="identifier">found</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
<co id="fiber.custom.c22" linkends="fiber.custom.c23" />
<phrase role="keyword">return</phrase><phrase role="special">;</phrase>
<phrase role="special">}</phrase>
<phrase role="comment">// Here we know that f was in our ready queue, but we've unlinked it.</phrase>
<phrase role="comment">// We happen to have a method that will (re-)add a context* to</phrase>
<phrase role="comment">// the ready queue.</phrase>
<phrase role="identifier">awakened</phrase><phrase role="special">(</phrase><phrase role="identifier">f</phrase><phrase role="special">,</phrase> <phrase role="identifier">props</phrase><phrase role="special">);</phrase>
<phrase role="special">}</phrase>
<phrase role="special">};</phrase>
</programlisting>
</para>
<calloutlist>
<callout arearefs="fiber.custom.c8" id="fiber.custom.c9">
<para>
You must override the <link linkend="sched_algorithm_with_properties_awakened"> <code>sched_algorithm_with_properties::awakened()</code></link>
method.
This is how your scheduler receives notification of a fiber that has become
ready to run.
</para>
</callout>
<callout arearefs="fiber.custom.c10" id="fiber.custom.c11">
<para>
<code><phrase role="identifier">props</phrase></code> is the instance of
priority_props associated with the passed fiber <code><phrase role="identifier">f</phrase></code>.
</para>
</callout>
<callout arearefs="fiber.custom.c12" id="fiber.custom.c13">
<para>
Use the <link linkend="sched_algorithm_with_properties_properties"> <code>sched_algorithm_with_properties::properties()</code></link>
method
to access properties for any <emphasis>other</emphasis> fiber.
</para>
</callout>
<callout arearefs="fiber.custom.c14" id="fiber.custom.c15">
<para>
Note use of the <link linkend="context_nxt"> <code>context::nxt</code></link> member.
</para>
</callout>
<callout arearefs="fiber.custom.c16" id="fiber.custom.c17">
<para>
You must override the <link linkend="sched_algorithm_with_properties_pick_next"> <code>sched_algorithm_with_properties::pick_next()</code></link>
method.
This is how your scheduler actually advises the fiber manager of the next
fiber to run.
</para>
</callout>
<callout arearefs="fiber.custom.c18" id="fiber.custom.c19">
<para>
You must override <link linkend="sched_algorithm_with_properties_ready_fibers"> <code>sched_algorithm_with_properties::ready_fibers()</code></link>
to
inform the fiber manager of the size of your ready queue.
</para>
</callout>
<callout arearefs="fiber.custom.c20" id="fiber.custom.c21">
<para>
Overriding <link linkend="sched_algorithm_with_properties_property_change"> <code>sched_algorithm_with_properties::property_change()</code></link>
is
optional. This override handles the case in which the running fiber changes
the priority of another ready fiber: a fiber already in our queue. In that
case, move the updated fiber within the queue.
</para>
</callout>
<callout arearefs="fiber.custom.c22" id="fiber.custom.c23">
<para>
Your <code><phrase role="identifier">property_change</phrase><phrase role="special">()</phrase></code>
override must be able to handle the case in which the passed <code><phrase
role="identifier">f</phrase></code> is not in your ready queue. It might
be running, or it might be blocked.
</para>
</callout>
</calloutlist>
<para>
Our example <code><phrase role="identifier">priority_scheduler</phrase></code>
doesn't override <link linkend="sched_algorithm_with_properties_new_properties"> <code>sched_algorithm_with_properties::new_properties()</code></link>:
we're content with allocating <code><phrase role="identifier">priority_props</phrase></code>
instances on the heap.
</para>
<bridgehead renderas="sect3" id="fiber.custom.h3">
<phrase id="fiber.custom.replace_default_scheduler"/><link linkend="fiber.custom.replace_default_scheduler">Replace
Default Scheduler</link>
</bridgehead>
<para>
You must call <link linkend="use_scheduling_algorithm"> <code>use_scheduling_algorithm()</code></link> at the start
of each thread on which you want <emphasis role="bold">Boost.Fiber</emphasis>
to use your custom scheduler rather than its own default <link linkend="class_round_robin"> <code>round_robin</code></link>.
Specifically, you must call <code><phrase role="identifier">use_scheduling_algorithm</phrase><phrase
role="special">()</phrase></code> before performing any other <emphasis role="bold">Boost.Fiber</emphasis>
operations on that thread.
</para>
<para>
<programlisting><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">// make sure we use our priority_scheduler rather than default round_robin</phrase>
<phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">use_scheduling_algorithm</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">priority_scheduler</phrase> <phrase role="special">&gt;();</phrase>
<phrase role="special">...</phrase>
<phrase role="special">}</phrase>
</programlisting>
</para>
<bridgehead renderas="sect3" id="fiber.custom.h4">
<phrase id="fiber.custom.use_properties"/><link linkend="fiber.custom.use_properties">Use
Properties</link>
</bridgehead>
<para>
The running fiber can access its own <link linkend="class_fiber_properties"> <code>fiber_properties</code></link> subclass
instance by calling <link linkend="this_fiber_properties"> <code>this_fiber::properties()</code></link>. Although
<code><phrase role="identifier">properties</phrase><phrase role="special">&lt;&gt;()</phrase></code>
is a nullary function, you must pass, as a template parameter, the <code><phrase
role="identifier">fiber_properties</phrase></code> subclass.
</para>
<para>
<programlisting><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">this_fiber</phrase><phrase role="special">::</phrase><phrase role="identifier">properties</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">priority_props</phrase> <phrase role="special">&gt;().</phrase><phrase role="identifier">name</phrase> <phrase role="special">=</phrase> <phrase role="string">&quot;main&quot;</phrase><phrase role="special">;</phrase>
</programlisting>
</para>
<para>
Given a <link linkend="class_fiber"> <code>fiber</code></link> instance still connected with a running fiber (that
is, not <link linkend="fiber_detach"> <code>fiber::detach()</code></link>ed), you may access that fiber's properties
using <link linkend="fiber_properties"> <code>fiber::properties()</code></link>. As with <code><phrase role="identifier">this_fiber</phrase><phrase
role="special">::</phrase><phrase role="identifier">properties</phrase><phrase
role="special">&lt;&gt;()</phrase></code>, you must pass your <code><phrase
role="identifier">fiber_properties</phrase></code> subclass as the template
parameter.
</para>
<para>
<programlisting><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">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">fiber</phrase> <phrase role="identifier">launch</phrase><phrase role="special">(</phrase> <phrase role="identifier">Fn</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="identifier">func</phrase><phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">name</phrase><phrase role="special">,</phrase> <phrase role="keyword">int</phrase> <phrase role="identifier">priority</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
<phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">fiber</phrase> <phrase role="identifier">fiber</phrase><phrase role="special">(</phrase> <phrase role="identifier">func</phrase><phrase role="special">);</phrase>
<phrase role="identifier">priority_props</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">props</phrase><phrase role="special">(</phrase> <phrase role="identifier">fiber</phrase><phrase role="special">.</phrase><phrase role="identifier">properties</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">priority_props</phrase> <phrase role="special">&gt;()</phrase> <phrase role="special">);</phrase>
<phrase role="identifier">props</phrase><phrase role="special">.</phrase><phrase role="identifier">name</phrase> <phrase role="special">=</phrase> <phrase role="identifier">name</phrase><phrase role="special">;</phrase>
<phrase role="identifier">props</phrase><phrase role="special">.</phrase><phrase role="identifier">set_priority</phrase><phrase role="special">(</phrase> <phrase role="identifier">priority</phrase><phrase role="special">);</phrase>
<phrase role="keyword">return</phrase> <phrase role="identifier">fiber</phrase><phrase role="special">;</phrase>
<phrase role="special">}</phrase>
</programlisting>
</para>
<para>
Launching a new fiber schedules that fiber as ready, but does <emphasis>not</emphasis>
immediately enter its <emphasis>fiber-function</emphasis>. The current fiber
retains control until it blocks (or yields, or terminates) for some other reason.
As shown in the <code><phrase role="identifier">launch</phrase><phrase role="special">()</phrase></code>
function above, it is reasonable to launch a fiber and immediately set relevant
properties -- such as, for instance, its priority. Your custom scheduler can
then make use of this information next time the fiber manager calls <link linkend="sched_algorithm_with_properties_pick_next"> <code>sched_algorithm_with_properties::pick_next()</code></link>.
</para>
</section>
<section id="fiber.acknowledgements">
<title><link linkend="fiber.acknowledgements">Acknowledgments</link></title>
<para>
I'd like to thank Eugene Yakubovich and especially Nat Goodspeed.
</para>
</section>
</library>