<?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: 2018/10/22 08:13:04 $"
 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://en.cppreference.com/w/cpp/thread">standard
      thread support library</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/cc.html"><emphasis>call/cc</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 runs 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 distribute your program
      across more hardware cores, though it can make more effective use of the core
      on which it's running.
    </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 can be migrated from one thread to another, though the library does
      not do this by default. It is possible for you to supply a custom scheduler
      that migrates fibers between threads. You may specify custom fiber properties
      to help your scheduler decide which fibers are permitted to migrate. Please
      see <link linkend="migration">Migrating fibers between threads</link> and
      <link linkend="custom">Customization</link> for more details.
    </para>
    <para>
      <emphasis role="bold">Boost.Fiber</emphasis> allows to <emphasis role="bold"><code><phrase
      role="identifier">multiplex</phrase> <phrase role="identifier">fibers</phrase>
      <phrase role="identifier">across</phrase> <phrase role="identifier">multiple</phrase>
      <phrase role="identifier">cores</phrase></code></emphasis> (see <link linkend="class_numa_work_stealing"><code>numa::work_stealing</code></link>).
    </para>
    <para>
      A fiber launched on a particular thread continues running on that thread unless
      migrated. It might be unblocked (see <link linkend="blocking">Blocking</link>
      below) by some other thread, but that only transitions the fiber from <quote>blocked</quote>
      to <quote>ready</quote> on its current thread &mdash; it does not cause the fiber to
      resume on the thread that unblocked it.
    </para>
    <anchor id="thread_local_storage"/>
    <bridgehead renderas="sect3" id="fiber.overview.h1">
      <phrase id="fiber.overview.thread_local_storage"/><link linkend="fiber.overview.thread_local_storage">thread-local
      storage</link>
    </bridgehead>
    <para>
      Unless migrated, a fiber may access thread-local storage; however that storage
      will be shared among all fibers running on the same thread. For fiber-local
      storage, please see <link linkend="class_fiber_specific_ptr"><code>fiber_specific_ptr</code></link>.
    </para>
    <anchor id="cross_thread_sync"/>
    <bridgehead renderas="sect3" id="fiber.overview.h2">
      <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>
    <anchor id="blocking"/>
    <bridgehead renderas="sect3" id="fiber.overview.h3">
      <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>
    <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.61.0 or greater is required.
    </para>
    <note>
      <para>
        This library requires C++11!
      </para>
    </note>
    <section id="fiber.overview.implementations__fcontext_t__ucontext_t_and_winfiber">
      <title><anchor id="implementation"/><link linkend="fiber.overview.implementations__fcontext_t__ucontext_t_and_winfiber">Implementations:
      fcontext_t, ucontext_t and WinFiber</link></title>
      <para>
        <emphasis role="bold">Boost.Fiber</emphasis> uses <ulink url="http://www.boost.org/doc/libs/release/libs/context/doc/html/context/cc.html"><emphasis>call/cc</emphasis></ulink>
        from <ulink url="http://www.boost.org/doc/libs/release/libs/context/index.html">Boost.Context</ulink>
        as building-block.
      </para>
      <bridgehead renderas="sect4" id="fiber.overview.implementations__fcontext_t__ucontext_t_and_winfiber.h0">
        <phrase id="fiber.overview.implementations__fcontext_t__ucontext_t_and_winfiber.fcontext_t"/><link
        linkend="fiber.overview.implementations__fcontext_t__ucontext_t_and_winfiber.fcontext_t">fcontext_t</link>
      </bridgehead>
      <para>
        The implementation uses <code><phrase role="identifier">fcontext_t</phrase></code>
        per default. fcontext_t is based on assembler and not available for all platforms.
        It provides a much better performance than <code><phrase role="identifier">ucontext_t</phrase></code>
        (the context switch takes two magnitudes of order less CPU cycles; see section
        <ulink url="http://www.boost.org/doc/libs/release/libs/context/doc/html/context/performance.html"><emphasis>performance</emphasis></ulink>)
        and <code><phrase role="identifier">WinFiber</phrase></code>.
      </para>
      <bridgehead renderas="sect4" id="fiber.overview.implementations__fcontext_t__ucontext_t_and_winfiber.h1">
        <phrase id="fiber.overview.implementations__fcontext_t__ucontext_t_and_winfiber.ucontext_t"/><link
        linkend="fiber.overview.implementations__fcontext_t__ucontext_t_and_winfiber.ucontext_t">ucontext_t</link>
      </bridgehead>
      <para>
        As an alternative, <ulink url="https://en.wikipedia.org/wiki/Setcontext"><code><phrase
        role="identifier">ucontext_t</phrase></code></ulink> can be used by compiling
        with <code><phrase role="identifier">BOOST_USE_UCONTEXT</phrase></code> and
        b2 property <code><phrase role="identifier">context</phrase><phrase role="special">-</phrase><phrase
        role="identifier">impl</phrase><phrase role="special">=</phrase><phrase role="identifier">ucontext</phrase></code>.
        <code><phrase role="identifier">ucontext_t</phrase></code> might be available
        on a broader range of POSIX-platforms but has some <ulink url="http://www.boost.org/doc/libs/release/libs/context/doc/html/context/rational.html#ucontext"><emphasis>disadvantages</emphasis></ulink>
        (for instance deprecated since POSIX.1-2003, not C99 conform).
      </para>
      <note>
        <para>
          <ulink url="http://www.boost.org/doc/libs/release/libs/context/doc/html/context/cc.html"><emphasis>call/cc</emphasis></ulink>
          supports <link linkend="segmented"><emphasis>Segmented stacks</emphasis></link>
          only with <code><phrase role="identifier">ucontext_t</phrase></code> as
          its implementation.
        </para>
      </note>
      <bridgehead renderas="sect4" id="fiber.overview.implementations__fcontext_t__ucontext_t_and_winfiber.h2">
        <phrase id="fiber.overview.implementations__fcontext_t__ucontext_t_and_winfiber.winfiber"/><link
        linkend="fiber.overview.implementations__fcontext_t__ucontext_t_and_winfiber.winfiber">WinFiber</link>
      </bridgehead>
      <para>
        With <code><phrase role="identifier">BOOST_USE_WINFIB</phrase></code> and
        b2 property <code><phrase role="identifier">context</phrase><phrase role="special">-</phrase><phrase
        role="identifier">impl</phrase><phrase role="special">=</phrase><phrase role="identifier">winfib</phrase></code>
        Win32-Fibers are used as implementation for <ulink url="http://www.boost.org/doc/libs/release/libs/context/doc/html/context/cc.html"><emphasis>call/cc</emphasis></ulink>.
      </para>
      <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.
      </para>
      <note>
        <para>
          The first call of <ulink url="http://www.boost.org/doc/libs/release/libs/context/doc/html/context/cc.html"><emphasis>call/cc</emphasis></ulink>
          converts the thread into a Windows fiber by invoking <code><phrase role="identifier">ConvertThreadToFiber</phrase><phrase
          role="special">()</phrase></code>. If desired, <code><phrase role="identifier">ConvertFiberToThread</phrase><phrase
          role="special">()</phrase></code> has to be called by the user explicitly
          in order to release resources allocated by <code><phrase role="identifier">ConvertThreadToFiber</phrase><phrase
          role="special">()</phrase></code> (e.g. after using boost.context).
        </para>
      </note>
    </section>
    <important>
      <para>
        Windows using fcontext_t: turn off global program optimization (/GL) and
        change /EHsc (compiler assumes that functions declared as extern &quot;C&quot;
        never throw a C++ exception) to /EHs (tells compiler assumes that functions
        declared as extern &quot;C&quot; may throw an exception).
      </para>
    </important>
  </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">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="keyword">bool</phrase> <phrase role="identifier">has_ready_fibers</phrase><phrase role="special">();</phrase>

<phrase role="keyword">namespace</phrase> <phrase role="identifier">algo</phrase> <phrase role="special">{</phrase>

<phrase role="keyword">struct</phrase> <phrase role="identifier">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">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">class</phrase> <phrase role="identifier">shared_round_robin</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">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">rel_time</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>
</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> or
      <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&#8217;s main fiber terminates,
      the thread will not shut down.
    </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.
    </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="class_fiber_id"/>
    <bridgehead renderas="sect3" id="fiber.fiber_mgmt.h7">
      <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>
    <anchor id="class_launch"/>
    <bridgehead renderas="sect3" id="fiber.fiber_mgmt.h8">
      <phrase id="fiber.fiber_mgmt.enumeration__code__phrase_role__identifier__launch__phrase___code_"/><link
      linkend="fiber.fiber_mgmt.enumeration__code__phrase_role__identifier__launch__phrase___code_">Enumeration
      <code><phrase role="identifier">launch</phrase></code></link>
    </bridgehead>
    <para>
      <code><phrase role="identifier">launch</phrase></code> specifies whether control
      passes immediately into a newly-launched fiber.
    </para>
<programlisting><phrase role="keyword">enum</phrase> <phrase role="keyword">class</phrase> <phrase role="identifier">launch</phrase> <phrase role="special">{</phrase>
    <phrase role="identifier">dispatch</phrase><phrase role="special">,</phrase>
    <phrase role="identifier">post</phrase>
<phrase role="special">};</phrase>
</programlisting>
    <bridgehead renderas="sect3" id="fiber.fiber_mgmt.h9">
      <phrase id="fiber.fiber_mgmt._code__phrase_role__identifier__dispatch__phrase___code_"/><link
      linkend="fiber.fiber_mgmt._code__phrase_role__identifier__dispatch__phrase___code_"><code><phrase
      role="identifier">dispatch</phrase></code></link>
    </bridgehead>
    <variablelist>
      <title></title>
      <varlistentry>
        <term>Effects:</term>
        <listitem>
          <para>
            A fiber launched with <code><phrase role="identifier">launch</phrase>
            <phrase role="special">==</phrase> <phrase role="identifier">dispatch</phrase></code>
            is entered immediately. In other words, launching a fiber with <code><phrase
            role="identifier">dispatch</phrase></code> suspends the caller (the previously-running
            fiber) until the fiber scheduler has a chance to resume it later.
          </para>
        </listitem>
      </varlistentry>
    </variablelist>
    <bridgehead renderas="sect3" id="fiber.fiber_mgmt.h10">
      <phrase id="fiber.fiber_mgmt._code__phrase_role__identifier__post__phrase___code_"/><link
      linkend="fiber.fiber_mgmt._code__phrase_role__identifier__post__phrase___code_"><code><phrase
      role="identifier">post</phrase></code></link>
    </bridgehead>
    <variablelist>
      <title></title>
      <varlistentry>
        <term>Effects:</term>
        <listitem>
          <para>
            A fiber launched with <code><phrase role="identifier">launch</phrase>
            <phrase role="special">==</phrase> <phrase role="identifier">post</phrase></code>
            is passed to the fiber scheduler as ready, but it is not yet entered.
            The caller (the previously-running fiber) continues executing. The newly-launched
            fiber will be entered when the fiber scheduler has a chance to resume
            it later.
          </para>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term>Note:</term>
        <listitem>
          <para>
            If <code><phrase role="identifier">launch</phrase></code> is not explicitly
            specified, <code><phrase role="identifier">post</phrase></code> is the
            default.
          </para>
        </listitem>
      </varlistentry>
    </variablelist>
    <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">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">public</phrase><phrase role="special">:</phrase>
    <phrase role="keyword">class</phrase> <phrase role="identifier">id</phrase><phrase role="special">;</phrase>

    <phrase role="keyword">constexpr</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="identifier">fiber</phrase><phrase role="special">(</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="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">fiber</phrase><phrase role="special">(</phrase> <link linkend="class_launch"><code><phrase role="identifier">launch</phrase></code></link><phrase role="special">,</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="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <link linkend="stack_allocator_concept"><code><phrase role="identifier">StackAllocator</phrase></code></link><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">fiber</phrase><phrase role="special">(</phrase> <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><phrase role="special">,</phrase> <phrase role="identifier">StackAllocator</phrase> <phrase role="special">&amp;&amp;,</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="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <link linkend="stack_allocator_concept"><code><phrase role="identifier">StackAllocator</phrase></code></link><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">fiber</phrase><phrase role="special">(</phrase> <link linkend="class_launch"><code><phrase role="identifier">launch</phrase></code></link><phrase role="special">,</phrase> <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><phrase role="special">,</phrase> <phrase role="identifier">StackAllocator</phrase> <phrase role="special">&amp;&amp;,</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="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="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="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="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="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="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">void</phrase> <phrase role="identifier">join</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">fiber</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;)</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">fiber</phrase> <phrase role="special">&amp;)</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="keyword">noexcept</phrase><phrase role="special">;</phrase>

<phrase role="keyword">bool</phrase> <phrase role="identifier">has_ready_fibers</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</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="keyword">constexpr</phrase> <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="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">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">fiber</phrase><phrase role="special">(</phrase> <link linkend="class_launch"><code><phrase role="identifier">launch</phrase></code></link> <phrase role="identifier">policy</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> <link linkend="stack_allocator_concept"><code><phrase role="identifier">StackAllocator</phrase></code></link><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">fiber</phrase><phrase role="special">(</phrase> <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><phrase role="special">,</phrase> <phrase role="identifier">StackAllocator</phrase> <phrase role="special">&amp;&amp;</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="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <link linkend="stack_allocator_concept"><code><phrase role="identifier">StackAllocator</phrase></code></link><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">fiber</phrase><phrase role="special">(</phrase> <link linkend="class_launch"><code><phrase role="identifier">launch</phrase></code></link> <phrase role="identifier">policy</phrase><phrase role="special">,</phrase> <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><phrase role="special">,</phrase> <phrase role="identifier">StackAllocator</phrase> <phrase role="special">&amp;&amp;</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. If <link linkend="class_launch"><code>launch</code></link> is
              specified (or defaulted) to <code><phrase role="identifier">post</phrase></code>,
              the new fiber is marked <quote>ready</quote> and will be entered at
              the next opportunity. If <code><phrase role="identifier">launch</phrase></code>
              is specified as <code><phrase role="identifier">dispatch</phrase></code>,
              the calling fiber is suspended and the new fiber is entered immediately.
            </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_error</phrase></code> if an error
              occurs.
            </para>
          </listitem>
        </varlistentry>
        <varlistentry>
          <term>Note:</term>
          <listitem>
            <para>
              <link linkend="stack_allocator_concept"><code><phrase role="identifier">StackAllocator</phrase></code></link>
              is required to allocate a stack for the internal __econtext__. If
              <code><phrase role="identifier">StackAllocator</phrase></code> is not
              explicitly passed, the default stack allocator depends on <code><phrase
              role="identifier">BOOST_USE_SEGMENTED_STACKS</phrase></code>: if defined,
              you will get a <link linkend="class_segmented_stack"><code>segmented_stack</code></link>, else a <link linkend="class_fixedsize_stack"><code>fixedsize_stack</code></link>.
            </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>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
              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>
      </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_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>
      </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">fiber_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_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_algorithm_with_properties"><code>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">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_algorithm_with_properties"><code>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_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_for_fiber_bridgehead">
  <phrase id="swap_for_fiber"/>
  <link linkend="swap_for_fiber">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>
        <varlistentry>
          <term>Throws:</term>
          <listitem>
            <para>
              Nothing
            </para>
          </listitem>
        </varlistentry>
      </variablelist>
      <para>
        <bridgehead renderas="sect4" id="operator&lt;_bridgehead">
  <phrase id="operator&lt;"/>
  <link linkend="operator&lt;">Non-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">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>
</programlisting>
      <variablelist>
        <title></title>
        <varlistentry>
          <term>Returns:</term>
          <listitem>
            <para>
              <code><phrase role="keyword">true</phrase></code> if <code><phrase
              role="identifier">l</phrase><phrase role="special">.</phrase><phrase
              role="identifier">get_id</phrase><phrase role="special">()</phrase>
              <phrase role="special">&lt;</phrase> <phrase role="identifier">r</phrase><phrase
              role="special">.</phrase><phrase role="identifier">get_id</phrase><phrase
              role="special">()</phrase></code> is <code><phrase role="keyword">true</phrase></code>,
              false otherwise.
            </para>
          </listitem>
        </varlistentry>
        <varlistentry>
          <term>Throws:</term>
          <listitem>
            <para>
              Nothing.
            </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> <phrase role="keyword">noexcept</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_algorithm"><code>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="has_ready_fibers_bridgehead">
  <phrase id="has_ready_fibers"/>
  <link linkend="has_ready_fibers">Non-member function
        <code>has_ready_fibers()</code></link>
</bridgehead>
      </para>
<programlisting><phrase role="keyword">bool</phrase> <phrase role="identifier">has_ready_fibers</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 scheduler has
              fibers ready to run.
            </para>
          </listitem>
        </varlistentry>
        <varlistentry>
          <term>Throws:</term>
          <listitem>
            <para>
              Nothing
            </para>
          </listitem>
        </varlistentry>
        <varlistentry>
          <term>Note:</term>
          <listitem>
            <para>
              Can be used for work-stealing to find an idle scheduler.
            </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">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">id</phrase> <phrase role="special">{</phrase>
<phrase role="keyword">public</phrase><phrase role="special">:</phrase>
    <phrase role="keyword">constexpr</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="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="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="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="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="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="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">id</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;);</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="keyword">constexpr</phrase> <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>. The representation
              is unspecified.
            </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>
      <para>
        In general, <code><phrase role="identifier">this_fiber</phrase></code> operations
        may be called from the <quote>main</quote> fiber &mdash; the fiber on which function
        <code><phrase role="identifier">main</phrase><phrase role="special">()</phrase></code>
        is entered &mdash; as well as from an explicitly-launched thread&#8217;s thread-function.
        That is, in many respects the main fiber on each thread can be treated like
        an explicitly-launched fiber.
      </para>
<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">noexcept</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="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="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>
</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="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="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="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">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">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="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>
              timeout-related exceptions.
            </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>
        <varlistentry>
          <term>Note:</term>
          <listitem>
            <para>
              <quote>timeout-related exceptions</quote> are as defined in the C++
              Standard, section <emphasis role="bold">30.2.4 Timing specifications
              [thread.req.timing]</emphasis>: <quote>A function that takes an argument
              which specifies a timeout will throw if, during its execution, a clock,
              time point, or time duration throws an exception. Such exceptions are
              referred to as <emphasis>timeout-related exceptions.</emphasis></quote>
            </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">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">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>

<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>
              timeout-related exceptions.
            </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">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">void</phrase> <phrase role="identifier">yield</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>

<phrase role="special">}}</phrase>
</programlisting>
      <variablelist>
        <title></title>
        <varlistentry>
          <term>Effects:</term>
          <listitem>
            <para>
              Relinquishes execution control, allowing other fibers to run.
            </para>
          </listitem>
        </varlistentry>
        <varlistentry>
          <term>Throws:</term>
          <listitem>
            <para>
              Nothing.
            </para>
          </listitem>
        </varlistentry>
        <varlistentry>
          <term>Note:</term>
          <listitem>
            <para>
              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">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">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>
</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_algorithm_with_properties"><code>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 an <code><phrase
              role="identifier">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_algorithm_with_properties"><code>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>
    </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. Different threads in a process may use different
      schedulers. 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_algorithm"><code>algorithm</code></link> subclass.
      For the most part, your <code><phrase role="identifier">algorithm</phrase></code>
      subclass need not defend against cross-thread calls: the fiber manager intercepts
      and defers such calls. Most <code><phrase role="identifier">algorithm</phrase></code>
      methods are only ever directly called from the thread whose fibers it is managing
      &mdash; with exceptions as documented below.
    </para>
    <para>
      Your <code><phrase role="identifier">algorithm</phrase></code> subclass is
      engaged on a particular thread by calling <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_algorithm"><code>algorithm</code></link>. <emphasis
      role="bold">Boost.Fiber</emphasis> provides schedulers: <link linkend="class_round_robin"><code>round_robin</code></link>,
      <link linkend="class_work_stealing"><code>work_stealing</code></link>, <link linkend="class_numa_work_stealing"><code>numa::work_stealing</code></link> and
      <link linkend="class_shared_work"><code>shared_work</code></link>.
    </para>
<programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">thread</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">uint32_t</phrase> <phrase role="identifier">thread_count</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
    <phrase role="comment">// thread registers itself at work-stealing scheduler</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">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">algo</phrase><phrase role="special">::</phrase><phrase role="identifier">work_stealing</phrase> <phrase role="special">&gt;(</phrase> <phrase role="identifier">thread_count</phrase><phrase role="special">);</phrase>
    <phrase role="special">...</phrase>
<phrase role="special">}</phrase>

<phrase role="comment">// count of logical cpus</phrase>
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">uint32_t</phrase> <phrase role="identifier">thread_count</phrase> <phrase role="special">=</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">thread</phrase><phrase role="special">::</phrase><phrase role="identifier">hardware_concurrency</phrase><phrase role="special">();</phrase>
<phrase role="comment">// start worker-threads first</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">thread</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">threads</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">uint32_t</phrase> <phrase role="identifier">i</phrase> <phrase role="special">=</phrase> <phrase role="number">1</phrase> <phrase role="comment">/* count start-thread */</phrase><phrase role="special">;</phrase> <phrase role="identifier">i</phrase> <phrase role="special">&lt;</phrase> <phrase role="identifier">thread_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">// spawn thread</phrase>
    <phrase role="identifier">threads</phrase><phrase role="special">.</phrase><phrase role="identifier">emplace_back</phrase><phrase role="special">(</phrase> <phrase role="identifier">thread</phrase><phrase role="special">,</phrase> <phrase role="identifier">thread_count</phrase><phrase role="special">);</phrase>
<phrase role="special">}</phrase>
<phrase role="comment">// start-thread registers itself at work-stealing scheduler</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">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">algo</phrase><phrase role="special">::</phrase><phrase role="identifier">work_stealing</phrase> <phrase role="special">&gt;(</phrase> <phrase role="identifier">thread_count</phrase><phrase role="special">);</phrase>
<phrase role="special">...</phrase>
</programlisting>
    <para>
      The example spawns as many threads as <code><phrase role="identifier">std</phrase><phrase
      role="special">::</phrase><phrase role="identifier">thread</phrase><phrase
      role="special">::</phrase><phrase role="identifier">hardware_concurrency</phrase><phrase
      role="special">()</phrase></code> returns. Each thread runs a <link linkend="class_work_stealing"><code>work_stealing</code></link> scheduler.
      Each instance of this scheduler needs to know how many threads run the work-stealing
      scheduler in the program. If the local queue of one thread runs out of ready
      fibers, the thread tries to steal a ready fiber from another thread running
      this scheduler.
    </para>
    <para>
      <bridgehead renderas="sect4" id="class_algorithm_bridgehead">
  <phrase id="class_algorithm"/>
  <link linkend="class_algorithm">Class <code>algorithm</code></link>
</bridgehead>
    </para>
    <para>
      <code><phrase role="identifier">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">algo</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">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">namespace</phrase> <phrase role="identifier">algo</phrase> <phrase role="special">{</phrase>

<phrase role="keyword">struct</phrase> <phrase role="identifier">algorithm</phrase> <phrase role="special">{</phrase>
    <phrase role="keyword">virtual</phrase> <phrase role="special">~</phrase><phrase role="identifier">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">noexcept</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">noexcept</phrase> <phrase role="special">=</phrase> <phrase role="number">0</phrase><phrase role="special">;</phrase>

    <phrase role="keyword">virtual</phrase> <phrase role="keyword">bool</phrase> <phrase role="identifier">has_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="keyword">virtual</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">suspend_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">steady_clock</phrase><phrase role="special">::</phrase><phrase role="identifier">time_point</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;)</phrase> <phrase role="keyword">noexcept</phrase> <phrase role="special">=</phrase> <phrase role="number">0</phrase><phrase role="special">;</phrase>

    <phrase role="keyword">virtual</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">notify</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase> <phrase role="special">=</phrase> <phrase role="number">0</phrase><phrase role="special">;</phrase>
<phrase role="special">};</phrase>

<phrase role="special">}}}</phrase>
</programlisting>
    <para>
      <bridgehead renderas="sect4" id="algorithm_awakened_bridgehead">
  <phrase id="algorithm_awakened"/>
  <link linkend="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="keyword">noexcept</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="algorithm_pick_next_bridgehead">
  <phrase id="algorithm_pick_next"/>
  <link linkend="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="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 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="algorithm_has_ready_fibers_bridgehead">
  <phrase id="algorithm_has_ready_fibers"/>
  <link linkend="algorithm_has_ready_fibers">Member
      function <code>has_ready_fibers</code>()</link>
</bridgehead>
    </para>
<programlisting><phrase role="keyword">virtual</phrase> <phrase role="keyword">bool</phrase> <phrase role="identifier">has_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>
            <code><phrase role="keyword">true</phrase></code> if scheduler has fibers
            ready to run.
          </para>
        </listitem>
      </varlistentry>
    </variablelist>
    <para>
      <bridgehead renderas="sect4" id="algorithm_suspend_until_bridgehead">
  <phrase id="algorithm_suspend_until"/>
  <link linkend="algorithm_suspend_until">Member
      function <code>suspend_until</code>()</link>
</bridgehead>
    </para>
<programlisting><phrase role="keyword">virtual</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">suspend_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">steady_clock</phrase><phrase role="special">::</phrase><phrase role="identifier">time_point</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">abs_time</phrase><phrase role="special">)</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>Effects:</term>
        <listitem>
          <para>
            Informs the scheduler that no fiber will be ready until time-point <code><phrase
            role="identifier">abs_time</phrase></code>.
          </para>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term>Note:</term>
        <listitem>
          <para>
            This method allows a custom scheduler to yield control to the containing
            environment in whatever way makes sense. The fiber manager is stating
            that <code><phrase role="identifier">suspend_until</phrase><phrase role="special">()</phrase></code>
            need not return until <code><phrase role="identifier">abs_time</phrase></code>
            &mdash; or <link linkend="algorithm_notify"><code>algorithm::notify()</code></link> is called &mdash; whichever comes first.
            The interaction with <code><phrase role="identifier">notify</phrase><phrase
            role="special">()</phrase></code> means that, for instance, calling
            <ulink url="http://en.cppreference.com/w/cpp/thread/sleep_until"><code><phrase
            role="identifier">std</phrase><phrase role="special">::</phrase><phrase
            role="identifier">this_thread</phrase><phrase role="special">::</phrase><phrase
            role="identifier">sleep_until</phrase><phrase role="special">(</phrase><phrase
            role="identifier">abs_time</phrase><phrase role="special">)</phrase></code></ulink>
            would be too simplistic. <link linkend="round_robin_suspend_until"><code>round_robin::suspend_until()</code></link> uses
            a <ulink url="http://en.cppreference.com/w/cpp/thread/condition_variable"><code><phrase
            role="identifier">std</phrase><phrase role="special">::</phrase><phrase
            role="identifier">condition_variable</phrase></code></ulink> to coordinate
            with <link linkend="round_robin_notify"><code>round_robin::notify()</code></link>.
          </para>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term>Note:</term>
        <listitem>
          <para>
            Given that <code><phrase role="identifier">notify</phrase><phrase role="special">()</phrase></code>
            might be called from another thread, your <code><phrase role="identifier">suspend_until</phrase><phrase
            role="special">()</phrase></code> implementation &mdash; like the rest of your
            <code><phrase role="identifier">algorithm</phrase></code> implementation
            &mdash; must guard any data it shares with your <code><phrase role="identifier">notify</phrase><phrase
            role="special">()</phrase></code> implementation.
          </para>
        </listitem>
      </varlistentry>
    </variablelist>
    <para>
      <bridgehead renderas="sect4" id="algorithm_notify_bridgehead">
  <phrase id="algorithm_notify"/>
  <link linkend="algorithm_notify">Member function
      <code>notify</code>()</link>
</bridgehead>
    </para>
<programlisting><phrase role="keyword">virtual</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">notify</phrase><phrase role="special">()</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>Effects:</term>
        <listitem>
          <para>
            Requests the scheduler to return from a pending call to <link linkend="algorithm_suspend_until"><code>algorithm::suspend_until()</code></link>.
          </para>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term>Note:</term>
        <listitem>
          <para>
            Alone among the <code><phrase role="identifier">algorithm</phrase></code>
            methods, <code><phrase role="identifier">notify</phrase><phrase role="special">()</phrase></code>
            may be called from another thread. Your <code><phrase role="identifier">notify</phrase><phrase
            role="special">()</phrase></code> implementation must guard any data
            it shares with the rest of your <code><phrase role="identifier">algorithm</phrase></code>
            implementation.
          </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_algorithm"><code>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">algo</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">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">namespace</phrase> <phrase role="identifier">algo</phrase> <phrase role="special">{</phrase>

<phrase role="keyword">class</phrase> <phrase role="identifier">round_robin</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <phrase role="identifier">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">noexcept</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">noexcept</phrase><phrase role="special">;</phrase>

    <phrase role="keyword">virtual</phrase> <phrase role="keyword">bool</phrase> <phrase role="identifier">has_ready_fibers</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>

    <phrase role="keyword">virtual</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">suspend_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">steady_clock</phrase><phrase role="special">::</phrase><phrase role="identifier">time_point</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>

    <phrase role="keyword">virtual</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">notify</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</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> <phrase role="keyword">noexcept</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>
      <varlistentry>
        <term>Throws:</term>
        <listitem>
          <para>
            Nothing.
          </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> <phrase role="keyword">noexcept</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 <code><phrase role="keyword">nullptr</phrase></code>
            if the queue is empty.
          </para>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term>Throws:</term>
        <listitem>
          <para>
            Nothing.
          </para>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term>Note:</term>
        <listitem>
          <para>
            Placing ready fibers onto the tail of 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_has_ready_fibers_bridgehead">
  <phrase id="round_robin_has_ready_fibers"/>
  <link linkend="round_robin_has_ready_fibers">Member
      function <code>has_ready_fibers</code>()</link>
</bridgehead>
    </para>
<programlisting><phrase role="keyword">virtual</phrase> <phrase role="keyword">bool</phrase> <phrase role="identifier">has_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>
            <code><phrase role="keyword">true</phrase></code> if scheduler has fibers
            ready to run.
          </para>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term>Throws:</term>
        <listitem>
          <para>
            Nothing.
          </para>
        </listitem>
      </varlistentry>
    </variablelist>
    <para>
      <bridgehead renderas="sect4" id="round_robin_suspend_until_bridgehead">
  <phrase id="round_robin_suspend_until"/>
  <link linkend="round_robin_suspend_until">Member
      function <code>suspend_until</code>()</link>
</bridgehead>
    </para>
<programlisting><phrase role="keyword">virtual</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">suspend_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">steady_clock</phrase><phrase role="special">::</phrase><phrase role="identifier">time_point</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">abs_time</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
</programlisting>
    <variablelist>
      <title></title>
      <varlistentry>
        <term>Effects:</term>
        <listitem>
          <para>
            Informs <code><phrase role="identifier">round_robin</phrase></code> that
            no ready fiber will be available until time-point <code><phrase role="identifier">abs_time</phrase></code>.
            This implementation blocks in <ulink url="http://en.cppreference.com/w/cpp/thread/condition_variable/wait_until"><code><phrase
            role="identifier">std</phrase><phrase role="special">::</phrase><phrase
            role="identifier">condition_variable</phrase><phrase role="special">::</phrase><phrase
            role="identifier">wait_until</phrase><phrase role="special">()</phrase></code></ulink>.
          </para>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term>Throws:</term>
        <listitem>
          <para>
            Nothing.
          </para>
        </listitem>
      </varlistentry>
    </variablelist>
    <para>
      <bridgehead renderas="sect4" id="round_robin_notify_bridgehead">
  <phrase id="round_robin_notify"/>
  <link linkend="round_robin_notify">Member function
      <code>notify</code>()</link>
</bridgehead>
    </para>
<programlisting><phrase role="keyword">virtual</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">notify</phrase><phrase role="special">()</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>Effects:</term>
        <listitem>
          <para>
            Wake up a pending call to <link linkend="round_robin_suspend_until"><code>round_robin::suspend_until()</code></link>,
            some fibers might be ready. This implementation wakes <code><phrase role="identifier">suspend_until</phrase><phrase
            role="special">()</phrase></code> via <ulink url="http://en.cppreference.com/w/cpp/thread/condition_variable/notify_all"><code><phrase
            role="identifier">std</phrase><phrase role="special">::</phrase><phrase
            role="identifier">condition_variable</phrase><phrase role="special">::</phrase><phrase
            role="identifier">notify_all</phrase><phrase role="special">()</phrase></code></ulink>.
          </para>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term>Throws:</term>
        <listitem>
          <para>
            Nothing.
          </para>
        </listitem>
      </varlistentry>
    </variablelist>
    <para>
      <bridgehead renderas="sect4" id="class_work_stealing_bridgehead">
  <phrase id="class_work_stealing"/>
  <link linkend="class_work_stealing">Class <code>work_stealing</code></link>
</bridgehead>
    </para>
    <para>
      This class implements <link linkend="class_algorithm"><code>algorithm</code></link>; if the local ready-queue runs
      out of ready fibers, ready fibers are stolen from other schedulers.<sbr/> The
      victim scheduler (from which a ready fiber is stolen) is selected at random.
    </para>
    <note>
      <para>
        Worker-threads are stored in a static variable, dynamically adding/removing
        worker threads is not supported.
      </para>
    </note>
<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">algo</phrase><phrase role="special">/</phrase><phrase role="identifier">work_stealing</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">namespace</phrase> <phrase role="identifier">algo</phrase> <phrase role="special">{</phrase>

<phrase role="keyword">class</phrase> <phrase role="identifier">work_stealing</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <phrase role="identifier">algorithm</phrase> <phrase role="special">{</phrase>
<phrase role="keyword">public</phrase><phrase role="special">:</phrase>
    <phrase role="identifier">work_stealing</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">uint32_t</phrase> <phrase role="identifier">thread_count</phrase><phrase role="special">,</phrase> <phrase role="keyword">bool</phrase> <phrase role="identifier">suspend</phrase> <phrase role="special">=</phrase> <phrase role="keyword">false</phrase><phrase role="special">);</phrase>

    <phrase role="identifier">work_stealing</phrase><phrase role="special">(</phrase> <phrase role="identifier">work_stealing</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">work_stealing</phrase><phrase role="special">(</phrase> <phrase role="identifier">work_stealing</phrase> <phrase role="special">&amp;&amp;)</phrase> <phrase role="special">=</phrase> <phrase role="keyword">delete</phrase><phrase role="special">;</phrase>

    <phrase role="identifier">work_stealing</phrase> <phrase role="special">&amp;</phrase> <phrase role="keyword">operator</phrase><phrase role="special">=(</phrase> <phrase role="identifier">work_stealing</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">work_stealing</phrase> <phrase role="special">&amp;</phrase> <phrase role="keyword">operator</phrase><phrase role="special">=(</phrase> <phrase role="identifier">work_stealing</phrase> <phrase role="special">&amp;&amp;)</phrase> <phrase role="special">=</phrase> <phrase role="keyword">delete</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">noexcept</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">noexcept</phrase><phrase role="special">;</phrase>

    <phrase role="keyword">virtual</phrase> <phrase role="keyword">bool</phrase> <phrase role="identifier">has_ready_fibers</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>

    <phrase role="keyword">virtual</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">suspend_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">steady_clock</phrase><phrase role="special">::</phrase><phrase role="identifier">time_point</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>

    <phrase role="keyword">virtual</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">notify</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
<phrase role="special">};</phrase>

<phrase role="special">}}}</phrase>
</programlisting>
    <bridgehead renderas="sect3" id="fiber.scheduling.h0">
      <phrase id="fiber.scheduling.constructor"/><link linkend="fiber.scheduling.constructor">Constructor</link>
    </bridgehead>
<programlisting><phrase role="identifier">work_stealing</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">uint32_t</phrase> <phrase role="identifier">thread_count</phrase><phrase role="special">,</phrase> <phrase role="keyword">bool</phrase> <phrase role="identifier">suspend</phrase> <phrase role="special">=</phrase> <phrase role="keyword">false</phrase><phrase role="special">);</phrase>
</programlisting>
    <variablelist>
      <title></title>
      <varlistentry>
        <term>Effects:</term>
        <listitem>
          <para>
            Constructs work-stealing scheduling algorithm. <code><phrase role="identifier">thread_count</phrase></code>
            represents the number of threads running this algorithm.
          </para>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term>Throws:</term>
        <listitem>
          <para>
            <code><phrase role="identifier">system_error</phrase></code>
          </para>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term>Note:</term>
        <listitem>
          <para>
            If <code><phrase role="identifier">suspend</phrase></code> is set to
            <code><phrase role="keyword">true</phrase></code>, then the scheduler
            suspends if no ready fiber could be stolen. The scheduler will by woken
            up if a sleeping fiber times out or it was notified from remote (other
            thread or fiber scheduler).
          </para>
        </listitem>
      </varlistentry>
    </variablelist>
    <para>
      <bridgehead renderas="sect4" id="work_stealing_awakened_bridgehead">
  <phrase id="work_stealing_awakened"/>
  <link linkend="work_stealing_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="keyword">noexcept</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
            the shared ready queue.
          </para>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term>Throws:</term>
        <listitem>
          <para>
            Nothing.
          </para>
        </listitem>
      </varlistentry>
    </variablelist>
    <para>
      <bridgehead renderas="sect4" id="work_stealing_pick_next_bridgehead">
  <phrase id="work_stealing_pick_next"/>
  <link linkend="work_stealing_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="keyword">noexcept</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 <code><phrase role="keyword">nullptr</phrase></code>
            if the queue is empty.
          </para>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term>Throws:</term>
        <listitem>
          <para>
            Nothing.
          </para>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term>Note:</term>
        <listitem>
          <para>
            Placing ready fibers onto the tail of the sahred 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="work_stealing_has_ready_fibers_bridgehead">
  <phrase id="work_stealing_has_ready_fibers"/>
  <link linkend="work_stealing_has_ready_fibers">Member
      function <code>has_ready_fibers</code>()</link>
</bridgehead>
    </para>
<programlisting><phrase role="keyword">virtual</phrase> <phrase role="keyword">bool</phrase> <phrase role="identifier">has_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>
            <code><phrase role="keyword">true</phrase></code> if scheduler has fibers
            ready to run.
          </para>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term>Throws:</term>
        <listitem>
          <para>
            Nothing.
          </para>
        </listitem>
      </varlistentry>
    </variablelist>
    <para>
      <bridgehead renderas="sect4" id="work_stealing_suspend_until_bridgehead">
  <phrase id="work_stealing_suspend_until"/>
  <link linkend="work_stealing_suspend_until">Member
      function <code>suspend_until</code>()</link>
</bridgehead>
    </para>
<programlisting><phrase role="keyword">virtual</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">suspend_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">steady_clock</phrase><phrase role="special">::</phrase><phrase role="identifier">time_point</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">abs_time</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
</programlisting>
    <variablelist>
      <title></title>
      <varlistentry>
        <term>Effects:</term>
        <listitem>
          <para>
            Informs <code><phrase role="identifier">work_stealing</phrase></code>
            that no ready fiber will be available until time-point <code><phrase
            role="identifier">abs_time</phrase></code>. This implementation blocks
            in <ulink url="http://en.cppreference.com/w/cpp/thread/condition_variable/wait_until"><code><phrase
            role="identifier">std</phrase><phrase role="special">::</phrase><phrase
            role="identifier">condition_variable</phrase><phrase role="special">::</phrase><phrase
            role="identifier">wait_until</phrase><phrase role="special">()</phrase></code></ulink>.
          </para>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term>Throws:</term>
        <listitem>
          <para>
            Nothing.
          </para>
        </listitem>
      </varlistentry>
    </variablelist>
    <para>
      <bridgehead renderas="sect4" id="work_stealing_notify_bridgehead">
  <phrase id="work_stealing_notify"/>
  <link linkend="work_stealing_notify">Member
      function <code>notify</code>()</link>
</bridgehead>
    </para>
<programlisting><phrase role="keyword">virtual</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">notify</phrase><phrase role="special">()</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>Effects:</term>
        <listitem>
          <para>
            Wake up a pending call to <link linkend="work_stealing_suspend_until"><code>work_stealing::suspend_until()</code></link>,
            some fibers might be ready. This implementation wakes <code><phrase role="identifier">suspend_until</phrase><phrase
            role="special">()</phrase></code> via <ulink url="http://en.cppreference.com/w/cpp/thread/condition_variable/notify_all"><code><phrase
            role="identifier">std</phrase><phrase role="special">::</phrase><phrase
            role="identifier">condition_variable</phrase><phrase role="special">::</phrase><phrase
            role="identifier">notify_all</phrase><phrase role="special">()</phrase></code></ulink>.
          </para>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term>Throws:</term>
        <listitem>
          <para>
            Nothing.
          </para>
        </listitem>
      </varlistentry>
    </variablelist>
    <para>
      <bridgehead renderas="sect4" id="class_shared_work_bridgehead">
  <phrase id="class_shared_work"/>
  <link linkend="class_shared_work">Class <code>shared_work</code></link>
</bridgehead>
    </para>
    <note>
      <para>
        Because of the non-locality of data, <emphasis>shared_work</emphasis> is
        less performant than <link linkend="class_work_stealing"><code>work_stealing</code></link>.
      </para>
    </note>
    <para>
      This class implements <link linkend="class_algorithm"><code>algorithm</code></link>, scheduling fibers in round-robin
      fashion. Ready fibers are shared between all instances (running on different
      threads) of shared_work, thus the work is distributed equally over all threads.
    </para>
    <note>
      <para>
        Worker-threads are stored in a static variable, dynamically adding/removing
        worker threads is not supported.
      </para>
    </note>
<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">algo</phrase><phrase role="special">/</phrase><phrase role="identifier">shared_work</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">namespace</phrase> <phrase role="identifier">algo</phrase> <phrase role="special">{</phrase>

<phrase role="keyword">class</phrase> <phrase role="identifier">shared_work</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <phrase role="identifier">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">noexcept</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">noexcept</phrase><phrase role="special">;</phrase>

    <phrase role="keyword">virtual</phrase> <phrase role="keyword">bool</phrase> <phrase role="identifier">has_ready_fibers</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>

    <phrase role="keyword">virtual</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">suspend_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">steady_clock</phrase><phrase role="special">::</phrase><phrase role="identifier">time_point</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>

    <phrase role="keyword">virtual</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">notify</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
<phrase role="special">};</phrase>

<phrase role="special">}}}</phrase>
</programlisting>
    <para>
      <bridgehead renderas="sect4" id="shared_work_awakened_bridgehead">
  <phrase id="shared_work_awakened"/>
  <link linkend="shared_work_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="keyword">noexcept</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
            the shared ready queue.
          </para>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term>Throws:</term>
        <listitem>
          <para>
            Nothing.
          </para>
        </listitem>
      </varlistentry>
    </variablelist>
    <para>
      <bridgehead renderas="sect4" id="shared_work_pick_next_bridgehead">
  <phrase id="shared_work_pick_next"/>
  <link linkend="shared_work_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="keyword">noexcept</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 <code><phrase role="keyword">nullptr</phrase></code>
            if the queue is empty.
          </para>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term>Throws:</term>
        <listitem>
          <para>
            Nothing.
          </para>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term>Note:</term>
        <listitem>
          <para>
            Placing ready fibers onto the tail of the shared 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="shared_work_has_ready_fibers_bridgehead">
  <phrase id="shared_work_has_ready_fibers"/>
  <link linkend="shared_work_has_ready_fibers">Member
      function <code>has_ready_fibers</code>()</link>
</bridgehead>
    </para>
<programlisting><phrase role="keyword">virtual</phrase> <phrase role="keyword">bool</phrase> <phrase role="identifier">has_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>
            <code><phrase role="keyword">true</phrase></code> if scheduler has fibers
            ready to run.
          </para>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term>Throws:</term>
        <listitem>
          <para>
            Nothing.
          </para>
        </listitem>
      </varlistentry>
    </variablelist>
    <para>
      <bridgehead renderas="sect4" id="shared_work_suspend_until_bridgehead">
  <phrase id="shared_work_suspend_until"/>
  <link linkend="shared_work_suspend_until">Member
      function <code>suspend_until</code>()</link>
</bridgehead>
    </para>
<programlisting><phrase role="keyword">virtual</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">suspend_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">steady_clock</phrase><phrase role="special">::</phrase><phrase role="identifier">time_point</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">abs_time</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
</programlisting>
    <variablelist>
      <title></title>
      <varlistentry>
        <term>Effects:</term>
        <listitem>
          <para>
            Informs <code><phrase role="identifier">shared_work</phrase></code> that
            no ready fiber will be available until time-point <code><phrase role="identifier">abs_time</phrase></code>.
            This implementation blocks in <ulink url="http://en.cppreference.com/w/cpp/thread/condition_variable/wait_until"><code><phrase
            role="identifier">std</phrase><phrase role="special">::</phrase><phrase
            role="identifier">condition_variable</phrase><phrase role="special">::</phrase><phrase
            role="identifier">wait_until</phrase><phrase role="special">()</phrase></code></ulink>.
          </para>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term>Throws:</term>
        <listitem>
          <para>
            Nothing.
          </para>
        </listitem>
      </varlistentry>
    </variablelist>
    <para>
      <bridgehead renderas="sect4" id="shared_work_notify_bridgehead">
  <phrase id="shared_work_notify"/>
  <link linkend="shared_work_notify">Member function
      <code>notify</code>()</link>
</bridgehead>
    </para>
<programlisting><phrase role="keyword">virtual</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">notify</phrase><phrase role="special">()</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>Effects:</term>
        <listitem>
          <para>
            Wake up a pending call to <link linkend="shared_work_suspend_until"><code>shared_work::suspend_until()</code></link>,
            some fibers might be ready. This implementation wakes <code><phrase role="identifier">suspend_until</phrase><phrase
            role="special">()</phrase></code> via <ulink url="http://en.cppreference.com/w/cpp/thread/condition_variable/notify_all"><code><phrase
            role="identifier">std</phrase><phrase role="special">::</phrase><phrase
            role="identifier">condition_variable</phrase><phrase role="special">::</phrase><phrase
            role="identifier">notify_all</phrase><phrase role="special">()</phrase></code></ulink>.
          </para>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term>Throws:</term>
        <listitem>
          <para>
            Nothing.
          </para>
        </listitem>
      </varlistentry>
    </variablelist>
    <bridgehead renderas="sect3" id="fiber.scheduling.h1">
      <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_algorithm"><code>algorithm</code></link> can use any
      information available from <link linkend="class_context"><code>context</code></link> to implement the <code><phrase
      role="identifier">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&#8217;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">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_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="keyword">noexcept</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="keyword">protected</phrase><phrase role="special">:</phrase>
    <phrase role="keyword">void</phrase> <phrase role="identifier">notify</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
<phrase role="special">};</phrase>

<phrase role="special">}}</phrase>
</programlisting>
    <bridgehead renderas="sect3" id="fiber.scheduling.h2">
      <phrase id="fiber.scheduling.constructor0"/><link linkend="fiber.scheduling.constructor0">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> <phrase role="keyword">noexcept</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>Throws:</term>
        <listitem>
          <para>
            Nothing.
          </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> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
</programlisting>
    <variablelist>
      <title></title>
      <varlistentry>
        <term>Effects:</term>
        <listitem>
          <para>
            Pass control to the custom <link linkend="class_algorithm_with_properties"><code>algorithm_with_properties&lt;&gt;</code></link> subclass&#8217;s
            <link linkend="algorithm_with_properties_property_change"><code>algorithm_with_properties::property_change()</code></link> method.
          </para>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term>Throws:</term>
        <listitem>
          <para>
            Nothing.
          </para>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term>Note:</term>
        <listitem>
          <para>
            A custom scheduler&#8217;s <link linkend="algorithm_with_properties_pick_next"><code>algorithm_with_properties::pick_next()</code></link> method
            might dynamically select from the ready fibers, or <link linkend="algorithm_with_properties_awakened"><code>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&#8217;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&#8217;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_algorithm_with_properties_bridgehead">
  <phrase id="class_algorithm_with_properties"/>
  <link linkend="class_algorithm_with_properties">Template
      <code>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">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">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">namespace</phrase> <phrase role="identifier">algo</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">algorithm_with_properties</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="identifier">PROPS</phrase> <phrase role="special">&amp;)</phrase> <phrase role="keyword">noexcept</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">noexcept</phrase><phrase role="special">;</phrase>

    <phrase role="keyword">virtual</phrase> <phrase role="keyword">bool</phrase> <phrase role="identifier">has_ready_fibers</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>

    <phrase role="keyword">virtual</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">suspend_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">steady_clock</phrase><phrase role="special">::</phrase><phrase role="identifier">time_point</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;)</phrase> <phrase role="keyword">noexcept</phrase> <phrase role="special">=</phrase> <phrase role="number">0</phrase><phrase role="special">;</phrase>

    <phrase role="keyword">virtual</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">notify</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase> <phrase role="special">=</phrase> <phrase role="number">0</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="identifier">context</phrase> <phrase role="special">*)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</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">PROPS</phrase> <phrase role="special">&amp;)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</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="special">};</phrase>

<phrase role="special">}}}</phrase>
</programlisting>
    <para>
      <bridgehead renderas="sect4" id="algorithm_with_properties_awakened_bridgehead">
  <phrase id="algorithm_with_properties_awakened"/>
  <link linkend="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> <phrase role="keyword">noexcept</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="algorithm_awakened"><code>algorithm::awakened()</code></link>. Passes
            the fiber&#8217;s associated <code><phrase role="identifier">PROPS</phrase></code>
            instance.
          </para>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term>Throws:</term>
        <listitem>
          <para>
            Nothing.
          </para>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term>Note:</term>
        <listitem>
          <para>
            An <code><phrase role="identifier">algorithm_with_properties</phrase><phrase
            role="special">&lt;&gt;</phrase></code> subclass must override this method
            instead of <code><phrase role="identifier">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="algorithm_with_properties_pick_next_bridgehead">
  <phrase id="algorithm_with_properties_pick_next"/>
  <link linkend="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> <phrase role="keyword">noexcept</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>Throws:</term>
        <listitem>
          <para>
            Nothing.
          </para>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term>Note:</term>
        <listitem>
          <para>
            same as <link linkend="algorithm_pick_next"><code>algorithm::pick_next()</code></link>
          </para>
        </listitem>
      </varlistentry>
    </variablelist>
    <para>
      <bridgehead renderas="sect4" id="algorithm_with_properties_has_ready_fibers_bridgehead">
  <phrase id="algorithm_with_properties_has_ready_fibers"/>
  <link linkend="algorithm_with_properties_has_ready_fibers">Member
      function <code>has_ready_fibers</code>()</link>
</bridgehead>
    </para>
<programlisting><phrase role="keyword">virtual</phrase> <phrase role="keyword">bool</phrase> <phrase role="identifier">has_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>
            <code><phrase role="keyword">true</phrase></code> if scheduler has fibers
            ready to run.
          </para>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term>Throws:</term>
        <listitem>
          <para>
            Nothing.
          </para>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term>Note:</term>
        <listitem>
          <para>
            same as <link linkend="algorithm_has_ready_fibers"><code>algorithm::has_ready_fibers()</code></link>
          </para>
        </listitem>
      </varlistentry>
    </variablelist>
    <para>
      <bridgehead renderas="sect4" id="algorithm_with_properties_suspend_until_bridgehead">
  <phrase id="algorithm_with_properties_suspend_until"/>
  <link linkend="algorithm_with_properties_suspend_until">Member
      function <code>suspend_until</code>()</link>
</bridgehead>
    </para>
<programlisting><phrase role="keyword">virtual</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">suspend_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">steady_clock</phrase><phrase role="special">::</phrase><phrase role="identifier">time_point</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">abs_time</phrase><phrase role="special">)</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>Effects:</term>
        <listitem>
          <para>
            Informs the scheduler that no fiber will be ready until time-point <code><phrase
            role="identifier">abs_time</phrase></code>.
          </para>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term>Note:</term>
        <listitem>
          <para>
            same as <link linkend="algorithm_suspend_until"><code>algorithm::suspend_until()</code></link>
          </para>
        </listitem>
      </varlistentry>
    </variablelist>
    <para>
      <bridgehead renderas="sect4" id="algorithm_with_properties_notify_bridgehead">
  <phrase id="algorithm_with_properties_notify"/>
  <link linkend="algorithm_with_properties_notify">Member
      function <code>notify</code>()</link>
</bridgehead>
    </para>
<programlisting><phrase role="keyword">virtual</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">notify</phrase><phrase role="special">()</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>Effects:</term>
        <listitem>
          <para>
            Requests the scheduler to return from a pending call to <link linkend="algorithm_with_properties_suspend_until"><code>algorithm_with_properties::suspend_until()</code></link>.
          </para>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term>Note:</term>
        <listitem>
          <para>
            same as <link linkend="algorithm_notify"><code>algorithm::notify()</code></link>
          </para>
        </listitem>
      </varlistentry>
    </variablelist>
    <para>
      <bridgehead renderas="sect4" id="algorithm_with_properties_properties_bridgehead">
  <phrase id="algorithm_with_properties_properties"/>
  <link linkend="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> <phrase role="keyword">noexcept</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>Throws:</term>
        <listitem>
          <para>
            Nothing.
          </para>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term>Note:</term>
        <listitem>
          <para>
            The fiber&#8217;s associated <code><phrase role="identifier">PROPS</phrase></code>
            instance is already passed to <link linkend="algorithm_with_properties_awakened"><code>algorithm_with_properties::awakened()</code></link> and
            <link linkend="algorithm_with_properties_property_change"><code>algorithm_with_properties::property_change()</code></link>.
            However, every <link linkend="class_algorithm"><code>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="algorithm_with_properties_property_change_bridgehead">
  <phrase id="algorithm_with_properties_property_change"/>
  <link linkend="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> <phrase role="keyword">noexcept</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>Throws:</term>
        <listitem>
          <para>
            Nothing.
          </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="algorithm_with_properties_new_properties_bridgehead">
  <phrase id="algorithm_with_properties_new_properties"/>
  <link linkend="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">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>
      <anchor id="context"/><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>
      <anchor id="ready_queue_t"/>Of particular note is the fact that <code><phrase
      role="identifier">context</phrase></code> contains a hook to participate in
      a <ulink url="http://www.boost.org/doc/libs/release/doc/html/intrusive/list.html"><code><phrase
      role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">intrusive</phrase><phrase
      role="special">::</phrase><phrase role="identifier">list</phrase></code></ulink>
      <literal>typedef</literal>&#8217;ed as <code><phrase role="identifier">boost</phrase><phrase
      role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase
      role="special">::</phrase><phrase role="identifier">scheduler</phrase><phrase
      role="special">::</phrase><phrase role="identifier">ready_queue_t</phrase></code>.
      This hook is reserved for use by <link linkend="class_algorithm"><code>algorithm</code></link> implementations. (For
      instance, <link linkend="class_round_robin"><code>round_robin</code></link> contains a <code><phrase role="identifier">ready_queue_t</phrase></code>
      instance to manage its ready fibers.) See <link linkend="context_ready_is_linked"><code>context::ready_is_linked()</code></link>,
      <link linkend="context_ready_link"><code>context::ready_link()</code></link>, <link linkend="context_ready_unlink"><code>context::ready_unlink()</code></link>.
    </para>
    <para>
      Your <code><phrase role="identifier">algorithm</phrase></code> implementation
      may use any container you desire to manage passed <code><phrase role="identifier">context</phrase></code>
      instances. <code><phrase role="identifier">ready_queue_t</phrase></code> avoids
      some of the overhead of typical STL containers.
    </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">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">enum</phrase> <phrase role="keyword">class</phrase> <phrase role="identifier">type</phrase> <phrase role="special">{</phrase>
  <phrase role="identifier">none</phrase>               <phrase role="special">=</phrase> <emphasis>unspecified</emphasis><phrase role="special">,</phrase>
  <phrase role="identifier">main_context</phrase>       <phrase role="special">=</phrase> <emphasis>unspecified</emphasis><phrase role="special">,</phrase> <phrase role="comment">// fiber associated with thread's stack</phrase>
  <phrase role="identifier">dispatcher_context</phrase> <phrase role="special">=</phrase> <emphasis>unspecified</emphasis><phrase role="special">,</phrase> <phrase role="comment">// special fiber for maintenance operations</phrase>
  <phrase role="identifier">worker_context</phrase>     <phrase role="special">=</phrase> <emphasis>unspecified</emphasis><phrase role="special">,</phrase> <phrase role="comment">// fiber not special to the library</phrase>
  <phrase role="identifier">pinned_context</phrase>     <phrase role="special">=</phrase> <emphasis>unspecified</emphasis>  <phrase role="comment">// fiber must not be migrated to another thread</phrase>
<phrase role="special">};</phrase>

<phrase role="keyword">class</phrase> <phrase role="identifier">context</phrase> <phrase role="special">{</phrase>
<phrase role="keyword">public</phrase><phrase role="special">:</phrase>
    <phrase role="keyword">class</phrase> <phrase role="identifier">id</phrase><phrase role="special">;</phrase>

    <phrase role="keyword">static</phrase> <phrase role="identifier">context</phrase> <phrase role="special">*</phrase> <phrase role="identifier">active</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>

    <phrase role="identifier">context</phrase><phrase role="special">(</phrase> <phrase role="identifier">context</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">context</phrase> <phrase role="special">&amp;</phrase> <phrase role="keyword">operator</phrase><phrase role="special">=(</phrase> <phrase role="identifier">context</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">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">attach</phrase><phrase role="special">(</phrase> <phrase role="identifier">context</phrase> <phrase role="special">*)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>

    <phrase role="keyword">bool</phrase> <phrase role="identifier">is_context</phrase><phrase role="special">(</phrase> <phrase role="identifier">type</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="identifier">is_terminated</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="identifier">ready_is_linked</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="identifier">remote_ready_is_linked</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="identifier">wait_is_linked</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">List</phrase> <phrase role="special">&gt;</phrase>
    <phrase role="keyword">void</phrase> <phrase role="identifier">ready_link</phrase><phrase role="special">(</phrase> <phrase role="identifier">List</phrase> <phrase role="special">&amp;)</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">List</phrase> <phrase role="special">&gt;</phrase>
    <phrase role="keyword">void</phrase> <phrase role="identifier">remote_ready_link</phrase><phrase role="special">(</phrase> <phrase role="identifier">List</phrase> <phrase role="special">&amp;)</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">List</phrase> <phrase role="special">&gt;</phrase>
    <phrase role="keyword">void</phrase> <phrase role="identifier">wait_link</phrase><phrase role="special">(</phrase> <phrase role="identifier">List</phrase> <phrase role="special">&amp;)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>

    <phrase role="keyword">void</phrase> <phrase role="identifier">ready_unlink</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
    <phrase role="keyword">void</phrase> <phrase role="identifier">remote_ready_unlink</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
    <phrase role="keyword">void</phrase> <phrase role="identifier">wait_unlink</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>

    <phrase role="keyword">void</phrase> <phrase role="identifier">suspend</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
    <phrase role="keyword">void</phrase> <phrase role="identifier">schedule</phrase><phrase role="special">(</phrase> <phrase role="identifier">context</phrase> <phrase role="special">*)</phrase> <phrase role="keyword">noexcept</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">context</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">l</phrase><phrase role="special">,</phrase> <phrase role="identifier">context</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="special">}}</phrase>
</programlisting>
    <para>
      <bridgehead renderas="sect4" id="context_active_bridgehead">
  <phrase id="context_active"/>
  <link linkend="context_active">Static member function
      <code>active</code>()</link>
</bridgehead>
    </para>
<programlisting><phrase role="keyword">static</phrase> <phrase role="identifier">context</phrase> <phrase role="special">*</phrase> <phrase role="identifier">active</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
</programlisting>
    <variablelist>
      <title></title>
      <varlistentry>
        <term>Returns:</term>
        <listitem>
          <para>
            Pointer to instance of current fiber.
          </para>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term>Throws:</term>
        <listitem>
          <para>
            Nothing
          </para>
        </listitem>
      </varlistentry>
    </variablelist>
    <para>
      <bridgehead renderas="sect4" id="context_get_id_bridgehead">
  <phrase id="context_get_id"/>
  <link linkend="context_get_id">Member function <code>get_id</code>()</link>
</bridgehead>
    </para>
<programlisting><phrase role="identifier">context</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="fiber_get_id"><code>fiber::get_id()</code></link>
          </para>
        </listitem>
      </varlistentry>
    </variablelist>
    <para>
      <bridgehead renderas="sect4" id="context_attach_bridgehead">
  <phrase id="context_attach"/>
  <link linkend="context_attach">Member function <code>attach</code>()</link>
</bridgehead>
    </para>
<programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">attach</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">noexcept</phrase><phrase role="special">;</phrase>
</programlisting>
    <variablelist>
      <title></title>
      <varlistentry>
        <term>Precondition:</term>
        <listitem>
          <para>
            <code><phrase role="keyword">this</phrase><phrase role="special">-&gt;</phrase><phrase
            role="identifier">get_scheduler</phrase><phrase role="special">()</phrase>
            <phrase role="special">==</phrase> <phrase role="keyword">nullptr</phrase></code>
          </para>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term>Effects:</term>
        <listitem>
          <para>
            Attach fiber <code><phrase role="identifier">f</phrase></code> to scheduler
            running <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>.
          </para>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term>Postcondition:</term>
        <listitem>
          <para>
            <code><phrase role="keyword">this</phrase><phrase role="special">-&gt;</phrase><phrase
            role="identifier">get_scheduler</phrase><phrase role="special">()</phrase>
            <phrase role="special">!=</phrase> <phrase role="keyword">nullptr</phrase></code>
          </para>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term>Throws:</term>
        <listitem>
          <para>
            Nothing
          </para>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term>Note:</term>
        <listitem>
          <para>
            A typical call: <code><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">active</phrase><phrase
            role="special">()-&gt;</phrase><phrase role="identifier">attach</phrase><phrase
            role="special">(</phrase><phrase role="identifier">f</phrase><phrase
            role="special">);</phrase></code>
          </para>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term>Note:</term>
        <listitem>
          <para>
            <code><phrase role="identifier">f</phrase></code> must not be the running
            fiber&#8217;s context. It must not be <link linkend="blocking"><emphasis>blocked</emphasis></link>
            or terminated. It must not be a <code><phrase role="identifier">pinned_context</phrase></code>.
            It must be currently detached. It must not currently be linked into an
            <link linkend="class_algorithm"><code>algorithm</code></link> implementation&#8217;s ready queue. Most of these conditions
            are implied by <code><phrase role="identifier">f</phrase></code> being
            owned by an <code><phrase role="identifier">algorithm</phrase></code>
            implementation: that is, it has been passed to <link linkend="algorithm_awakened"><code>algorithm::awakened()</code></link> but
            has not yet been returned by <link linkend="algorithm_pick_next"><code>algorithm::pick_next()</code></link>.
            Typically a <code><phrase role="identifier">pick_next</phrase><phrase
            role="special">()</phrase></code> implementation would call <code><phrase
            role="identifier">attach</phrase><phrase role="special">()</phrase></code>
            with the <code><phrase role="identifier">context</phrase><phrase role="special">*</phrase></code>
            it is about to return. It must first remove <code><phrase role="identifier">f</phrase></code>
            from its ready queue. You should never pass a <code><phrase role="identifier">pinned_context</phrase></code>
            to <code><phrase role="identifier">attach</phrase><phrase role="special">()</phrase></code>
            because you should never have called its <code><phrase role="identifier">detach</phrase><phrase
            role="special">()</phrase></code> method in the first place.
          </para>
        </listitem>
      </varlistentry>
    </variablelist>
    <para>
      <bridgehead renderas="sect4" id="context_detach_bridgehead">
  <phrase id="context_detach"/>
  <link linkend="context_detach">Member function <code>detach</code>()</link>
</bridgehead>
    </para>
<programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">detach</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
</programlisting>
    <variablelist>
      <title></title>
      <varlistentry>
        <term>Precondition:</term>
        <listitem>
          <para>
            <code><phrase role="special">(</phrase><phrase role="keyword">this</phrase><phrase
            role="special">-&gt;</phrase><phrase role="identifier">get_scheduler</phrase><phrase
            role="special">()</phrase> <phrase role="special">!=</phrase> <phrase
            role="keyword">nullptr</phrase><phrase role="special">)</phrase> <phrase
            role="special">&amp;&amp;</phrase> <phrase role="special">!</phrase>
            <phrase role="keyword">this</phrase><phrase role="special">-&gt;</phrase><phrase
            role="identifier">is_context</phrase><phrase role="special">(</phrase><phrase
            role="identifier">pinned_context</phrase><phrase role="special">)</phrase></code>
          </para>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term>Effects:</term>
        <listitem>
          <para>
            Detach fiber <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>
            from its scheduler running <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>Postcondition:</term>
        <listitem>
          <para>
            <code><phrase role="keyword">this</phrase><phrase role="special">-&gt;</phrase><phrase
            role="identifier">get_scheduler</phrase><phrase role="special">()</phrase>
            <phrase role="special">==</phrase> <phrase role="keyword">nullptr</phrase></code>
          </para>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term>Note:</term>
        <listitem>
          <para>
            This method must be called on the thread with which the fiber is currently
            associated. <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>
            must not be the running fiber&#8217;s context. It must not be <link linkend="blocking"><emphasis>blocked</emphasis></link>
            or terminated. It must not be a <code><phrase role="identifier">pinned_context</phrase></code>.
            It must not be detached already. It must not already be linked into an
            <link linkend="class_algorithm"><code>algorithm</code></link> implementation&#8217;s ready queue. Most of these conditions
            are implied by <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>
            being passed to <link linkend="algorithm_awakened"><code>algorithm::awakened()</code></link>; an <code><phrase
            role="identifier">awakened</phrase><phrase role="special">()</phrase></code>
            implementation must, however, test for <code><phrase role="identifier">pinned_context</phrase></code>.
            It must call <code><phrase role="identifier">detach</phrase><phrase role="special">()</phrase></code>
            <emphasis>before</emphasis> linking <code><phrase role="special">*</phrase><phrase
            role="keyword">this</phrase></code> into its ready queue.
          </para>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term>Note:</term>
        <listitem>
          <para>
            In particular, it is erroneous to attempt to migrate a fiber from one
            thread to another by calling both <code><phrase role="identifier">detach</phrase><phrase
            role="special">()</phrase></code> and <code><phrase role="identifier">attach</phrase><phrase
            role="special">()</phrase></code> in the <link linkend="algorithm_pick_next"><code>algorithm::pick_next()</code></link> method.
            <code><phrase role="identifier">pick_next</phrase><phrase role="special">()</phrase></code>
            is called on the intended destination thread. <code><phrase role="identifier">detach</phrase><phrase
            role="special">()</phrase></code> must be called on the fiber&#8217;s original
            thread. You must call <code><phrase role="identifier">detach</phrase><phrase
            role="special">()</phrase></code> in the corresponding <code><phrase
            role="identifier">awakened</phrase><phrase role="special">()</phrase></code>
            method.
          </para>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term>Note:</term>
        <listitem>
          <para>
            Unless you intend make a fiber available for potential migration to a
            different thread, you should call neither <code><phrase role="identifier">detach</phrase><phrase
            role="special">()</phrase></code> nor <code><phrase role="identifier">attach</phrase><phrase
            role="special">()</phrase></code> with its <code><phrase role="identifier">context</phrase></code>.
          </para>
        </listitem>
      </varlistentry>
    </variablelist>
    <para>
      <bridgehead renderas="sect4" id="context_is_context_bridgehead">
  <phrase id="context_is_context"/>
  <link linkend="context_is_context">Member function
      <code>is_context</code>()</link>
</bridgehead>
    </para>
<programlisting><phrase role="keyword">bool</phrase> <phrase role="identifier">is_context</phrase><phrase role="special">(</phrase> <phrase role="identifier">type</phrase> <phrase role="identifier">t</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> is of the specified type.
          </para>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term>Throws:</term>
        <listitem>
          <para>
            Nothing
          </para>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term>Note:</term>
        <listitem>
          <para>
            <code><phrase role="identifier">type</phrase><phrase role="special">::</phrase><phrase
            role="identifier">worker_context</phrase></code> here means any fiber
            not special to the library. For <code><phrase role="identifier">type</phrase><phrase
            role="special">::</phrase><phrase role="identifier">main_context</phrase></code>
            the <code><phrase role="identifier">context</phrase></code> is associated
            with the <quote>main</quote> fiber of the thread: the one implicitly
            created by the thread itself, rather than one explicitly created by
            <emphasis role="bold">Boost.Fiber</emphasis>. For <code><phrase role="identifier">type</phrase><phrase
            role="special">::</phrase><phrase role="identifier">dispatcher_context</phrase></code>
            the <code><phrase role="identifier">context</phrase></code> is associated
            with a <quote>dispatching</quote> fiber, responsible for dispatching
            awakened fibers to a scheduler&#8217;s ready-queue. The <quote>dispatching</quote>
            fiber is an implementation detail of the fiber manager. The context of
            the <quote>main</quote> or <quote>dispatching</quote> fiber &mdash; any fiber
            for which <code><phrase role="identifier">is_context</phrase><phrase
            role="special">(</phrase><phrase role="identifier">pinned_context</phrase><phrase
            role="special">)</phrase></code> is <code><phrase role="keyword">true</phrase></code>
            &mdash; must never be passed to <link linkend="context_detach"><code>context::detach()</code></link>.
          </para>
        </listitem>
      </varlistentry>
    </variablelist>
    <para>
      <bridgehead renderas="sect4" id="context_is_terminated_bridgehead">
  <phrase id="context_is_terminated"/>
  <link linkend="context_is_terminated">Member
      function <code>is_terminated</code>()</link>
</bridgehead>
    </para>
<programlisting><phrase role="keyword">bool</phrase> <phrase role="identifier">is_terminated</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> is no longer a valid context.
          </para>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term>Throws:</term>
        <listitem>
          <para>
            Nothing
          </para>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term>Note:</term>
        <listitem>
          <para>
            The <code><phrase role="identifier">context</phrase></code> has returned
            from its fiber-function and is no longer considered a valid context.
          </para>
        </listitem>
      </varlistentry>
    </variablelist>
    <para>
      <bridgehead renderas="sect4" id="context_ready_is_linked_bridgehead">
  <phrase id="context_ready_is_linked"/>
  <link linkend="context_ready_is_linked">Member
      function <code>ready_is_linked</code>()</link>
</bridgehead>
    </para>
<programlisting><phrase role="keyword">bool</phrase> <phrase role="identifier">ready_is_linked</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> is stored in an <link linkend="class_algorithm"><code>algorithm</code></link>
implementation&#8217;s
            ready-queue.
          </para>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term>Throws:</term>
        <listitem>
          <para>
            Nothing
          </para>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term>Note:</term>
        <listitem>
          <para>
            Specifically, this method indicates whether <link linkend="context_ready_link"><code>context::ready_link()</code></link> has
            been called on <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>.
            <code><phrase role="identifier">ready_is_linked</phrase><phrase role="special">()</phrase></code>
            has no information about participation in any other containers.
          </para>
        </listitem>
      </varlistentry>
    </variablelist>
    <para>
      <bridgehead renderas="sect4" id="context_remote_ready_is_linked_bridgehead">
  <phrase id="context_remote_ready_is_linked"/>
  <link linkend="context_remote_ready_is_linked">Member
      function <code>remote_ready_is_linked</code>()</link>
</bridgehead>
    </para>
<programlisting><phrase role="keyword">bool</phrase> <phrase role="identifier">remote_ready_is_linked</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> is stored in the fiber manager&#8217;s remote-ready-queue.
          </para>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term>Throws:</term>
        <listitem>
          <para>
            Nothing
          </para>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term>Note:</term>
        <listitem>
          <para>
            A <code><phrase role="identifier">context</phrase></code> signaled as
            ready by another thread is first stored in the fiber manager&#8217;s remote-ready-queue.
            This is the mechanism by which the fiber manager protects an <link linkend="class_algorithm"><code>algorithm</code></link> implementation
            from cross-thread <link linkend="algorithm_awakened"><code>algorithm::awakened()</code></link> calls.
          </para>
        </listitem>
      </varlistentry>
    </variablelist>
    <para>
      <bridgehead renderas="sect4" id="context_wait_is_linked_bridgehead">
  <phrase id="context_wait_is_linked"/>
  <link linkend="context_wait_is_linked">Member
      function <code>wait_is_linked</code>()</link>
</bridgehead>
    </para>
<programlisting><phrase role="keyword">bool</phrase> <phrase role="identifier">wait_is_linked</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> is stored in the wait-queue of some
            synchronization object.
          </para>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term>Throws:</term>
        <listitem>
          <para>
            Nothing
          </para>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term>Note:</term>
        <listitem>
          <para>
            The <code><phrase role="identifier">context</phrase></code> of a fiber
            waiting on a synchronization object (e.g. <code><phrase role="identifier">mutex</phrase></code>,
            <code><phrase role="identifier">condition_variable</phrase></code> etc.)
            is stored in the wait-queue of that synchronization object.
          </para>
        </listitem>
      </varlistentry>
    </variablelist>
    <para>
      <bridgehead renderas="sect4" id="context_ready_link_bridgehead">
  <phrase id="context_ready_link"/>
  <link linkend="context_ready_link">Member function
      <code>ready_link</code>()</link>
</bridgehead>
    </para>
<programlisting><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">List</phrase> <phrase role="special">&gt;</phrase>
<phrase role="keyword">void</phrase> <phrase role="identifier">ready_link</phrase><phrase role="special">(</phrase> <phrase role="identifier">List</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">lst</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 <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>
            in ready-queue <code><phrase role="identifier">lst</phrase></code>.
          </para>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term>Throws:</term>
        <listitem>
          <para>
            Nothing
          </para>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term>Note:</term>
        <listitem>
          <para>
            Argument <code><phrase role="identifier">lst</phrase></code> must be
            a doubly-linked list from <ulink url="http://www.boost.org/doc/libs/release/libs/intrusive/index.html">Boost.Intrusive</ulink>,
            e.g. an instance of <code><phrase role="identifier">boost</phrase><phrase
            role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase
            role="special">::</phrase><phrase role="identifier">scheduler</phrase><phrase
            role="special">::</phrase><phrase role="identifier">ready_queue_t</phrase></code>.
            Specifically, it must be a <ulink url="http://www.boost.org/doc/libs/release/doc/html/intrusive/list.html"><code><phrase
            role="identifier">boost</phrase><phrase role="special">::</phrase><phrase
            role="identifier">intrusive</phrase><phrase role="special">::</phrase><phrase
            role="identifier">list</phrase></code></ulink> compatible with the <code><phrase
            role="identifier">list_member_hook</phrase></code> stored in the <code><phrase
            role="identifier">context</phrase></code> object.
          </para>
        </listitem>
      </varlistentry>
    </variablelist>
    <para>
      <bridgehead renderas="sect4" id="context_remote_ready_link_bridgehead">
  <phrase id="context_remote_ready_link"/>
  <link linkend="context_remote_ready_link">Member
      function <code>remote_ready_link</code>()</link>
</bridgehead>
    </para>
<programlisting><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">List</phrase> <phrase role="special">&gt;</phrase>
<phrase role="keyword">void</phrase> <phrase role="identifier">remote_ready_link</phrase><phrase role="special">(</phrase> <phrase role="identifier">List</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">lst</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 <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>
            in remote-ready-queue <code><phrase role="identifier">lst</phrase></code>.
          </para>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term>Throws:</term>
        <listitem>
          <para>
            Nothing
          </para>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term>Note:</term>
        <listitem>
          <para>
            Argument <code><phrase role="identifier">lst</phrase></code> must be
            a doubly-linked list from <ulink url="http://www.boost.org/doc/libs/release/libs/intrusive/index.html">Boost.Intrusive</ulink>.
          </para>
        </listitem>
      </varlistentry>
    </variablelist>
    <para>
      <bridgehead renderas="sect4" id="context_wait_link_bridgehead">
  <phrase id="context_wait_link"/>
  <link linkend="context_wait_link">Member function
      <code>wait_link</code>()</link>
</bridgehead>
    </para>
<programlisting><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">List</phrase> <phrase role="special">&gt;</phrase>
<phrase role="keyword">void</phrase> <phrase role="identifier">wait_link</phrase><phrase role="special">(</phrase> <phrase role="identifier">List</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">lst</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 <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>
            in wait-queue <code><phrase role="identifier">lst</phrase></code>.
          </para>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term>Throws:</term>
        <listitem>
          <para>
            Nothing
          </para>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term>Note:</term>
        <listitem>
          <para>
            Argument <code><phrase role="identifier">lst</phrase></code> must be
            a doubly-linked list from <ulink url="http://www.boost.org/doc/libs/release/libs/intrusive/index.html">Boost.Intrusive</ulink>.
          </para>
        </listitem>
      </varlistentry>
    </variablelist>
    <para>
      <bridgehead renderas="sect4" id="context_ready_unlink_bridgehead">
  <phrase id="context_ready_unlink"/>
  <link linkend="context_ready_unlink">Member
      function <code>ready_unlink</code>()</link>
</bridgehead>
    </para>
<programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">ready_unlink</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
</programlisting>
    <variablelist>
      <title></title>
      <varlistentry>
        <term>Effects:</term>
        <listitem>
          <para>
            Removes <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>
            from ready-queue: undoes the effect of <link linkend="context_ready_link"><code>context::ready_link()</code></link>.
          </para>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term>Throws:</term>
        <listitem>
          <para>
            Nothing
          </para>
        </listitem>
      </varlistentry>
    </variablelist>
    <para>
      <bridgehead renderas="sect4" id="context_remote_ready_unlink_bridgehead">
  <phrase id="context_remote_ready_unlink"/>
  <link linkend="context_remote_ready_unlink">Member
      function <code>remote_ready_unlink</code>()</link>
</bridgehead>
    </para>
<programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">remote_ready_unlink</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
</programlisting>
    <variablelist>
      <title></title>
      <varlistentry>
        <term>Effects:</term>
        <listitem>
          <para>
            Removes <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>
            from remote-ready-queue.
          </para>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term>Throws:</term>
        <listitem>
          <para>
            Nothing
          </para>
        </listitem>
      </varlistentry>
    </variablelist>
    <para>
      <bridgehead renderas="sect4" id="context_wait_unlink_bridgehead">
  <phrase id="context_wait_unlink"/>
  <link linkend="context_wait_unlink">Member
      function <code>wait_unlink</code>()</link>
</bridgehead>
    </para>
<programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">wait_unlink</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
</programlisting>
    <variablelist>
      <title></title>
      <varlistentry>
        <term>Effects:</term>
        <listitem>
          <para>
            Removes <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>
            from wait-queue.
          </para>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term>Throws:</term>
        <listitem>
          <para>
            Nothing
          </para>
        </listitem>
      </varlistentry>
    </variablelist>
    <para>
      <bridgehead renderas="sect4" id="context_suspend_bridgehead">
  <phrase id="context_suspend"/>
  <link linkend="context_suspend">Member function <code>suspend</code>()</link>
</bridgehead>
    </para>
<programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">suspend</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
</programlisting>
    <variablelist>
      <title></title>
      <varlistentry>
        <term>Effects:</term>
        <listitem>
          <para>
            Suspends the running fiber (the fiber associated with <code><phrase role="special">*</phrase><phrase
            role="keyword">this</phrase></code>) until some other fiber passes <code><phrase
            role="keyword">this</phrase></code> to <link linkend="context_schedule"><code>context::schedule()</code></link>.
            <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>
            is marked as not-ready, and control passes to the scheduler to select
            another fiber to run.
          </para>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term>Throws:</term>
        <listitem>
          <para>
            Nothing
          </para>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term>Note:</term>
        <listitem>
          <para>
            This is a low-level API potentially useful for integration with other
            frameworks. It is not intended to be directly invoked by a typical application
            program.
          </para>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term>Note:</term>
        <listitem>
          <para>
            The burden is on the caller to arrange for a call to <code><phrase role="identifier">schedule</phrase><phrase
            role="special">()</phrase></code> with a pointer to <code><phrase role="keyword">this</phrase></code>
            at some future time.
          </para>
        </listitem>
      </varlistentry>
    </variablelist>
    <para>
      <bridgehead renderas="sect4" id="context_schedule_bridgehead">
  <phrase id="context_schedule"/>
  <link linkend="context_schedule">Member function
      <code>schedule</code>()</link>
</bridgehead>
    </para>
<programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">schedule</phrase><phrase role="special">(</phrase> <phrase role="identifier">context</phrase> <phrase role="special">*</phrase> <phrase role="identifier">ctx</phrase> <phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
</programlisting>
    <variablelist>
      <title></title>
      <varlistentry>
        <term>Effects:</term>
        <listitem>
          <para>
            Mark the fiber associated with context <code><phrase role="special">*</phrase><phrase
            role="identifier">ctx</phrase></code> as being ready to run. This does
            not immediately resume that fiber; rather it passes the fiber to the
            scheduler for subsequent resumption. If the scheduler is idle (has not
            returned from a call to <link linkend="algorithm_suspend_until"><code>algorithm::suspend_until()</code></link>),
            <link linkend="algorithm_notify"><code>algorithm::notify()</code></link> is called to wake it up.
          </para>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term>Throws:</term>
        <listitem>
          <para>
            Nothing
          </para>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term>Note:</term>
        <listitem>
          <para>
            This is a low-level API potentially useful for integration with other
            frameworks. It is not intended to be directly invoked by a typical application
            program.
          </para>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term>Note:</term>
        <listitem>
          <para>
            It is explicitly supported to call <code><phrase role="identifier">schedule</phrase><phrase
            role="special">(</phrase><phrase role="identifier">ctx</phrase><phrase
            role="special">)</phrase></code> from a thread other than the one on
            which <code><phrase role="special">*</phrase><phrase role="identifier">ctx</phrase></code>
            is currently suspended. The corresponding fiber will be resumed on its
            original thread in due course.
          </para>
        </listitem>
      </varlistentry>
    </variablelist>
    <para>
      <bridgehead renderas="sect4" id="context_less_bridgehead">
  <phrase id="context_less"/>
  <link linkend="context_less">Non-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">context</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">l</phrase><phrase role="special">,</phrase> <phrase role="identifier">context</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>
</programlisting>
    <variablelist>
      <title></title>
      <varlistentry>
        <term>Returns:</term>
        <listitem>
          <para>
            <code><phrase role="keyword">true</phrase></code> if <code><phrase role="identifier">l</phrase><phrase
            role="special">.</phrase><phrase role="identifier">get_id</phrase><phrase
            role="special">()</phrase> <phrase role="special">&lt;</phrase> <phrase
            role="identifier">r</phrase><phrase role="special">.</phrase><phrase
            role="identifier">get_id</phrase><phrase role="special">()</phrase></code>
            is <code><phrase role="keyword">true</phrase></code>, <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.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 an __econtext__ 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.stack_allocator_concept"/><link linkend="fiber.stack.stack_allocator_concept">stack-allocator
      concept</link>
    </bridgehead>
    <para>
      A <emphasis>stack_allocator</emphasis> must satisfy the <emphasis>stack-allocator
      concept</emphasis> requirements shown in the following table, in which <code><phrase
      role="identifier">a</phrase></code> is an object of a <emphasis>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 __econtext__.
      </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>. In particular, <code><phrase role="identifier">traits_type</phrase></code>
      methods are as described for <ulink url="http://www.boost.org/doc/libs/release/libs/context/doc/html/context/stack/stack_traits.html"><code><phrase
      role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">context</phrase><phrase
      role="special">::</phrase><phrase role="identifier">stack_traits</phrase></code></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>
<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">protected_fixedsize</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">struct</phrase> <phrase role="identifier">protected_fixedsize</phrase> <phrase role="special">{</phrase>
    <phrase role="identifier">protected_fixesize</phrase><phrase role="special">(</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">size</phrase> <phrase role="special">=</phrase> <phrase role="identifier">traits_type</phrase><phrase role="special">::</phrase><phrase role="identifier">default_size</phrase><phrase role="special">());</phrase>

    <phrase role="identifier">stack_context</phrase> <phrase role="identifier">allocate</phrase><phrase role="special">();</phrase>

    <phrase role="keyword">void</phrase> <phrase role="identifier">deallocate</phrase><phrase role="special">(</phrase> <phrase role="identifier">stack_context</phrase> <phrase role="special">&amp;);</phrase>
<phrase role="special">}</phrase>

<phrase role="special">}}</phrase>
</programlisting>
    <para>
      <bridgehead renderas="sect4" id="protected_fixedsize_allocate_bridgehead">
  <phrase id="protected_fixedsize_allocate"/>
  <link linkend="protected_fixedsize_allocate">Member
      function <code>allocate</code>()</link>
</bridgehead>
    </para>
<programlisting><phrase role="identifier">stack_context</phrase> <phrase role="identifier">allocate</phrase><phrase role="special">();</phrase>
</programlisting>
    <variablelist>
      <title></title>
      <varlistentry>
        <term>Preconditions:</term>
        <listitem>
          <para>
            <code><phrase role="identifier">traits_type</phrase><phrase role="special">::</phrase><phrase
            role="identifier">minimum_size</phrase><phrase role="special">()</phrase>
            <phrase role="special">&lt;=</phrase> <phrase role="identifier">size</phrase></code>
            and <code><phrase role="identifier">traits_type</phrase><phrase role="special">::</phrase><phrase
            role="identifier">is_unbounded</phrase><phrase role="special">()</phrase>
            <phrase role="special">||</phrase> <phrase role="special">(</phrase>
            <phrase role="identifier">size</phrase> <phrase role="special">&lt;=</phrase>
            <phrase role="identifier">traits_type</phrase><phrase role="special">::</phrase><phrase
            role="identifier">maximum_size</phrase><phrase role="special">()</phrase>
            <phrase role="special">)</phrase></code>.
          </para>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term>Effects:</term>
        <listitem>
          <para>
            Allocates memory of at least <code><phrase role="identifier">size</phrase></code>
            bytes and stores a pointer to the stack and its actual size in <code><phrase
            role="identifier">sctx</phrase></code>. Depending on the architecture
            (the stack grows downwards/upwards) the stored address is the highest/lowest
            address of the stack.
          </para>
        </listitem>
      </varlistentry>
    </variablelist>
    <para>
      <bridgehead renderas="sect4" id="protected_fixesize_deallocate_bridgehead">
  <phrase id="protected_fixesize_deallocate"/>
  <link linkend="protected_fixesize_deallocate">Member
      function <code>deallocate</code>()</link>
</bridgehead>
    </para>
<programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">deallocate</phrase><phrase role="special">(</phrase> <phrase role="identifier">stack_context</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">sctx</phrase><phrase role="special">);</phrase>
</programlisting>
    <variablelist>
      <title></title>
      <varlistentry>
        <term>Preconditions:</term>
        <listitem>
          <para>
            <code><phrase role="identifier">sctx</phrase><phrase role="special">.</phrase><phrase
            role="identifier">sp</phrase></code> is valid, <code><phrase role="identifier">traits_type</phrase><phrase
            role="special">::</phrase><phrase role="identifier">minimum_size</phrase><phrase
            role="special">()</phrase> <phrase role="special">&lt;=</phrase> <phrase
            role="identifier">sctx</phrase><phrase role="special">.</phrase><phrase
            role="identifier">size</phrase></code> and <code><phrase role="identifier">traits_type</phrase><phrase
            role="special">::</phrase><phrase role="identifier">is_unbounded</phrase><phrase
            role="special">()</phrase> <phrase role="special">||</phrase> <phrase
            role="special">(</phrase> <phrase role="identifier">sctx</phrase><phrase
            role="special">.</phrase><phrase role="identifier">size</phrase> <phrase
            role="special">&lt;=</phrase> <phrase role="identifier">traits_type</phrase><phrase
            role="special">::</phrase><phrase role="identifier">maximum_size</phrase><phrase
            role="special">()</phrase> <phrase role="special">)</phrase></code>.
          </para>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term>Effects:</term>
        <listitem>
          <para>
            Deallocates the stack space.
          </para>
        </listitem>
      </varlistentry>
    </variablelist>
    <para>
      <bridgehead renderas="sect4" id="class_pooled_fixedsize_stack_bridgehead">
  <phrase id="class_pooled_fixedsize_stack"/>
  <link linkend="class_pooled_fixedsize_stack">Class
      <code>pooled_fixedsize_stack</code></link>
</bridgehead>
    </para>
    <para>
      <emphasis role="bold">Boost.Fiber</emphasis> provides the class <link linkend="class_pooled_fixedsize_stack"><code>pooled_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 managed
      internally by <ulink url="http://www.boost.org/doc/libs/release/libs/pool/doc/html/boost/pool.html"><code><phrase
      role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">pool</phrase><phrase
      role="special">&lt;&gt;</phrase></code></ulink>.
    </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">pooled_fixedsize_stack</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">struct</phrase> <phrase role="identifier">pooled_fixedsize_stack</phrase> <phrase role="special">{</phrase>
    <phrase role="identifier">pooled_fixedsize_stack</phrase><phrase role="special">(</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">stack_size</phrase> <phrase role="special">=</phrase> <phrase role="identifier">traits_type</phrase><phrase role="special">::</phrase><phrase role="identifier">default_size</phrase><phrase role="special">(),</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">next_size</phrase> <phrase role="special">=</phrase> <phrase role="number">32</phrase><phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">max_size</phrase> <phrase role="special">=</phrase> <phrase role="number">0</phrase><phrase role="special">);</phrase>

    <phrase role="identifier">stack_context</phrase> <phrase role="identifier">allocate</phrase><phrase role="special">();</phrase>

    <phrase role="keyword">void</phrase> <phrase role="identifier">deallocate</phrase><phrase role="special">(</phrase> <phrase role="identifier">stack_context</phrase> <phrase role="special">&amp;);</phrase>
<phrase role="special">}</phrase>

<phrase role="special">}}</phrase>
</programlisting>
    <para>
      <bridgehead renderas="sect4" id="pooled_fixedsize_bridgehead">
  <phrase id="pooled_fixedsize"/>
  <link linkend="pooled_fixedsize">Constructor</link>
</bridgehead>
    </para>
<programlisting><phrase role="identifier">pooled_fixedsize_stack</phrase><phrase role="special">(</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">stack_size</phrase><phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">next_size</phrase><phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">max_size</phrase><phrase role="special">);</phrase>
</programlisting>
    <variablelist>
      <title></title>
      <varlistentry>
        <term>Preconditions:</term>
        <listitem>
          <para>
            <code><phrase role="identifier">traits_type</phrase><phrase role="special">::</phrase><phrase
            role="identifier">is_unbounded</phrase><phrase role="special">()</phrase>
            <phrase role="special">||</phrase> <phrase role="special">(</phrase>
            <phrase role="identifier">traits_type</phrase><phrase role="special">::</phrase><phrase
            role="identifier">maximum_size</phrase><phrase role="special">()</phrase>
            <phrase role="special">&gt;=</phrase> <phrase role="identifier">stack_size</phrase><phrase
            role="special">)</phrase></code> and <code><phrase role="number">0</phrase>
            <phrase role="special">&lt;</phrase> <phrase role="identifier">next_size</phrase></code>.
          </para>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term>Effects:</term>
        <listitem>
          <para>
            Allocates memory of at least <code><phrase role="identifier">stack_size</phrase></code>
            bytes and stores a pointer to the stack and its actual size in <code><phrase
            role="identifier">sctx</phrase></code>. Depending on the architecture
            (the stack grows downwards/upwards) the stored address is the highest/lowest
            address of the stack. Argument <code><phrase role="identifier">next_size</phrase></code>
            determines the number of stacks to request from the system the first
            time that <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>
            needs to allocate system memory. The third argument <code><phrase role="identifier">max_size</phrase></code>
            controls how much memory might be allocated for stacks &mdash; a value of zero
            means no upper limit.
          </para>
        </listitem>
      </varlistentry>
    </variablelist>
    <para>
      <bridgehead renderas="sect4" id="pooled_fixedsize_allocate_bridgehead">
  <phrase id="pooled_fixedsize_allocate"/>
  <link linkend="pooled_fixedsize_allocate">Member
      function <code>allocate</code>()</link>
</bridgehead>
    </para>
<programlisting><phrase role="identifier">stack_context</phrase> <phrase role="identifier">allocate</phrase><phrase role="special">();</phrase>
</programlisting>
    <variablelist>
      <title></title>
      <varlistentry>
        <term>Preconditions:</term>
        <listitem>
          <para>
            <code><phrase role="identifier">traits_type</phrase><phrase role="special">::</phrase><phrase
            role="identifier">is_unbounded</phrase><phrase role="special">()</phrase>
            <phrase role="special">||</phrase> <phrase role="special">(</phrase>
            <phrase role="identifier">traits_type</phrase><phrase role="special">::</phrase><phrase
            role="identifier">maximum_size</phrase><phrase role="special">()</phrase>
            <phrase role="special">&gt;=</phrase> <phrase role="identifier">stack_size</phrase><phrase
            role="special">)</phrase></code>.
          </para>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term>Effects:</term>
        <listitem>
          <para>
            Allocates memory of at least <code><phrase role="identifier">stack_size</phrase></code>
            bytes and stores a pointer to the stack and its actual size in <code><phrase
            role="identifier">sctx</phrase></code>. Depending on the architecture
            (the stack grows downwards/upwards) the stored address is the highest/lowest
            address of the stack.
          </para>
        </listitem>
      </varlistentry>
    </variablelist>
    <para>
      <bridgehead renderas="sect4" id="pooled_fixesize_deallocate_bridgehead">
  <phrase id="pooled_fixesize_deallocate"/>
  <link linkend="pooled_fixesize_deallocate">Member
      function <code>deallocate</code>()</link>
</bridgehead>
    </para>
<programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">deallocate</phrase><phrase role="special">(</phrase> <phrase role="identifier">stack_context</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">sctx</phrase><phrase role="special">);</phrase>
</programlisting>
    <variablelist>
      <title></title>
      <varlistentry>
        <term>Preconditions:</term>
        <listitem>
          <para>
            <code><phrase role="identifier">sctx</phrase><phrase role="special">.</phrase><phrase
            role="identifier">sp</phrase></code> is valid, <code><phrase role="identifier">traits_type</phrase><phrase
            role="special">::</phrase><phrase role="identifier">is_unbounded</phrase><phrase
            role="special">()</phrase> <phrase role="special">||</phrase> <phrase
            role="special">(</phrase> <phrase role="identifier">traits_type</phrase><phrase
            role="special">::</phrase><phrase role="identifier">maximum_size</phrase><phrase
            role="special">()</phrase> <phrase role="special">&gt;=</phrase> <phrase
            role="identifier">sctx</phrase><phrase role="special">.</phrase><phrase
            role="identifier">size</phrase><phrase role="special">)</phrase></code>.
          </para>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term>Effects:</term>
        <listitem>
          <para>
            Deallocates the stack space.
          </para>
        </listitem>
      </varlistentry>
    </variablelist>
    <note>
      <para>
        This stack allocator is not thread safe.
      </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>
<programlisting><phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">context</phrase><phrase role="special">/</phrase><phrase role="identifier">fixedsize_stack</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">struct</phrase> <phrase role="identifier">fixedsize_stack</phrase> <phrase role="special">{</phrase>
    <phrase role="identifier">fixedsize_stack</phrase><phrase role="special">(</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">size</phrase> <phrase role="special">=</phrase> <phrase role="identifier">traits_type</phrase><phrase role="special">::</phrase><phrase role="identifier">default_size</phrase><phrase role="special">());</phrase>

    <phrase role="identifier">stack_context</phrase> <phrase role="identifier">allocate</phrase><phrase role="special">();</phrase>

    <phrase role="keyword">void</phrase> <phrase role="identifier">deallocate</phrase><phrase role="special">(</phrase> <phrase role="identifier">stack_context</phrase> <phrase role="special">&amp;);</phrase>
<phrase role="special">}</phrase>

<phrase role="special">}}</phrase>
</programlisting>
    <para>
      <bridgehead renderas="sect4" id="fixedsize_allocate_bridgehead">
  <phrase id="fixedsize_allocate"/>
  <link linkend="fixedsize_allocate">Member function
      <code>allocate</code>()</link>
</bridgehead>
    </para>
<programlisting><phrase role="identifier">stack_context</phrase> <phrase role="identifier">allocate</phrase><phrase role="special">();</phrase>
</programlisting>
    <variablelist>
      <title></title>
      <varlistentry>
        <term>Preconditions:</term>
        <listitem>
          <para>
            <code><phrase role="identifier">traits_type</phrase><phrase role="special">::</phrase><phrase
            role="identifier">minimum_size</phrase><phrase role="special">()</phrase>
            <phrase role="special">&lt;=</phrase> <phrase role="identifier">size</phrase></code>
            and <code><phrase role="identifier">traits_type</phrase><phrase role="special">::</phrase><phrase
            role="identifier">is_unbounded</phrase><phrase role="special">()</phrase>
            <phrase role="special">||</phrase> <phrase role="special">(</phrase>
            <phrase role="identifier">traits_type</phrase><phrase role="special">::</phrase><phrase
            role="identifier">maximum_size</phrase><phrase role="special">()</phrase>
            <phrase role="special">&gt;=</phrase> <phrase role="identifier">size</phrase><phrase
            role="special">)</phrase></code>.
          </para>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term>Effects:</term>
        <listitem>
          <para>
            Allocates memory of at least <code><phrase role="identifier">size</phrase></code>
            bytes and stores a pointer to the stack and its actual size in <code><phrase
            role="identifier">sctx</phrase></code>. Depending on the architecture
            (the stack grows downwards/upwards) the stored address is the highest/lowest
            address of the stack.
          </para>
        </listitem>
      </varlistentry>
    </variablelist>
    <para>
      <bridgehead renderas="sect4" id="fixesize_deallocate_bridgehead">
  <phrase id="fixesize_deallocate"/>
  <link linkend="fixesize_deallocate">Member
      function <code>deallocate</code>()</link>
</bridgehead>
    </para>
<programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">deallocate</phrase><phrase role="special">(</phrase> <phrase role="identifier">stack_context</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">sctx</phrase><phrase role="special">);</phrase>
</programlisting>
    <variablelist>
      <title></title>
      <varlistentry>
        <term>Preconditions:</term>
        <listitem>
          <para>
            <code><phrase role="identifier">sctx</phrase><phrase role="special">.</phrase><phrase
            role="identifier">sp</phrase></code> is valid, <code><phrase role="identifier">traits_type</phrase><phrase
            role="special">::</phrase><phrase role="identifier">minimum_size</phrase><phrase
            role="special">()</phrase> <phrase role="special">&lt;=</phrase> <phrase
            role="identifier">sctx</phrase><phrase role="special">.</phrase><phrase
            role="identifier">size</phrase></code> and <code><phrase role="identifier">traits_type</phrase><phrase
            role="special">::</phrase><phrase role="identifier">is_unbounded</phrase><phrase
            role="special">()</phrase> <phrase role="special">||</phrase> <phrase
            role="special">(</phrase> <phrase role="identifier">traits_type</phrase><phrase
            role="special">::</phrase><phrase role="identifier">maximum_size</phrase><phrase
            role="special">()</phrase> <phrase role="special">&gt;=</phrase> <phrase
            role="identifier">sctx</phrase><phrase role="special">.</phrase><phrase
            role="identifier">size</phrase><phrase role="special">)</phrase></code>.
          </para>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term>Effects:</term>
        <listitem>
          <para>
            Deallocates the stack space.
          </para>
        </listitem>
      </varlistentry>
    </variablelist>
    <para>
      <anchor id="segmented"/><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> and
        applying BOOST_USE_SEGMENTED_STACKS at b2/bjam command line.
      </para>
    </note>
    <note>
      <para>
        Segmented stacks can only be used with callcc() using property <code><phrase
        role="identifier">context</phrase><phrase role="special">-</phrase><phrase
        role="identifier">impl</phrase><phrase role="special">=</phrase><phrase role="identifier">ucontext</phrase></code>.
      </para>
    </note>
<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">segmented_stack</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">struct</phrase> <phrase role="identifier">segmented_stack</phrase> <phrase role="special">{</phrase>
    <phrase role="identifier">segmented_stack</phrase><phrase role="special">(</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">stack_size</phrase> <phrase role="special">=</phrase> <phrase role="identifier">traits_type</phrase><phrase role="special">::</phrase><phrase role="identifier">default_size</phrase><phrase role="special">());</phrase>

    <phrase role="identifier">stack_context</phrase> <phrase role="identifier">allocate</phrase><phrase role="special">();</phrase>

    <phrase role="keyword">void</phrase> <phrase role="identifier">deallocate</phrase><phrase role="special">(</phrase> <phrase role="identifier">stack_context</phrase> <phrase role="special">&amp;);</phrase>
<phrase role="special">}</phrase>

<phrase role="special">}}</phrase>
</programlisting>
    <para>
      <bridgehead renderas="sect4" id="segmented_allocate_bridgehead">
  <phrase id="segmented_allocate"/>
  <link linkend="segmented_allocate">Member function
      <code>allocate</code>()</link>
</bridgehead>
    </para>
<programlisting><phrase role="identifier">stack_context</phrase> <phrase role="identifier">allocate</phrase><phrase role="special">();</phrase>
</programlisting>
    <variablelist>
      <title></title>
      <varlistentry>
        <term>Preconditions:</term>
        <listitem>
          <para>
            <code><phrase role="identifier">traits_type</phrase><phrase role="special">::</phrase><phrase
            role="identifier">minimum_size</phrase><phrase role="special">()</phrase>
            <phrase role="special">&lt;=</phrase> <phrase role="identifier">size</phrase></code>
            and <code><phrase role="identifier">traits_type</phrase><phrase role="special">::</phrase><phrase
            role="identifier">is_unbounded</phrase><phrase role="special">()</phrase>
            <phrase role="special">||</phrase> <phrase role="special">(</phrase>
            <phrase role="identifier">traits_type</phrase><phrase role="special">::</phrase><phrase
            role="identifier">maximum_size</phrase><phrase role="special">()</phrase>
            <phrase role="special">&gt;=</phrase> <phrase role="identifier">size</phrase><phrase
            role="special">)</phrase></code>.
          </para>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term>Effects:</term>
        <listitem>
          <para>
            Allocates memory of at least <code><phrase role="identifier">size</phrase></code>
            bytes and stores a pointer to the stack and its actual size in <code><phrase
            role="identifier">sctx</phrase></code>. Depending on the architecture
            (the stack grows downwards/upwards) the stored address is the highest/lowest
            address of the stack.
          </para>
        </listitem>
      </varlistentry>
    </variablelist>
    <para>
      <bridgehead renderas="sect4" id="segmented_deallocate_bridgehead">
  <phrase id="segmented_deallocate"/>
  <link linkend="segmented_deallocate">Member
      function <code>deallocate</code>()</link>
</bridgehead>
    </para>
<programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">deallocate</phrase><phrase role="special">(</phrase> <phrase role="identifier">stack_context</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">sctx</phrase><phrase role="special">);</phrase>
</programlisting>
    <variablelist>
      <title></title>
      <varlistentry>
        <term>Preconditions:</term>
        <listitem>
          <para>
            <code><phrase role="identifier">sctx</phrase><phrase role="special">.</phrase><phrase
            role="identifier">sp</phrase></code> is valid, <code><phrase role="identifier">traits_type</phrase><phrase
            role="special">::</phrase><phrase role="identifier">minimum_size</phrase><phrase
            role="special">()</phrase> <phrase role="special">&lt;=</phrase> <phrase
            role="identifier">sctx</phrase><phrase role="special">.</phrase><phrase
            role="identifier">size</phrase></code> and <code><phrase role="identifier">traits_type</phrase><phrase
            role="special">::</phrase><phrase role="identifier">is_unbounded</phrase><phrase
            role="special">()</phrase> <phrase role="special">||</phrase> <phrase
            role="special">(</phrase> <phrase role="identifier">traits_type</phrase><phrase
            role="special">::</phrase><phrase role="identifier">maximum_size</phrase><phrase
            role="special">()</phrase> <phrase role="special">&gt;=</phrase> <phrase
            role="identifier">sctx</phrase><phrase role="special">.</phrase><phrase
            role="identifier">size</phrase><phrase role="special">)</phrase></code>.
          </para>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term>Effects:</term>
        <listitem>
          <para>
            Deallocates the stack space.
          </para>
        </listitem>
      </varlistentry>
    </variablelist>
    <note>
      <para>
        If the library is compiled for segmented stacks, <link linkend="class_segmented_stack"><code>segmented_stack</code></link> is
        the only available stack allocator.
      </para>
    </note>
    <section id="fiber.stack.valgrind">
      <title><link linkend="fiber.stack.valgrind">Support for valgrind</link></title>
      <para>
        Running programs that switch stacks under valgrind causes problems. Property
        (b2 command-line) <code><phrase role="identifier">valgrind</phrase><phrase
        role="special">=</phrase><phrase role="identifier">on</phrase></code> let
        valgrind treat the memory regions as stack space which suppresses the errors.
      </para>
    </section>
  </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">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">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>

<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">lock_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="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>
              already owns the mutex.
            </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>
              <code><phrase role="identifier">lock_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="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>
              already owns the mutex.
            </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>
              <code><phrase role="identifier">lock_error</phrase></code>
            </para>
          </listitem>
        </varlistentry>
        <varlistentry>
          <term>Error Conditions:</term>
          <listitem>
            <para>
              <emphasis role="bold">operation_not_permitted</emphasis>: if <code><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>
              does not own the mutex.
            </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">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">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">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="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>

<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">lock_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="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>
              already owns the mutex.
            </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>
              <code><phrase role="identifier">lock_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="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>
              already owns the mutex.
            </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>
              <code><phrase role="identifier">lock_error</phrase></code>
            </para>
          </listitem>
        </varlistentry>
        <varlistentry>
          <term>Error Conditions:</term>
          <listitem>
            <para>
              <emphasis role="bold">operation_not_permitted</emphasis>: if <code><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>
              does not own the mutex.
            </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>
              <code><phrase role="identifier">lock_error</phrase></code>, timeout-related
              exceptions.
            </para>
          </listitem>
        </varlistentry>
        <varlistentry>
          <term>Error Conditions:</term>
          <listitem>
            <para>
              <emphasis role="bold">resource_deadlock_would_occur</emphasis>: if
              <code><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>
              already owns the mutex.
            </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>
              <code><phrase role="identifier">lock_error</phrase></code>, timeout-related
              exceptions.
            </para>
          </listitem>
        </varlistentry>
        <varlistentry>
          <term>Error Conditions:</term>
          <listitem>
            <para>
              <emphasis role="bold">resource_deadlock_would_occur</emphasis>: if
              <code><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>
              already owns the mutex.
            </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">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">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>

<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>
              Nothing
            </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> <phrase role="keyword">noexcept</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>
              <code><phrase role="identifier">lock_error</phrase></code>
            </para>
          </listitem>
        </varlistentry>
        <varlistentry>
          <term>Error Conditions:</term>
          <listitem>
            <para>
              <emphasis role="bold">operation_not_permitted</emphasis>: if <code><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>
              does not own the mutex.
            </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">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">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>

<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>
              Nothing
            </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> <phrase role="keyword">noexcept</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>
              <code><phrase role="identifier">lock_error</phrase></code>
            </para>
          </listitem>
        </varlistentry>
        <varlistentry>
          <term>Error Conditions:</term>
          <listitem>
            <para>
              <emphasis role="bold">operation_not_permitted</emphasis>: if <code><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>
              does not own the mutex.
            </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>
              Timeout-related exceptions.
            </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>
              Timeout-related exceptions.
            </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 <link linkend="class_condition_variable"><code>condition_variable</code></link> 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 <link linkend="condition_variable_wait"><code>condition_variable::wait()</code></link>: <code><phrase role="identifier">wait</phrase><phrase
        role="special">()</phrase></code> will atomically add the fiber to the set
        of fibers waiting on the condition variable, and unlock the <link linkend="class_mutex"><code>mutex</code></link>.
        When the fiber is awakened, the <code><phrase role="identifier">mutex</phrase></code>
        will be locked again before the call to <code><phrase role="identifier">wait</phrase><phrase
        role="special">()</phrase></code> returns. This allows other fibers to acquire
        the <code><phrase role="identifier">mutex</phrase></code> in order to update
        the shared data, and ensures that the data associated with the condition
        is correctly synchronized.
      </para>
      <para>
        <code><phrase role="identifier">wait_for_data_to_process</phrase><phrase
        role="special">()</phrase></code> could equivalently be written:
      </para>
<programlisting><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="comment">// make condition_variable::wait() perform the loop</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="keyword">return</phrase> <phrase role="identifier">data_ready</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>
        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
        <link linkend="condition_variable_notify_one"><code>condition_variable::notify_one()</code></link> or <link linkend="condition_variable_notify_all"><code>condition_variable::notify_all()</code></link> on
        the <link linkend="class_condition_variable"><code>condition_variable</code></link> <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 <link linkend="class_mutex"><code>mutex</code></link> is locked before the shared data is updated,
        but that the <code><phrase role="identifier">mutex</phrase></code> does not
        have to be locked across the call to <link linkend="condition_variable_notify_one"><code>condition_variable::notify_one()</code></link>.
      </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 <link linkend="class_condition_variable"><code>condition_variable</code></link> and
        <link linkend="class_condition_variable_any"><code>condition_variable_any</code></link>. <code><phrase role="identifier">boost</phrase><phrase
        role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase
        role="special">::</phrase><phrase role="identifier">condition_variable</phrase></code>
        can only wait on <ulink url="http://en.cppreference.com/w/cpp/thread/unique_lock"><code><phrase
        role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">unique_lock</phrase></code></ulink><code><phrase
        role="special">&lt;</phrase> <phrase role="identifier">boost</phrase><phrase
        role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase
        role="special">::</phrase></code><link linkend="class_mutex"><code>mutex</code></link><code> <phrase role="special">&gt;</phrase></code>
        while <code><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase
        role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase
        role="identifier">condition_variable_any</phrase></code> can wait on user-defined
        lock types.
      </para>
      <anchor id="condition_variable_spurious_wakeups"/>
      <bridgehead renderas="sect4" id="fiber.synchronization.conditions.h1">
        <phrase id="fiber.synchronization.conditions.no_spurious_wakeups"/><link
        linkend="fiber.synchronization.conditions.no_spurious_wakeups">No Spurious
        Wakeups</link>
      </bridgehead>
      <para>
        Neither <link linkend="class_condition_variable"><code>condition_variable</code></link> nor <link linkend="class_condition_variable_any"><code>condition_variable_any</code></link> are
        subject to spurious wakeup: <link linkend="condition_variable_wait"><code>condition_variable::wait()</code></link> can
        only wake up when <link linkend="condition_variable_notify_one"><code>condition_variable::notify_one()</code></link> or
        <link linkend="condition_variable_notify_all"><code>condition_variable::notify_all()</code></link> is called. Even
        so, it is prudent to use one of the <code><phrase role="identifier">wait</phrase><phrase
        role="special">(</phrase> <phrase role="identifier">lock</phrase><phrase
        role="special">,</phrase> <phrase role="identifier">predicate</phrase> <phrase
        role="special">)</phrase></code> overloads.
      </para>
      <para>
        Consider a set of consumer fibers processing items from a <ulink url="http://en.cppreference.com/w/cpp/container/queue"><code><phrase
        role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">queue</phrase></code></ulink>.
        The queue is continually populated by a set of producer fibers.
      </para>
      <para>
        The consumer fibers might reasonably wait on a <code><phrase role="identifier">condition_variable</phrase></code>
        as long as the queue remains <ulink url="http://en.cppreference.com/w/cpp/container/queue/empty"><code><phrase
        role="identifier">empty</phrase><phrase role="special">()</phrase></code></ulink>.
      </para>
      <para>
        Because producer fibers might <ulink url="http://en.cppreference.com/w/cpp/container/queue/push"><code><phrase
        role="identifier">push</phrase><phrase role="special">()</phrase></code></ulink>
        items to the queue in bursts, they call <link linkend="condition_variable_notify_all"><code>condition_variable::notify_all()</code></link> rather
        than <link linkend="condition_variable_notify_one"><code>condition_variable::notify_one()</code></link>.
      </para>
      <para>
        But a given consumer fiber might well wake up from <link linkend="condition_variable_wait"><code>condition_variable::wait()</code></link> and
        find the queue <code><phrase role="identifier">empty</phrase><phrase role="special">()</phrase></code>,
        because other consumer fibers might already have processed all pending items.
      </para>
      <para>
        (See also <link linkend="spurious_wakeup">spurious wakeup</link>.)
      </para>
      <anchor id="class_cv_status"/>
      <bridgehead renderas="sect4" id="fiber.synchronization.conditions.h2">
        <phrase id="fiber.synchronization.conditions.enumeration__code__phrase_role__identifier__cv_status__phrase___code_"/><link
        linkend="fiber.synchronization.conditions.enumeration__code__phrase_role__identifier__cv_status__phrase___code_">Enumeration
        <code><phrase role="identifier">cv_status</phrase></code></link>
      </bridgehead>
      <para>
        A timed wait operation might return because of timeout or not.
      </para>
<programlisting><phrase role="keyword">enum</phrase> <phrase role="keyword">class</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>
</programlisting>
      <bridgehead renderas="sect4" id="fiber.synchronization.conditions.h3">
        <phrase id="fiber.synchronization.conditions._code__phrase_role__identifier__no_timeout__phrase___code_"/><link
        linkend="fiber.synchronization.conditions._code__phrase_role__identifier__no_timeout__phrase___code_"><code><phrase
        role="identifier">no_timeout</phrase></code></link>
      </bridgehead>
      <variablelist>
        <title></title>
        <varlistentry>
          <term>Effects:</term>
          <listitem>
            <para>
              The condition variable was awakened with <code><phrase role="identifier">notify_one</phrase></code>
              or <code><phrase role="identifier">notify_all</phrase></code>.
            </para>
          </listitem>
        </varlistentry>
      </variablelist>
      <bridgehead renderas="sect4" id="fiber.synchronization.conditions.h4">
        <phrase id="fiber.synchronization.conditions._code__phrase_role__identifier__timeout__phrase___code_"/><link
        linkend="fiber.synchronization.conditions._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 condition variable was awakened by timeout.
            </para>
          </listitem>
        </varlistentry>
      </variablelist>
      <para>
        <bridgehead renderas="sect4" id="class_condition_variable_any_bridgehead">
  <phrase id="class_condition_variable_any"/>
  <link linkend="class_condition_variable_any">Class
        <code>condition_variable_any</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_variable</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> condition_variable_any <phrase role="special">{</phrase>
<phrase role="keyword">public</phrase><phrase role="special">:</phrase>
    condition_variable_any<phrase role="special">();</phrase>
    <phrase role="special">~</phrase>condition_variable_any<phrase role="special">();</phrase>

    condition_variable_any<phrase role="special">(</phrase> condition_variable_any <phrase role="keyword">const</phrase><phrase role="special">&amp;)</phrase> <phrase role="special">=</phrase> <phrase role="keyword">delete</phrase><phrase role="special">;</phrase>
    condition_variable_any <phrase role="special">&amp;</phrase> <phrase role="keyword">operator</phrase><phrase role="special">=(</phrase> condition_variable_any <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">noexcept</phrase><phrase role="special">;</phrase>
    <phrase role="keyword">void</phrase> <phrase role="identifier">notify_all</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>

    template&lt; typename LockType &gt;
    void <phrase role="identifier">wait</phrase><phrase role="special">(</phrase> LockType <phrase role="special">&amp;);</phrase>

    <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> typename LockType, typename <phrase role="identifier">Pred</phrase> <phrase role="special">&gt;</phrase>
    <phrase role="keyword">void</phrase> <phrase role="identifier">wait</phrase><phrase role="special">(</phrase> LockType <phrase role="special">&amp;,</phrase> <phrase role="identifier">Pred</phrase><phrase role="special">);</phrase>

    <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> typename LockType, typename <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> LockType <phrase role="special">&amp;,</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="keyword">template</phrase><phrase role="special">&lt;</phrase> typename LockType, typename <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> LockType <phrase role="special">&amp;,</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">Pred</phrase><phrase role="special">);</phrase>

    <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> typename LockType, typename <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> LockType <phrase role="special">&amp;,</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="keyword">template</phrase><phrase role="special">&lt;</phrase> typename LockType, typename <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> LockType <phrase role="special">&amp;,</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">Pred</phrase><phrase role="special">);</phrase>
<phrase role="special">};</phrase>

<phrase role="special">}}</phrase>
</programlisting>
      <bridgehead renderas="sect4" id="fiber.synchronization.conditions.h5">
        <phrase id="fiber.synchronization.conditions.constructor"/><link linkend="fiber.synchronization.conditions.constructor">Constructor</link>
      </bridgehead>
<programlisting>condition_variable_any<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.h6">
        <phrase id="fiber.synchronization.conditions.destructor"/><link linkend="fiber.synchronization.conditions.destructor">Destructor</link>
      </bridgehead>
<programlisting><phrase role="special">~</phrase>condition_variable_any<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>
      </variablelist>
      <para>
        <bridgehead renderas="sect4" id="condition_variable_any_notify_one_bridgehead">
  <phrase id="condition_variable_any_notify_one"/>
  <link linkend="condition_variable_any_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> <phrase role="keyword">noexcept</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_any_notify_all_bridgehead">
  <phrase id="condition_variable_any_notify_all"/>
  <link linkend="condition_variable_any_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> <phrase role="keyword">noexcept</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>condition_variable_any</code>,
              and retry the wait until that state is reached. A fiber waiting on
              a <code>condition_variable_any</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_any_wait_bridgehead">
  <phrase id="condition_variable_any_wait"/>
  <link linkend="condition_variable_any_wait">Templated
        member function <code>wait</code>()</link>
</bridgehead>
      </para>
<programlisting>template&lt; typename LockType &gt;
    void <phrase role="identifier">wait</phrase><phrase role="special">(</phrase> LockType <phrase role="special">&amp;</phrase> <phrase role="identifier">lk</phrase><phrase role="special">);</phrase>

<phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> typename LockType, typename <phrase role="identifier">Pred</phrase> <phrase role="special">&gt;</phrase>
<phrase role="keyword">void</phrase> <phrase role="identifier">wait</phrase><phrase role="special">(</phrase> LockType <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 <ulink url="http://en.cppreference.com/w/cpp/thread/unique_lock/mutex"><code><phrase
              role="identifier">mutex</phrase><phrase role="special">()</phrase></code></ulink>
              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>. 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_error</phrase></code> if an error
              occurs.
            </para>
          </listitem>
        </varlistentry>
        <varlistentry>
          <term>Note:</term>
          <listitem>
            <para>
              The Precondition is a bit dense. It merely states that all the fibers
              concurrently 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> <link linkend="class_mutex"><code>mutex</code></link>. Three distinct
              objects are involved in any <code>condition_variable_any::wait()</code> call: the
              <code>condition_variable_any</code> itself, the <code><phrase role="identifier">mutex</phrase></code>
              coordinating access between fibers and a local lock object (e.g. <ulink
              url="http://en.cppreference.com/w/cpp/thread/unique_lock"><code><phrase
              role="identifier">std</phrase><phrase role="special">::</phrase><phrase
              role="identifier">unique_lock</phrase></code></ulink>). In general,
              you can partition the lifespan of a given <code>condition_variable_any</code> instance
              into periods with one or more fibers waiting on it, separated by periods
              when no fibers are waiting on it. When more than one fiber is waiting
              on that <code>condition_variable_any</code>, all must pass lock objects referencing
              the <emphasis>same</emphasis> <code><phrase role="identifier">mutex</phrase></code>
              instance.
            </para>
          </listitem>
        </varlistentry>
      </variablelist>
      <para>
        <bridgehead renderas="sect4" id="condition_variable_any_wait_until_bridgehead">
  <phrase id="condition_variable_any_wait_until"/>
  <link linkend="condition_variable_any_wait_until">Templated
        member function <code>wait_until</code>()</link>
</bridgehead>
      </para>
<programlisting><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> typename LockType, typename <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> LockType <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">abs_time</phrase><phrase role="special">);</phrase>

<phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> typename LockType, typename <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> LockType <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">abs_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">abs_time</phrase></code>.
              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">abs_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_error</phrase></code> if an error
              occurs or timeout-related exceptions.
            </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">abs_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">abs_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_any_wait"><code>condition_variable_any::wait()</code></link>.
            </para>
          </listitem>
        </varlistentry>
      </variablelist>
      <para>
        <bridgehead renderas="sect4" id="condition_variable_any_wait_for_bridgehead">
  <phrase id="condition_variable_any_wait_for"/>
  <link linkend="condition_variable_any_wait_for">Templated
        member function <code>wait_for</code>()</link>
</bridgehead>
      </para>
<programlisting><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> typename LockType, typename <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> LockType <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">rel_time</phrase><phrase role="special">);</phrase>

<phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> typename LockType, typename <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> LockType <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">rel_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_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">rel_time</phrase></code>
              has elapsed. 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">rel_time</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">rel_time</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_error</phrase></code> if an error
              occurs or timeout-related exceptions.
            </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">rel_time</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">rel_time</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_any_wait"><code>condition_variable_any::wait()</code></link>.
            </para>
          </listitem>
        </varlistentry>
      </variablelist>
      <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_variable</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> condition_variable <phrase role="special">{</phrase>
<phrase role="keyword">public</phrase><phrase role="special">:</phrase>
    condition_variable<phrase role="special">();</phrase>
    <phrase role="special">~</phrase>condition_variable<phrase role="special">();</phrase>

    condition_variable<phrase role="special">(</phrase> condition_variable <phrase role="keyword">const</phrase><phrase role="special">&amp;)</phrase> <phrase role="special">=</phrase> <phrase role="keyword">delete</phrase><phrase role="special">;</phrase>
    condition_variable <phrase role="special">&amp;</phrase> <phrase role="keyword">operator</phrase><phrase role="special">=(</phrase> condition_variable <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">noexcept</phrase><phrase role="special">;</phrase>
    <phrase role="keyword">void</phrase> <phrase role="identifier">notify_all</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>

    void <phrase role="identifier">wait</phrase><phrase role="special">(</phrase> std::unique_lock&lt; mutex &gt; <phrase role="special">&amp;);</phrase>

    <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> typename <phrase role="identifier">Pred</phrase> <phrase role="special">&gt;</phrase>
    <phrase role="keyword">void</phrase> <phrase role="identifier">wait</phrase><phrase role="special">(</phrase> std::unique_lock&lt; mutex &gt; <phrase role="special">&amp;,</phrase> <phrase role="identifier">Pred</phrase><phrase role="special">);</phrase>

    <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> typename <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> std::unique_lock&lt; mutex &gt; <phrase role="special">&amp;,</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="keyword">template</phrase><phrase role="special">&lt;</phrase> typename <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> std::unique_lock&lt; mutex &gt; <phrase role="special">&amp;,</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">Pred</phrase><phrase role="special">);</phrase>

    <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> typename <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> std::unique_lock&lt; mutex &gt; <phrase role="special">&amp;,</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="keyword">template</phrase><phrase role="special">&lt;</phrase> typename <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> std::unique_lock&lt; mutex &gt; <phrase role="special">&amp;,</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">Pred</phrase><phrase role="special">);</phrase>
<phrase role="special">};</phrase>

<phrase role="special">}}</phrase>
</programlisting>
      <bridgehead renderas="sect4" id="fiber.synchronization.conditions.h7">
        <phrase id="fiber.synchronization.conditions.constructor0"/><link linkend="fiber.synchronization.conditions.constructor0">Constructor</link>
      </bridgehead>
<programlisting>condition_variable<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.h8">
        <phrase id="fiber.synchronization.conditions.destructor0"/><link linkend="fiber.synchronization.conditions.destructor0">Destructor</link>
      </bridgehead>
<programlisting><phrase role="special">~</phrase>condition_variable<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>
      </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> <phrase role="keyword">noexcept</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> <phrase role="keyword">noexcept</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>condition_variable</code>,
              and retry the wait until that state is reached. A fiber waiting on
              a <code>condition_variable</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>void <phrase role="identifier">wait</phrase><phrase role="special">(</phrase> std::unique_lock&lt; mutex &gt; <phrase role="special">&amp;</phrase> <phrase role="identifier">lk</phrase><phrase role="special">);</phrase>

<phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> typename <phrase role="identifier">Pred</phrase> <phrase role="special">&gt;</phrase>
<phrase role="keyword">void</phrase> <phrase role="identifier">wait</phrase><phrase role="special">(</phrase> std::unique_lock&lt; mutex &gt; <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 <ulink url="http://en.cppreference.com/w/cpp/thread/unique_lock/mutex"><code><phrase
              role="identifier">mutex</phrase><phrase role="special">()</phrase></code></ulink>
              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>. 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_error</phrase></code> if an error
              occurs.
            </para>
          </listitem>
        </varlistentry>
        <varlistentry>
          <term>Note:</term>
          <listitem>
            <para>
              The Precondition is a bit dense. It merely states that all the fibers
              concurrently 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> <link linkend="class_mutex"><code>mutex</code></link>. Three distinct
              objects are involved in any <code>condition_variable::wait()</code> call: the <code>condition_variable</code> itself,
              the <code><phrase role="identifier">mutex</phrase></code> coordinating
              access between fibers and a local lock object (e.g. <ulink url="http://en.cppreference.com/w/cpp/thread/unique_lock"><code><phrase
              role="identifier">std</phrase><phrase role="special">::</phrase><phrase
              role="identifier">unique_lock</phrase></code></ulink>). In general,
              you can partition the lifespan of a given <code>condition_variable</code> instance
              into periods with one or more fibers waiting on it, separated by periods
              when no fibers are waiting on it. When more than one fiber is waiting
              on that <code>condition_variable</code>, all must pass lock objects referencing
              the <emphasis>same</emphasis> <code><phrase role="identifier">mutex</phrase></code>
              instance.
            </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> typename <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> std::unique_lock&lt; mutex &gt; <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">abs_time</phrase><phrase role="special">);</phrase>

<phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> typename <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> std::unique_lock&lt; mutex &gt; <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">abs_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">abs_time</phrase></code>.
              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">abs_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_error</phrase></code> if an error
              occurs or timeout-related exceptions.
            </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">abs_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">abs_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> typename <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> std::unique_lock&lt; mutex &gt; <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">rel_time</phrase><phrase role="special">);</phrase>

<phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> typename <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> std::unique_lock&lt; mutex &gt; <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">rel_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_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">rel_time</phrase></code>
              has elapsed. 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">rel_time</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">rel_time</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_error</phrase></code> if an error
              occurs or timeout-related exceptions.
            </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">rel_time</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">rel_time</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 <quote>main</quote> 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 <quote>main</quote> 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 <quote>simultaneously,</quote>
          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">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">barrier</phrase> <phrase role="special">{</phrase>
<phrase role="keyword">public</phrase><phrase role="special">:</phrase>
    <phrase role="keyword">explicit</phrase> <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="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="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="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>

<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="keyword">explicit</phrase> <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">fiber_error</phrase></code>
            </para>
          </listitem>
        </varlistentry>
        <varlistentry>
          <term>Error Conditions:</term>
          <listitem>
            <para>
              <emphasis role="bold">invalid_argument</emphasis>: 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_error</phrase></code>
            </para>
          </listitem>
        </varlistentry>
      </variablelist>
    </section>
    <section id="fiber.synchronization.channels">
      <title><link linkend="fiber.synchronization.channels">Channels</link></title>
      <para>
        A channel is a model to communicate and synchronize <code><phrase role="identifier">Threads</phrase>
        <phrase role="identifier">of</phrase> <phrase role="identifier">Execution</phrase></code>
        <footnote id="fiber.synchronization.channels.f0">
        <para>
          The smallest ordered sequence of instructions that can be managed independently
          by a scheduler is called a <code><phrase role="identifier">Thread</phrase>
          <phrase role="identifier">of</phrase> <phrase role="identifier">Execution</phrase></code>.
        </para>
        </footnote> via message passing.
      </para>
      <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>
      <section id="fiber.synchronization.channels.buffered_channel">
        <title><link linkend="fiber.synchronization.channels.buffered_channel">Buffered
        Channel</link></title>
        <para>
          <emphasis role="bold">Boost.Fiber</emphasis> provides a bounded, buffered
          channel (MPMC queue) suitable to synchonize fibers (running on same or
          different threads) via asynchronouss 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">buffered_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">chan</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">chan</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">chan</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">chan</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">chan</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">chan</phrase><phrase role="special">{</phrase> <phrase role="number">2</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">std</phrase><phrase role="special">::</phrase><phrase role="identifier">ref</phrase><phrase role="special">(</phrase> <phrase role="identifier">chan</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">std</phrase><phrase role="special">::</phrase><phrase role="identifier">ref</phrase><phrase role="special">(</phrase> <phrase role="identifier">chan</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>
        <para>
          Class <code><phrase role="identifier">buffered_channel</phrase></code>
          supports range-for syntax:
        </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">buffered_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">foo</phrase><phrase role="special">(</phrase> <phrase role="identifier">channel_t</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">chan</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
    <phrase role="identifier">chan</phrase><phrase role="special">.</phrase><phrase role="identifier">push</phrase><phrase role="special">(</phrase> <phrase role="number">1</phrase><phrase role="special">);</phrase>
    <phrase role="identifier">chan</phrase><phrase role="special">.</phrase><phrase role="identifier">push</phrase><phrase role="special">(</phrase> <phrase role="number">1</phrase><phrase role="special">);</phrase>
    <phrase role="identifier">chan</phrase><phrase role="special">.</phrase><phrase role="identifier">push</phrase><phrase role="special">(</phrase> <phrase role="number">2</phrase><phrase role="special">);</phrase>
    <phrase role="identifier">chan</phrase><phrase role="special">.</phrase><phrase role="identifier">push</phrase><phrase role="special">(</phrase> <phrase role="number">3</phrase><phrase role="special">);</phrase>
    <phrase role="identifier">chan</phrase><phrase role="special">.</phrase><phrase role="identifier">push</phrase><phrase role="special">(</phrase> <phrase role="number">5</phrase><phrase role="special">);</phrase>
    <phrase role="identifier">chan</phrase><phrase role="special">.</phrase><phrase role="identifier">push</phrase><phrase role="special">(</phrase> <phrase role="number">8</phrase><phrase role="special">);</phrase>
    <phrase role="identifier">chan</phrase><phrase role="special">.</phrase><phrase role="identifier">push</phrase><phrase role="special">(</phrase> <phrase role="number">12</phrase><phrase role="special">);</phrase>
    <phrase role="identifier">chan</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">bar</phrase><phrase role="special">(</phrase> <phrase role="identifier">channel_t</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">chan</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
    <phrase role="keyword">for</phrase> <phrase role="special">(</phrase> <phrase role="keyword">unsigned</phrase> <phrase role="keyword">int</phrase> <phrase role="identifier">value</phrase> <phrase role="special">:</phrase> <phrase role="identifier">chan</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">value</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>
<phrase role="special">}</phrase>
</programlisting>
        <para>
          <bridgehead renderas="sect4" id="class_buffered_channel_bridgehead">
  <phrase id="class_buffered_channel"/>
  <link linkend="class_buffered_channel">Template
          <code>buffered_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">buffered_channel</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">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">buffered_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="keyword">class</phrase> <phrase role="identifier">iterator</phrase><phrase role="special">;</phrase>

    <phrase role="keyword">explicit</phrase> <phrase role="identifier">buffered_channel</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">capacity</phrase><phrase role="special">);</phrase>

    <phrase role="identifier">buffered_channel</phrase><phrase role="special">(</phrase> <phrase role="identifier">buffered_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">buffered_channel</phrase> <phrase role="special">&amp;</phrase> <phrase role="keyword">operator</phrase><phrase role="special">=(</phrase> <phrase role="identifier">buffered_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="keyword">noexcept</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>

<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">buffered_channel</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">T</phrase> <phrase role="special">&gt;::</phrase><phrase role="identifier">iterator</phrase> <phrase role="identifier">begin</phrase><phrase role="special">(</phrase> <phrase role="identifier">buffered_channel</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">T</phrase> <phrase role="special">&gt;</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">chan</phrase><phrase role="special">);</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="identifier">buffered_channel</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">T</phrase> <phrase role="special">&gt;::</phrase><phrase role="identifier">iterator</phrase> <phrase role="identifier">end</phrase><phrase role="special">(</phrase> <phrase role="identifier">buffered_channel</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">T</phrase> <phrase role="special">&gt;</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">chan</phrase><phrase role="special">);</phrase>

<phrase role="special">}}</phrase>
</programlisting>
        <bridgehead renderas="sect5" id="fiber.synchronization.channels.buffered_channel.h0">
          <phrase id="fiber.synchronization.channels.buffered_channel.constructor"/><link
          linkend="fiber.synchronization.channels.buffered_channel.constructor">Constructor</link>
        </bridgehead>
<programlisting><phrase role="keyword">explicit</phrase> <phrase role="identifier">buffered_channel</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">capacity</phrase><phrase role="special">);</phrase>
</programlisting>
        <variablelist>
          <title></title>
          <varlistentry>
            <term>Preconditions:</term>
            <listitem>
              <para>
                <code><phrase role="number">2</phrase><phrase role="special">&lt;=</phrase><phrase
                role="identifier">capacity</phrase> <phrase role="special">&amp;&amp;</phrase>
                <phrase role="number">0</phrase><phrase role="special">==(</phrase><phrase
                role="identifier">capacity</phrase> <phrase role="special">&amp;</phrase>
                <phrase role="special">(</phrase><phrase role="identifier">capacity</phrase><phrase
                role="special">-</phrase><phrase role="number">1</phrase><phrase
                role="special">))</phrase></code>
              </para>
            </listitem>
          </varlistentry>
          <varlistentry>
            <term>Effects:</term>
            <listitem>
              <para>
                The constructor constructs an object of class <code><phrase role="identifier">buffered_channel</phrase></code>
                with an internal buffer of size <code><phrase role="identifier">capacity</phrase></code>.
              </para>
            </listitem>
          </varlistentry>
          <varlistentry>
            <term>Throws:</term>
            <listitem>
              <para>
                <code><phrase role="identifier">fiber_error</phrase></code>
              </para>
            </listitem>
          </varlistentry>
          <varlistentry>
            <term>Error Conditions:</term>
            <listitem>
              <para>
                <emphasis role="bold">invalid_argument</emphasis>: if <code><phrase
                role="number">0</phrase><phrase role="special">==</phrase><phrase
                role="identifier">capacity</phrase> <phrase role="special">||</phrase>
                <phrase role="number">0</phrase><phrase role="special">!=(</phrase><phrase
                role="identifier">capacity</phrase> <phrase role="special">&amp;</phrase>
                <phrase role="special">(</phrase><phrase role="identifier">capacity</phrase><phrase
                role="special">-</phrase><phrase role="number">1</phrase><phrase
                role="special">))</phrase></code>.
              </para>
            </listitem>
          </varlistentry>
          <varlistentry>
            <term>Notes:</term>
            <listitem>
              <para>
                A <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 not block until the number
                of values in the channel becomes equal to <code><phrase role="identifier">capacity</phrase></code>.
                The channel can hold only <code><phrase role="identifier">capacity</phrase>
                <phrase role="special">-</phrase> <phrase role="number">1</phrase></code>
                elements, otherwise it is considered to be full.
              </para>
            </listitem>
          </varlistentry>
        </variablelist>
        <para>
          <bridgehead renderas="sect4" id="buffered_channel_close_bridgehead">
  <phrase id="buffered_channel_close"/>
  <link linkend="buffered_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> <phrase role="keyword">noexcept</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="buffered_channel_push_bridgehead">
  <phrase id="buffered_channel_push"/>
  <link linkend="buffered_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>.
                If the channel is full, the fiber is blocked.
              </para>
            </listitem>
          </varlistentry>
          <varlistentry>
            <term>Throws:</term>
            <listitem>
              <para>
                Exceptions thrown by copy- or move-operations.
              </para>
            </listitem>
          </varlistentry>
        </variablelist>
        <para>
          <bridgehead renderas="sect4" id="buffered_channel_try_push_bridgehead">
  <phrase id="buffered_channel_try_push"/>
  <link linkend="buffered_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 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>.
                If the channel is full, it doesn't block and returns <code><phrase
                role="identifier">full</phrase></code>.
              </para>
            </listitem>
          </varlistentry>
          <varlistentry>
            <term>Throws:</term>
            <listitem>
              <para>
                Exceptions thrown by copy- or move-operations.
              </para>
            </listitem>
          </varlistentry>
        </variablelist>
        <para>
          <bridgehead renderas="sect4" id="buffered_channel_pop_bridgehead">
  <phrase id="buffered_channel_pop"/>
  <link linkend="buffered_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>
                Exceptions thrown by copy- or move-operations.
              </para>
            </listitem>
          </varlistentry>
        </variablelist>
        <para>
          <bridgehead renderas="sect4" id="buffered_channel_value_pop_bridgehead">
  <phrase id="buffered_channel_value_pop"/>
  <link linkend="buffered_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">fiber_error</phrase></code> if <code><phrase
                role="special">*</phrase><phrase role="keyword">this</phrase></code>
                is closed or by copy- or move-operations.
              </para>
            </listitem>
          </varlistentry>
          <varlistentry>
            <term>Error conditions:</term>
            <listitem>
              <para>
                <code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase
                role="identifier">errc</phrase><phrase role="special">::</phrase><phrase
                role="identifier">operation_not_permitted</phrase></code>
              </para>
            </listitem>
          </varlistentry>
        </variablelist>
        <para>
          <bridgehead renderas="sect4" id="buffered_channel_try_pop_bridgehead">
  <phrase id="buffered_channel_try_pop"/>
  <link linkend="buffered_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>
                Exceptions thrown by copy- or move-operations.
              </para>
            </listitem>
          </varlistentry>
        </variablelist>
        <para>
          <bridgehead renderas="sect4" id="buffered_channel_pop_wait_for_bridgehead">
  <phrase id="buffered_channel_pop_wait_for"/>
  <link linkend="buffered_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>
                timeout-related exceptions or by copy- or move-operations.
              </para>
            </listitem>
          </varlistentry>
        </variablelist>
        <para>
          <bridgehead renderas="sect4" id="buffered_channel_pop_wait_until_bridgehead">
  <phrase id="buffered_channel_pop_wait_until"/>
  <link linkend="buffered_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>
                timeout-related exceptions or by copy- or move-operations.
              </para>
            </listitem>
          </varlistentry>
        </variablelist>
        <bridgehead renderas="sect5" id="fiber.synchronization.channels.buffered_channel.h1">
          <phrase id="fiber.synchronization.channels.buffered_channel.non_member_function__code__phrase_role__identifier__begin__phrase__phrase_role__special_____phrase___phrase_role__identifier__buffered_channel__phrase__phrase_role__special___lt___phrase___phrase_role__identifier__t__phrase___phrase_role__special___gt___phrase___phrase_role__special___amp____phrase___code_"/><link
          linkend="fiber.synchronization.channels.buffered_channel.non_member_function__code__phrase_role__identifier__begin__phrase__phrase_role__special_____phrase___phrase_role__identifier__buffered_channel__phrase__phrase_role__special___lt___phrase___phrase_role__identifier__t__phrase___phrase_role__special___gt___phrase___phrase_role__special___amp____phrase___code_">Non-member
          function <code><phrase role="identifier">begin</phrase><phrase role="special">(</phrase>
          <phrase role="identifier">buffered_channel</phrase><phrase role="special">&lt;</phrase>
          <phrase role="identifier">T</phrase> <phrase role="special">&gt;</phrase>
          <phrase role="special">&amp;)</phrase></code></link>
        </bridgehead>
<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">buffered_channel</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">T</phrase> <phrase role="special">&gt;::</phrase><phrase role="identifier">iterator</phrase> <phrase role="identifier">begin</phrase><phrase role="special">(</phrase> <phrase role="identifier">buffered_channel</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">T</phrase> <phrase role="special">&gt;</phrase> <phrase role="special">&amp;);</phrase>
</programlisting>
        <variablelist>
          <title></title>
          <varlistentry>
            <term>Returns:</term>
            <listitem>
              <para>
                Returns a range-iterator (input-iterator).
              </para>
            </listitem>
          </varlistentry>
        </variablelist>
        <bridgehead renderas="sect5" id="fiber.synchronization.channels.buffered_channel.h2">
          <phrase id="fiber.synchronization.channels.buffered_channel.non_member_function__code__phrase_role__identifier__end__phrase__phrase_role__special_____phrase___phrase_role__identifier__buffered_channel__phrase__phrase_role__special___lt___phrase___phrase_role__identifier__t__phrase___phrase_role__special___gt___phrase___phrase_role__special___amp____phrase___code_"/><link
          linkend="fiber.synchronization.channels.buffered_channel.non_member_function__code__phrase_role__identifier__end__phrase__phrase_role__special_____phrase___phrase_role__identifier__buffered_channel__phrase__phrase_role__special___lt___phrase___phrase_role__identifier__t__phrase___phrase_role__special___gt___phrase___phrase_role__special___amp____phrase___code_">Non-member
          function <code><phrase role="identifier">end</phrase><phrase role="special">(</phrase>
          <phrase role="identifier">buffered_channel</phrase><phrase role="special">&lt;</phrase>
          <phrase role="identifier">T</phrase> <phrase role="special">&gt;</phrase>
          <phrase role="special">&amp;)</phrase></code></link>
        </bridgehead>
<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">buffered_channel</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">R</phrase> <phrase role="special">&gt;::</phrase><phrase role="identifier">iterator</phrase> <phrase role="identifier">end</phrase><phrase role="special">(</phrase> <phrase role="identifier">buffered_channel</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">T</phrase> <phrase role="special">&gt;</phrase> <phrase role="special">&amp;);</phrase>
</programlisting>
        <variablelist>
          <title></title>
          <varlistentry>
            <term>Returns:</term>
            <listitem>
              <para>
                Returns an end range-iterator (input-iterator).
              </para>
            </listitem>
          </varlistentry>
        </variablelist>
      </section>
      <section id="fiber.synchronization.channels.unbuffered_channel">
        <title><link linkend="fiber.synchronization.channels.unbuffered_channel">Unbuffered
        Channel</link></title>
        <para>
          <emphasis role="bold">Boost.Fiber</emphasis> provides template <code><phrase
          role="identifier">unbuffered_channel</phrase></code> suitable to synchonize
          fibers (running on same or different threads) via synchronous message passing.
          A fiber waiting to consume an value will block until the value is produced.
          If a fiber attempts to send a value through an unbuffered channel and no
          fiber is waiting to receive the value, the channel will block the sending
          fiber.
        </para>
        <para>
          The unbuffered channel acts as an <code><phrase role="identifier">rendezvous</phrase>
          <phrase role="identifier">point</phrase></code>.
        </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">unbuffered_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">chan</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">chan</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">chan</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">chan</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">chan</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">chan</phrase><phrase role="special">{</phrase> <phrase role="number">1</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">std</phrase><phrase role="special">::</phrase><phrase role="identifier">ref</phrase><phrase role="special">(</phrase> <phrase role="identifier">chan</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">std</phrase><phrase role="special">::</phrase><phrase role="identifier">ref</phrase><phrase role="special">(</phrase> <phrase role="identifier">chan</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>
        <para>
          Range-for syntax is supported:
        </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">unbuffered_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">foo</phrase><phrase role="special">(</phrase> <phrase role="identifier">channel_t</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">chan</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
    <phrase role="identifier">chan</phrase><phrase role="special">.</phrase><phrase role="identifier">push</phrase><phrase role="special">(</phrase> <phrase role="number">1</phrase><phrase role="special">);</phrase>
    <phrase role="identifier">chan</phrase><phrase role="special">.</phrase><phrase role="identifier">push</phrase><phrase role="special">(</phrase> <phrase role="number">1</phrase><phrase role="special">);</phrase>
    <phrase role="identifier">chan</phrase><phrase role="special">.</phrase><phrase role="identifier">push</phrase><phrase role="special">(</phrase> <phrase role="number">2</phrase><phrase role="special">);</phrase>
    <phrase role="identifier">chan</phrase><phrase role="special">.</phrase><phrase role="identifier">push</phrase><phrase role="special">(</phrase> <phrase role="number">3</phrase><phrase role="special">);</phrase>
    <phrase role="identifier">chan</phrase><phrase role="special">.</phrase><phrase role="identifier">push</phrase><phrase role="special">(</phrase> <phrase role="number">5</phrase><phrase role="special">);</phrase>
    <phrase role="identifier">chan</phrase><phrase role="special">.</phrase><phrase role="identifier">push</phrase><phrase role="special">(</phrase> <phrase role="number">8</phrase><phrase role="special">);</phrase>
    <phrase role="identifier">chan</phrase><phrase role="special">.</phrase><phrase role="identifier">push</phrase><phrase role="special">(</phrase> <phrase role="number">12</phrase><phrase role="special">);</phrase>
    <phrase role="identifier">chan</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">bar</phrase><phrase role="special">(</phrase> <phrase role="identifier">channel_t</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">chan</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
    <phrase role="keyword">for</phrase> <phrase role="special">(</phrase> <phrase role="keyword">unsigned</phrase> <phrase role="keyword">int</phrase> <phrase role="identifier">value</phrase> <phrase role="special">:</phrase> <phrase role="identifier">chan</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">value</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>
<phrase role="special">}</phrase>
</programlisting>
        <para>
          <bridgehead renderas="sect4" id="class_unbuffered_channel_bridgehead">
  <phrase id="class_unbuffered_channel"/>
  <link linkend="class_unbuffered_channel">Template
          <code>unbuffered_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">unbuffered_channel</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">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">unbuffered_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="keyword">class</phrase> <phrase role="identifier">iterator</phrase><phrase role="special">;</phrase>

    <phrase role="identifier">unbuffered_channel</phrase><phrase role="special">();</phrase>

    <phrase role="identifier">unbuffered_channel</phrase><phrase role="special">(</phrase> <phrase role="identifier">unbuffered_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">unbuffered_channel</phrase> <phrase role="special">&amp;</phrase> <phrase role="keyword">operator</phrase><phrase role="special">=(</phrase> <phrase role="identifier">unbuffered_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="keyword">noexcept</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">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="special">};</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="identifier">unbuffered_channel</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">T</phrase> <phrase role="special">&gt;::</phrase><phrase role="identifier">iterator</phrase> <phrase role="identifier">begin</phrase><phrase role="special">(</phrase> <phrase role="identifier">unbuffered_channel</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">T</phrase> <phrase role="special">&gt;</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">chan</phrase><phrase role="special">);</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="identifier">unbuffered_channel</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">T</phrase> <phrase role="special">&gt;::</phrase><phrase role="identifier">iterator</phrase> <phrase role="identifier">end</phrase><phrase role="special">(</phrase> <phrase role="identifier">unbuffered_channel</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">T</phrase> <phrase role="special">&gt;</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">chan</phrase><phrase role="special">);</phrase>

<phrase role="special">}}</phrase>
</programlisting>
        <bridgehead renderas="sect5" id="fiber.synchronization.channels.unbuffered_channel.h0">
          <phrase id="fiber.synchronization.channels.unbuffered_channel.constructor"/><link
          linkend="fiber.synchronization.channels.unbuffered_channel.constructor">Constructor</link>
        </bridgehead>
<programlisting><phrase role="identifier">unbuffered_channel</phrase><phrase role="special">();</phrase>
</programlisting>
        <variablelist>
          <title></title>
          <varlistentry>
            <term>Effects:</term>
            <listitem>
              <para>
                The constructor constructs an object of class <code><phrase role="identifier">unbuffered_channel</phrase></code>.
              </para>
            </listitem>
          </varlistentry>
        </variablelist>
        <para>
          <bridgehead renderas="sect4" id="unbuffered_channel_close_bridgehead">
  <phrase id="unbuffered_channel_close"/>
  <link linkend="unbuffered_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> <phrase role="keyword">noexcept</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="unbuffered_channel_push_bridgehead">
  <phrase id="unbuffered_channel_push"/>
  <link linkend="unbuffered_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>
                Exceptions thrown by copy- or move-operations.
              </para>
            </listitem>
          </varlistentry>
        </variablelist>
        <para>
          <bridgehead renderas="sect4" id="unbuffered_channel_pop_bridgehead">
  <phrase id="unbuffered_channel_pop"/>
  <link linkend="unbuffered_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>
                Exceptions thrown by copy- or move-operations.
              </para>
            </listitem>
          </varlistentry>
        </variablelist>
        <para>
          <bridgehead renderas="sect4" id="unbuffered_channel_value_pop_bridgehead">
  <phrase id="unbuffered_channel_value_pop"/>
  <link linkend="unbuffered_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">fiber_error</phrase></code> if <code><phrase
                role="special">*</phrase><phrase role="keyword">this</phrase></code>
                is closed or by copy- or move-operations.
              </para>
            </listitem>
          </varlistentry>
          <varlistentry>
            <term>Error conditions:</term>
            <listitem>
              <para>
                <code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase
                role="identifier">errc</phrase><phrase role="special">::</phrase><phrase
                role="identifier">operation_not_permitted</phrase></code>
              </para>
            </listitem>
          </varlistentry>
        </variablelist>
        <para>
          <bridgehead renderas="sect4" id="unbuffered_channel_pop_wait_for_bridgehead">
  <phrase id="unbuffered_channel_pop_wait_for"/>
  <link linkend="unbuffered_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>
                timeout-related exceptions or by copy- or move-operations.
              </para>
            </listitem>
          </varlistentry>
        </variablelist>
        <para>
          <bridgehead renderas="sect4" id="unbuffered_channel_pop_wait_until_bridgehead">
  <phrase id="unbuffered_channel_pop_wait_until"/>
  <link linkend="unbuffered_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>
                timeout-related exceptions or by copy- or move-operations.
              </para>
            </listitem>
          </varlistentry>
        </variablelist>
        <bridgehead renderas="sect5" id="fiber.synchronization.channels.unbuffered_channel.h1">
          <phrase id="fiber.synchronization.channels.unbuffered_channel.non_member_function__code__phrase_role__identifier__begin__phrase__phrase_role__special_____phrase___phrase_role__identifier__unbuffered_channel__phrase__phrase_role__special___lt___phrase___phrase_role__identifier__t__phrase___phrase_role__special___gt___phrase___phrase_role__special___amp____phrase___code_"/><link
          linkend="fiber.synchronization.channels.unbuffered_channel.non_member_function__code__phrase_role__identifier__begin__phrase__phrase_role__special_____phrase___phrase_role__identifier__unbuffered_channel__phrase__phrase_role__special___lt___phrase___phrase_role__identifier__t__phrase___phrase_role__special___gt___phrase___phrase_role__special___amp____phrase___code_">Non-member
          function <code><phrase role="identifier">begin</phrase><phrase role="special">(</phrase>
          <phrase role="identifier">unbuffered_channel</phrase><phrase role="special">&lt;</phrase>
          <phrase role="identifier">T</phrase> <phrase role="special">&gt;</phrase>
          <phrase role="special">&amp;)</phrase></code></link>
        </bridgehead>
<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">unbuffered_channel</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">T</phrase> <phrase role="special">&gt;::</phrase><phrase role="identifier">iterator</phrase> <phrase role="identifier">begin</phrase><phrase role="special">(</phrase> <phrase role="identifier">unbuffered_channel</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">T</phrase> <phrase role="special">&gt;</phrase> <phrase role="special">&amp;);</phrase>
</programlisting>
        <variablelist>
          <title></title>
          <varlistentry>
            <term>Returns:</term>
            <listitem>
              <para>
                Returns a range-iterator (input-iterator).
              </para>
            </listitem>
          </varlistentry>
        </variablelist>
        <bridgehead renderas="sect5" id="fiber.synchronization.channels.unbuffered_channel.h2">
          <phrase id="fiber.synchronization.channels.unbuffered_channel.non_member_function__code__phrase_role__identifier__end__phrase__phrase_role__special_____phrase___phrase_role__identifier__unbuffered_channel__phrase__phrase_role__special___lt___phrase___phrase_role__identifier__t__phrase___phrase_role__special___gt___phrase___phrase_role__special___amp____phrase___code_"/><link
          linkend="fiber.synchronization.channels.unbuffered_channel.non_member_function__code__phrase_role__identifier__end__phrase__phrase_role__special_____phrase___phrase_role__identifier__unbuffered_channel__phrase__phrase_role__special___lt___phrase___phrase_role__identifier__t__phrase___phrase_role__special___gt___phrase___phrase_role__special___amp____phrase___code_">Non-member
          function <code><phrase role="identifier">end</phrase><phrase role="special">(</phrase>
          <phrase role="identifier">unbuffered_channel</phrase><phrase role="special">&lt;</phrase>
          <phrase role="identifier">T</phrase> <phrase role="special">&gt;</phrase>
          <phrase role="special">&amp;)</phrase></code></link>
        </bridgehead>
<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">unbuffered_channel</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">R</phrase> <phrase role="special">&gt;::</phrase><phrase role="identifier">iterator</phrase> <phrase role="identifier">end</phrase><phrase role="special">(</phrase> <phrase role="identifier">unbuffered_channel</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">T</phrase> <phrase role="special">&gt;</phrase> <phrase role="special">&amp;);</phrase>
</programlisting>
        <variablelist>
          <title></title>
          <varlistentry>
            <term>Returns:</term>
            <listitem>
              <para>
                Returns an end range-iterator (input-iterator).
              </para>
            </listitem>
          </varlistentry>
        </variablelist>
      </section>
    </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: <quote>How do
        I return a value from a fiber?</quote> 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>
        <note>
          <para>
            Deferred futures are not supported.
          </para>
        </note>
        <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="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">future</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">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="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">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="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">&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="special">~</phrase><phrase role="identifier">future</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="comment">// member only of generic 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 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 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>

<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> <phrase role="keyword">noexcept</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>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>    <phrase role="comment">// member only of generic 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 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 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 <link linkend="promise_set_value"><code>promise::set_value()</code></link> is called, returns
                the value. If <link linkend="promise_set_exception"><code>promise::set_exception()</code></link> 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>,
                <code><phrase role="identifier">future_errc</phrase><phrase role="special">::</phrase><phrase
                role="identifier">broken_promise</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>.
              </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>.
              </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 timeout-related exceptions.
              </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 timeout-related exceptions.
              </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="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">future</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">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">&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">&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>

<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">&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>
</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>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">&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">&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 <link linkend="promise_set_value"><code>promise::set_value()</code></link> is called, returns
                the value. If <link linkend="promise_set_exception"><code>promise::set_exception()</code></link> 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>,
                <code><phrase role="identifier">future_errc</phrase><phrase role="special">::</phrase><phrase
                role="identifier">broken_promise</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>.
              </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>.
              </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 timeout-related exceptions.
              </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 timeout-related exceptions.
              </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">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">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">class</phrase> <phrase role="identifier">Function</phrase><phrase role="special">,</phrase> <phrase role="keyword">class</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="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">result_of_t</phrase><phrase role="special">&lt;</phrase>
        <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">decay_t</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Function</phrase> <phrase role="special">&gt;(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">decay_t</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Args</phrase> <phrase role="special">&gt;</phrase> <phrase role="special">...</phrase> <phrase role="special">)</phrase>
    <phrase role="special">&gt;</phrase>
<phrase role="special">&gt;</phrase>
<phrase role="identifier">async</phrase><phrase role="special">(</phrase> <phrase role="identifier">Function</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">class</phrase> <phrase role="identifier">Function</phrase><phrase role="special">,</phrase> <phrase role="keyword">class</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="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">result_of_t</phrase><phrase role="special">&lt;</phrase>
        <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">decay_t</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Function</phrase> <phrase role="special">&gt;(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">decay_t</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Args</phrase> <phrase role="special">&gt;</phrase> <phrase role="special">...</phrase> <phrase role="special">)</phrase>
    <phrase role="special">&gt;</phrase>
<phrase role="special">&gt;</phrase>
<phrase role="identifier">async</phrase><phrase role="special">(</phrase> <link linkend="class_launch"><code><phrase role="identifier">launch</phrase></code></link> <phrase role="identifier">policy</phrase><phrase role="special">,</phrase> <phrase role="identifier">Function</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> <link linkend="stack_allocator_concept"><code><phrase role="identifier">StackAllocator</phrase></code></link><phrase role="special">,</phrase> <phrase role="keyword">class</phrase> <phrase role="identifier">Function</phrase><phrase role="special">,</phrase> <phrase role="keyword">class</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="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">result_of_t</phrase><phrase role="special">&lt;</phrase>
        <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">decay_t</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Function</phrase> <phrase role="special">&gt;(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">decay_t</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Args</phrase> <phrase role="special">&gt;</phrase> <phrase role="special">...</phrase> <phrase role="special">)</phrase>
    <phrase role="special">&gt;</phrase>
<phrase role="special">&gt;</phrase>
<phrase role="identifier">async</phrase><phrase role="special">(</phrase> <link linkend="class_launch"><code><phrase role="identifier">launch</phrase></code></link> <phrase role="identifier">policy</phrase><phrase role="special">,</phrase> <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><phrase role="special">,</phrase> <link linkend="stack_allocator_concept"><code><phrase role="identifier">StackAllocator</phrase></code></link> <phrase role="identifier">salloc</phrase><phrase role="special">,</phrase>
       <phrase role="identifier">Function</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> <link linkend="stack_allocator_concept"><code><phrase role="identifier">StackAllocator</phrase></code></link><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Allocator</phrase><phrase role="special">,</phrase> <phrase role="keyword">class</phrase> <phrase role="identifier">Function</phrase><phrase role="special">,</phrase> <phrase role="keyword">class</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="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">result_of_t</phrase><phrase role="special">&lt;</phrase>
        <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">decay_t</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Function</phrase> <phrase role="special">&gt;(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">decay_t</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Args</phrase> <phrase role="special">&gt;</phrase> <phrase role="special">...</phrase> <phrase role="special">)</phrase>
    <phrase role="special">&gt;</phrase>
<phrase role="special">&gt;</phrase>
<phrase role="identifier">async</phrase><phrase role="special">(</phrase> <link linkend="class_launch"><code><phrase role="identifier">launch</phrase></code></link> <phrase role="identifier">policy</phrase><phrase role="special">,</phrase> <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><phrase role="special">,</phrase> <link linkend="stack_allocator_concept"><code><phrase role="identifier">StackAllocator</phrase></code></link> <phrase role="identifier">salloc</phrase><phrase role="special">,</phrase>
       <phrase role="identifier">Allocator</phrase> <phrase role="identifier">alloc</phrase><phrase role="special">,</phrase> <phrase role="identifier">Function</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>
</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>
<programlisting><phrase role="identifier">future</phrase><phrase role="special">&lt;</phrase>
    <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">result_of_t</phrase><phrase role="special">&lt;</phrase>
        <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">decay_t</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Function</phrase> <phrase role="special">&gt;(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">decay_t</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Args</phrase> <phrase role="special">&gt;</phrase> <phrase role="special">...</phrase> <phrase role="special">)</phrase>
    <phrase role="special">&gt;</phrase>
<phrase role="special">&gt;</phrase></programlisting>
                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_error</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 overloads 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> use the
                passed <link linkend="stack_allocator_concept"><code><phrase role="identifier">StackAllocator</phrase></code></link>
                when constructing the launched <code><phrase role="identifier">fiber</phrase></code>.
                The overloads accepting <link linkend="class_launch"><code>launch</code></link> use the passed <code><phrase
                role="identifier">launch</phrase></code> when constructing the launched
                <code><phrase role="identifier">fiber</phrase></code>. The default
                <code><phrase role="identifier">launch</phrase></code> is <code><phrase
                role="identifier">post</phrase></code>, as for the <code><phrase
                role="identifier">fiber</phrase></code> constructor.
              </para>
            </listitem>
          </varlistentry>
        </variablelist>
        <note>
          <para>
            Deferred futures are not supported.
          </para>
        </note>
      </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="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">promise</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">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> <ulink url="http://en.cppreference.com/w/cpp/concept/Allocator"><code><phrase role="identifier">Allocator</phrase></code></ulink> <phrase role="special">&gt;</phrase>
    <phrase role="identifier">promise</phrase><phrase role="special">(</phrase> <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><phrase role="special">,</phrase> <phrase role="identifier">Allocator</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="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="special">&amp;&amp;)</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="special">=</phrase> <phrase role="keyword">delete</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="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="keyword">void</phrase> <phrase role="identifier">swap</phrase><phrase role="special">(</phrase> <phrase role="identifier">promise</phrase> <phrase role="special">&amp;)</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="comment">// member only of generic promise template</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="comment">// member only of generic promise template</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;);</phrase>       <phrase role="comment">// member only of promise&lt; R &amp; &gt; template</phrase>
    <phrase role="keyword">void</phrase> <phrase role="identifier">set_value</phrase><phrase role="special">();</phrase>           <phrase role="comment">// member only of promise&lt; void &gt; template</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>

<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">void</phrase> <phrase role="identifier">swap</phrase><phrase role="special">(</phrase> <phrase role="identifier">promise</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">R</phrase> <phrase role="special">&gt;</phrase> <phrase role="special">&amp;,</phrase> <phrase role="identifier">promise</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">R</phrase> <phrase role="special">&gt;</phrase> <phrase role="special">&amp;)</phrase> <phrase role="keyword">noexcept</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>
                Exceptions caused by memory allocation.
              </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> <ulink url="http://en.cppreference.com/w/cpp/concept/Allocator"><code><phrase role="identifier">Allocator</phrase></code></ulink> <phrase role="special">&gt;</phrase>
<phrase role="identifier">promise</phrase><phrase role="special">(</phrase> <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><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>
                Exceptions caused by memory allocation.
              </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>
                as if by <link linkend="promise_set_exception"><code>promise::set_exception()</code></link>: the shared
                state is set ready.
              </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="comment">// member only of generic promise template</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="comment">// member only of generic promise template</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;</phrase> <phrase role="identifier">value</phrase><phrase role="special">);</phrase>       <phrase role="comment">// member only of promise&lt; R &amp; &gt; template</phrase>
<phrase role="keyword">void</phrase> <phrase role="identifier">set_value</phrase><phrase role="special">();</phrase>                 <phrase role="comment">// member only of promise&lt; void &gt; template</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>
        <para>
          <bridgehead renderas="sect4" id="swap_for_promise_bridgehead">
  <phrase id="swap_for_promise"/>
  <link linkend="swap_for_promise">Non-member function
          <code>swap()</code></link>
</bridgehead>
        </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">void</phrase> <phrase role="identifier">swap</phrase><phrase role="special">(</phrase> <phrase role="identifier">promise</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">R</phrase> <phrase role="special">&gt;</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">l</phrase><phrase role="special">,</phrase> <phrase role="identifier">promise</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">R</phrase> <phrase role="special">&gt;</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>
      </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="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">packaged_task</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">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="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> <ulink url="http://en.cppreference.com/w/cpp/concept/Allocator"><code><phrase role="identifier">Allocator</phrase></code></ulink> <phrase role="special">&gt;</phrase>
    <phrase role="identifier">packaged_task</phrase><phrase role="special">(</phrase> <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><phrase role="special">,</phrase> <phrase role="identifier">Allocator</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;,</phrase> <phrase role="identifier">Fn</phrase> <phrase role="special">&amp;&amp;);</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="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="special">&amp;&amp;)</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="special">=</phrase> <phrase role="keyword">delete</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="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="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="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">...);</phrase>

    <phrase role="keyword">void</phrase> <phrase role="identifier">reset</phrase><phrase role="special">();</phrase>
<phrase role="special">};</phrase>

<phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Signature</phrase> <phrase role="special">&gt;</phrase>
<phrase role="keyword">void</phrase> <phrase role="identifier">swap</phrase><phrase role="special">(</phrase> <phrase role="identifier">packaged_task</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Signature</phrase> <phrase role="special">&gt;</phrase> <phrase role="special">&amp;,</phrase> <phrase role="identifier">packaged_task</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Signature</phrase> <phrase role="special">&gt;</phrase> <phrase role="special">&amp;)</phrase> <phrase role="keyword">noexcept</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> <phrase role="keyword">noexcept</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__identifier__packaged_task__phrase__phrase_role__special______phrase___code_"/><link
          linkend="fiber.synchronization.futures.packaged_task.templated_constructor__code__phrase_role__identifier__packaged_task__phrase__phrase_role__special______phrase___code_">Templated
          constructor <code><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> <ulink url="http://en.cppreference.com/w/cpp/concept/Allocator"><code><phrase role="identifier">Allocator</phrase></code></ulink> <phrase role="special">&gt;</phrase>
<phrase role="identifier">packaged_task</phrase><phrase role="special">(</phrase> <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><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 copies
                or moves the callable target <code><phrase role="identifier">fn</phrase></code>
                to internal storage.
              </para>
            </listitem>
          </varlistentry>
          <varlistentry>
            <term>Throws:</term>
            <listitem>
              <para>
                Exceptions caused by memory allocation.
              </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>
                as if by <link linkend="promise_set_exception"><code>promise::set_exception()</code></link>: the shared
                state is set ready.
              </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> as if by
                <link linkend="promise_set_exception"><code>promise::set_exception()</code></link>. Otherwise, the value
                returned by <code><phrase role="identifier">fn</phrase></code> is
                stored in the shared state as if by <link linkend="promise_set_value"><code>promise::set_value()</code></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">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 abandons
                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>
        <para>
          <bridgehead renderas="sect4" id="swap_for_packaged_task_bridgehead">
  <phrase id="swap_for_packaged_task"/>
  <link linkend="swap_for_packaged_task">Non-member
          function <code>swap()</code></link>
</bridgehead>
        </para>
<programlisting><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Signature</phrase> <phrase role="special">&gt;</phrase>
<phrase role="keyword">void</phrase> <phrase role="identifier">swap</phrase><phrase role="special">(</phrase> <phrase role="identifier">packaged_task</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Signature</phrase> <phrase role="special">&gt;</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">l</phrase><phrase role="special">,</phrase> <phrase role="identifier">packaged_task</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Signature</phrase> <phrase role="special">&gt;</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>
      </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">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">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="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="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="keyword">noexcept</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="keyword">noexcept</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="keyword">noexcept</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="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_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>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="keyword">noexcept</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="keyword">noexcept</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="keyword">noexcept</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>
            Exception raised during cleanup of previous value.
          </para>
        </listitem>
      </varlistentry>
    </variablelist>
  </section>
  <section id="fiber.migration">
    <title><anchor id="migration"/><link linkend="fiber.migration">Migrating fibers
    between threads</link></title>
    <bridgehead renderas="sect3" id="fiber.migration.h0">
      <phrase id="fiber.migration.overview"/><link linkend="fiber.migration.overview">Overview</link>
    </bridgehead>
    <para>
      Each fiber owns a stack and manages its execution state, including all registers
      and CPU flags, the instruction pointer and the stack pointer. That means, in
      general, a fiber is not bound to a specific thread.<footnote id="fiber.migration.f0">
      <para>
        The <quote>main</quote> fiber on each thread, that is, the fiber on which
        the thread is launched, cannot migrate to any other thread. Also <emphasis
        role="bold">Boost.Fiber</emphasis> implicitly creates a dispatcher fiber
        for each thread &mdash; this cannot migrate either.
      </para>
      </footnote><superscript>,</superscript><footnote id="fiber.migration.f1">
      <para>
        Of course it would be problematic to migrate a fiber that relies on <link
        linkend="thread_local_storage">thread-local storage</link>.
      </para>
      </footnote>
    </para>
    <para>
      Migrating a fiber from a logical CPU with heavy workload to another logical
      CPU with a lighter workload might speed up the overall execution. Note that
      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> might reduce the performance of the application
      due to increased latency of memory access.
    </para>
    <para>
      Only fibers that are contained in <link linkend="class_algorithm"><code>algorithm</code></link>&#8217;s ready queue can
      migrate between threads. You cannot migrate a running fiber, nor one that is
      <link linkend="blocking"><emphasis>blocked</emphasis></link>. You cannot migrate
      a fiber if its <link linkend="context_is_context"><code>context::is_context()</code></link> method returns <code><phrase
      role="keyword">true</phrase></code> for <code><phrase role="identifier">pinned_context</phrase></code>.
    </para>
    <para>
      In <emphasis role="bold">Boost.Fiber</emphasis> a fiber is migrated by invoking
      <link linkend="context_detach"><code>context::detach()</code></link> on the thread from which the fiber migrates
      and <link linkend="context_attach"><code>context::attach()</code></link> on the thread to which the fiber migrates.
    </para>
    <para>
      Thus, fiber migration is accomplished by sharing state between instances of
      a user-coded <link linkend="class_algorithm"><code>algorithm</code></link> implementation running on different threads.
      The fiber&#8217;s original thread calls <link linkend="algorithm_awakened"><code>algorithm::awakened()</code></link>, passing
      the fiber&#8217;s <link linkend="class_context"><code>context</code></link><literal>*</literal>. The <code><phrase role="identifier">awakened</phrase><phrase
      role="special">()</phrase></code> implementation calls <link linkend="context_detach"><code>context::detach()</code></link>.
    </para>
    <para>
      At some later point, when the same or a different thread calls <link linkend="algorithm_pick_next"><code>algorithm::pick_next()</code></link>,
      the <code><phrase role="identifier">pick_next</phrase><phrase role="special">()</phrase></code>
      implementation selects a ready fiber and calls <link linkend="context_attach"><code>context::attach()</code></link> on
      it before returning it.
    </para>
    <para>
      As stated above, a <code><phrase role="identifier">context</phrase></code>
      for which <code><phrase role="identifier">is_context</phrase><phrase role="special">(</phrase><phrase
      role="identifier">pinned_context</phrase><phrase role="special">)</phrase>
      <phrase role="special">==</phrase> <phrase role="keyword">true</phrase></code>
      must never be passed to either <link linkend="context_detach"><code>context::detach()</code></link> or <link linkend="context_attach"><code>context::attach()</code></link>.
      It may only be returned from <code><phrase role="identifier">pick_next</phrase><phrase
      role="special">()</phrase></code> called by the <emphasis>same</emphasis> thread
      that passed that context to <code><phrase role="identifier">awakened</phrase><phrase
      role="special">()</phrase></code>.
    </para>
    <bridgehead renderas="sect3" id="fiber.migration.h1">
      <phrase id="fiber.migration.example_of_work_sharing"/><link linkend="fiber.migration.example_of_work_sharing">Example
      of work sharing</link>
    </bridgehead>
    <para>
      In the example <ulink url="../../examples/work_sharing.cpp">work_sharing.cpp</ulink>
      multiple worker fibers are created on the main thread. Each fiber gets a character
      as parameter at construction. This character is printed out ten times. Between
      each iteration the fiber calls <link linkend="this_fiber_yield"><code>this_fiber::yield()</code></link>. That puts
      the fiber in the ready queue of the fiber-scheduler <emphasis>shared_ready_queue</emphasis>,
      running in the current thread. The next fiber ready to be executed is dequeued
      from the shared ready queue and resumed by <emphasis>shared_ready_queue</emphasis>
      running on <emphasis>any participating thread</emphasis>.
    </para>
    <para>
      All instances of <emphasis>shared_ready_queue</emphasis> share one global concurrent
      queue, used as ready queue. This mechanism shares all worker fibers between
      all instances of <emphasis>shared_ready_queue</emphasis>, thus between all
      participating threads.
    </para>
    <bridgehead renderas="sect3" id="fiber.migration.h2">
      <phrase id="fiber.migration.setup_of_threads_and_fibers"/><link linkend="fiber.migration.setup_of_threads_and_fibers">Setup
      of threads and fibers</link>
    </bridgehead>
    <para>
      In <code><phrase role="identifier">main</phrase><phrase role="special">()</phrase></code>
      the fiber-scheduler is installed and the worker fibers and the threads are
      launched.
    </para>
    <para>
<programlisting><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">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">algo</phrase><phrase role="special">::</phrase><phrase role="identifier">shared_work</phrase> <phrase role="special">&gt;();</phrase> <co id="fiber.migration.c0" linkends="fiber.migration.c1" />

<phrase role="keyword">for</phrase> <phrase role="special">(</phrase> <phrase role="keyword">char</phrase> <phrase role="identifier">c</phrase> <phrase role="special">:</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase><phrase role="special">(</phrase><phrase role="string">&quot;abcdefghijklmnopqrstuvwxyz&quot;</phrase><phrase role="special">))</phrase> <phrase role="special">{</phrase> <co id="fiber.migration.c2" linkends="fiber.migration.c3" />
    <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">c</phrase><phrase role="special">](){</phrase> <phrase role="identifier">whatevah</phrase><phrase role="special">(</phrase> <phrase role="identifier">c</phrase><phrase role="special">);</phrase> <phrase role="special">}).</phrase><phrase role="identifier">detach</phrase><phrase role="special">();</phrase>
    <phrase role="special">++</phrase><phrase role="identifier">fiber_count</phrase><phrase role="special">;</phrase> <co id="fiber.migration.c4" linkends="fiber.migration.c5" />
<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">detail</phrase><phrase role="special">::</phrase><phrase role="identifier">thread_barrier</phrase> <phrase role="identifier">b</phrase><phrase role="special">(</phrase> <phrase role="number">4</phrase><phrase role="special">);</phrase>
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">thread</phrase> <phrase role="identifier">threads</phrase><phrase role="special">[]</phrase> <phrase role="special">=</phrase> <phrase role="special">{</phrase> <co id="fiber.migration.c6" linkends="fiber.migration.c7" />
    <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">thread</phrase><phrase role="special">(</phrase> <phrase role="identifier">thread</phrase><phrase role="special">,</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">b</phrase><phrase role="special">),</phrase>
    <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">thread</phrase><phrase role="special">(</phrase> <phrase role="identifier">thread</phrase><phrase role="special">,</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">b</phrase><phrase role="special">),</phrase>
    <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">thread</phrase><phrase role="special">(</phrase> <phrase role="identifier">thread</phrase><phrase role="special">,</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">b</phrase><phrase role="special">)</phrase>
<phrase role="special">};</phrase>
<phrase role="identifier">b</phrase><phrase role="special">.</phrase><phrase role="identifier">wait</phrase><phrase role="special">();</phrase> <co id="fiber.migration.c8" linkends="fiber.migration.c9" />
<phrase role="special">{</phrase>
    <phrase role="identifier">lock_type</phrase><co id="fiber.migration.c10" linkends="fiber.migration.c11" /> <phrase role="identifier">lk</phrase><phrase role="special">(</phrase> <phrase role="identifier">mtx_count</phrase><phrase role="special">);</phrase>
    <phrase role="identifier">cnd_count</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="keyword">return</phrase> <phrase role="number">0</phrase> <phrase role="special">==</phrase> <phrase role="identifier">fiber_count</phrase><phrase role="special">;</phrase> <phrase role="special">}</phrase> <phrase role="special">);</phrase> <co id="fiber.migration.c12" linkends="fiber.migration.c13" />
<phrase role="special">}</phrase> <co id="fiber.migration.c14" linkends="fiber.migration.c15" />
<phrase role="identifier">BOOST_ASSERT</phrase><phrase role="special">(</phrase> <phrase role="number">0</phrase> <phrase role="special">==</phrase> <phrase role="identifier">fiber_count</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">thread</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">t</phrase> <phrase role="special">:</phrase> <phrase role="identifier">threads</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase> <co id="fiber.migration.c16" linkends="fiber.migration.c17" />
    <phrase role="identifier">t</phrase><phrase role="special">.</phrase><phrase role="identifier">join</phrase><phrase role="special">();</phrase>
<phrase role="special">}</phrase>
</programlisting>
    </para>
    <calloutlist>
      <callout arearefs="fiber.migration.c0" id="fiber.migration.c1">
        <para>
          Install the scheduling algorithm <code><phrase role="identifier">boost</phrase><phrase
          role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase
          role="special">::</phrase><phrase role="identifier">algo</phrase><phrase
          role="special">::</phrase><phrase role="identifier">shared_work</phrase></code>
          in the main thread too, so each new fiber gets launched into the shared
          pool.
        </para>
      </callout>
      <callout arearefs="fiber.migration.c2" id="fiber.migration.c3">
        <para>
          Launch a number of worker fibers; each worker fiber picks up a character
          that is passed as parameter to fiber-function <code><phrase role="identifier">whatevah</phrase></code>.
          Each worker fiber gets detached.
        </para>
      </callout>
      <callout arearefs="fiber.migration.c4" id="fiber.migration.c5">
        <para>
          Increment fiber counter for each new fiber.
        </para>
      </callout>
      <callout arearefs="fiber.migration.c6" id="fiber.migration.c7">
        <para>
          Launch a couple of threads that join the work sharing.
        </para>
      </callout>
      <callout arearefs="fiber.migration.c8" id="fiber.migration.c9">
        <para>
          sync with other threads: allow them to start processing
        </para>
      </callout>
      <callout arearefs="fiber.migration.c10" id="fiber.migration.c11">
        <para>
          <code><phrase role="identifier">lock_type</phrase></code> is typedef'ed
          as <ulink url="http://en.cppreference.com/w/cpp/thread/unique_lock"><code><phrase
          role="identifier">std</phrase><phrase role="special">::</phrase><phrase
          role="identifier">unique_lock</phrase></code></ulink>&lt; <ulink url="http://en.cppreference.com/w/cpp/thread/mutex"><code><phrase
          role="identifier">std</phrase><phrase role="special">::</phrase><phrase
          role="identifier">mutex</phrase></code></ulink> &gt;
        </para>
      </callout>
      <callout arearefs="fiber.migration.c12" id="fiber.migration.c13">
        <para>
          Suspend main fiber and resume worker fibers in the meanwhile. Main fiber
          gets resumed (e.g returns from <code><phrase role="identifier">condition_variable_any</phrase><phrase
          role="special">::</phrase><phrase role="identifier">wait</phrase><phrase
          role="special">()</phrase></code>) if all worker fibers are complete.
        </para>
      </callout>
      <callout arearefs="fiber.migration.c14" id="fiber.migration.c15">
        <para>
          Releasing lock of mtx_count is required before joining the threads, otherwise
          the other threads would be blocked inside condition_variable::wait() and
          would never return (deadlock).
        </para>
      </callout>
      <callout arearefs="fiber.migration.c16" id="fiber.migration.c17">
        <para>
          wait for threads to terminate
        </para>
      </callout>
    </calloutlist>
    <para>
      The start of the threads is synchronized with a barrier. The main fiber of
      each thread (including main thread) is suspended until all worker fibers are
      complete. When the main fiber returns from <link linkend="condition_variable_wait"><code>condition_variable::wait()</code></link>,
      the thread terminates: the main thread joins all other threads.
    </para>
    <para>
<programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">thread</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">detail</phrase><phrase role="special">::</phrase><phrase role="identifier">thread_barrier</phrase> <phrase role="special">*</phrase> <phrase role="identifier">b</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">buffer</phrase><phrase role="special">;</phrase>
    <phrase role="identifier">buffer</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="string">&quot;thread started &quot;</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">this_thread</phrase><phrase role="special">::</phrase><phrase role="identifier">get_id</phrase><phrase role="special">()</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">endl</phrase><phrase role="special">;</phrase>
    <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cout</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="identifier">buffer</phrase><phrase role="special">.</phrase><phrase role="identifier">str</phrase><phrase role="special">()</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">flush</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">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">algo</phrase><phrase role="special">::</phrase><phrase role="identifier">shared_work</phrase> <phrase role="special">&gt;();</phrase> <co id="fiber.migration.c18" linkends="fiber.migration.c19" />
    <phrase role="identifier">b</phrase><phrase role="special">-&gt;</phrase><phrase role="identifier">wait</phrase><phrase role="special">();</phrase> <co id="fiber.migration.c20" linkends="fiber.migration.c21" />
    <phrase role="identifier">lock_type</phrase> <phrase role="identifier">lk</phrase><phrase role="special">(</phrase> <phrase role="identifier">mtx_count</phrase><phrase role="special">);</phrase>
    <phrase role="identifier">cnd_count</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="keyword">return</phrase> <phrase role="number">0</phrase> <phrase role="special">==</phrase> <phrase role="identifier">fiber_count</phrase><phrase role="special">;</phrase> <phrase role="special">}</phrase> <phrase role="special">);</phrase> <co id="fiber.migration.c22" linkends="fiber.migration.c23" />
    <phrase role="identifier">BOOST_ASSERT</phrase><phrase role="special">(</phrase> <phrase role="number">0</phrase> <phrase role="special">==</phrase> <phrase role="identifier">fiber_count</phrase><phrase role="special">);</phrase>
<phrase role="special">}</phrase>
</programlisting>
    </para>
    <calloutlist>
      <callout arearefs="fiber.migration.c18" id="fiber.migration.c19">
        <para>
          Install the scheduling algorithm <code><phrase role="identifier">boost</phrase><phrase
          role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase
          role="special">::</phrase><phrase role="identifier">algo</phrase><phrase
          role="special">::</phrase><phrase role="identifier">shared_work</phrase></code>
          in order to join the work sharing.
        </para>
      </callout>
      <callout arearefs="fiber.migration.c20" id="fiber.migration.c21">
        <para>
          sync with other threads: allow them to start processing
        </para>
      </callout>
      <callout arearefs="fiber.migration.c22" id="fiber.migration.c23">
        <para>
          Suspend main fiber and resume worker fibers in the meanwhile. Main fiber
          gets resumed (e.g returns from <code><phrase role="identifier">condition_variable_any</phrase><phrase
          role="special">::</phrase><phrase role="identifier">wait</phrase><phrase
          role="special">()</phrase></code>) if all worker fibers are complete.
        </para>
      </callout>
    </calloutlist>
    <para>
      Each worker fiber executes function <code><phrase role="identifier">whatevah</phrase><phrase
      role="special">()</phrase></code> with character <code><phrase role="identifier">me</phrase></code>
      as parameter. The fiber yields in a loop and prints out a message if it was
      migrated to another thread.
    </para>
    <para>
<programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">whatevah</phrase><phrase role="special">(</phrase> <phrase role="keyword">char</phrase> <phrase role="identifier">me</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
    <phrase role="keyword">try</phrase> <phrase role="special">{</phrase>
        <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">thread</phrase><phrase role="special">::</phrase><phrase role="identifier">id</phrase> <phrase role="identifier">my_thread</phrase> <phrase role="special">=</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">this_thread</phrase><phrase role="special">::</phrase><phrase role="identifier">get_id</phrase><phrase role="special">();</phrase> <co id="fiber.migration.c24" linkends="fiber.migration.c25" />
        <phrase role="special">{</phrase>
            <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">ostringstream</phrase> <phrase role="identifier">buffer</phrase><phrase role="special">;</phrase>
            <phrase role="identifier">buffer</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="string">&quot;fiber &quot;</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="identifier">me</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="string">&quot; started on thread &quot;</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="identifier">my_thread</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="char">'\n'</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">buffer</phrase><phrase role="special">.</phrase><phrase role="identifier">str</phrase><phrase role="special">()</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">flush</phrase><phrase role="special">;</phrase>
        <phrase role="special">}</phrase>
        <phrase role="keyword">for</phrase> <phrase role="special">(</phrase> <phrase role="keyword">unsigned</phrase> <phrase role="identifier">i</phrase> <phrase role="special">=</phrase> <phrase role="number">0</phrase><phrase role="special">;</phrase> <phrase role="identifier">i</phrase> <phrase role="special">&lt;</phrase> <phrase role="number">10</phrase><phrase role="special">;</phrase> <phrase role="special">++</phrase><phrase role="identifier">i</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase> <co id="fiber.migration.c26" linkends="fiber.migration.c27" />
            <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> <co id="fiber.migration.c28" linkends="fiber.migration.c29" />
            <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">thread</phrase><phrase role="special">::</phrase><phrase role="identifier">id</phrase> <phrase role="identifier">new_thread</phrase> <phrase role="special">=</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">this_thread</phrase><phrase role="special">::</phrase><phrase role="identifier">get_id</phrase><phrase role="special">();</phrase> <co id="fiber.migration.c30" linkends="fiber.migration.c31" />
            <phrase role="keyword">if</phrase> <phrase role="special">(</phrase> <phrase role="identifier">new_thread</phrase> <phrase role="special">!=</phrase> <phrase role="identifier">my_thread</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase> <co id="fiber.migration.c32" linkends="fiber.migration.c33" />
                <phrase role="identifier">my_thread</phrase> <phrase role="special">=</phrase> <phrase role="identifier">new_thread</phrase><phrase role="special">;</phrase>
                <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">ostringstream</phrase> <phrase role="identifier">buffer</phrase><phrase role="special">;</phrase>
                <phrase role="identifier">buffer</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="string">&quot;fiber &quot;</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="identifier">me</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="string">&quot; switched to thread &quot;</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="identifier">my_thread</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="char">'\n'</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">buffer</phrase><phrase role="special">.</phrase><phrase role="identifier">str</phrase><phrase role="special">()</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">flush</phrase><phrase role="special">;</phrase>
            <phrase role="special">}</phrase>
        <phrase role="special">}</phrase>
    <phrase role="special">}</phrase> <phrase role="keyword">catch</phrase> <phrase role="special">(</phrase> <phrase role="special">...</phrase> <phrase role="special">)</phrase> <phrase role="special">{</phrase>
    <phrase role="special">}</phrase>
    <phrase role="identifier">lock_type</phrase> <phrase role="identifier">lk</phrase><phrase role="special">(</phrase> <phrase role="identifier">mtx_count</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="special">--</phrase><phrase role="identifier">fiber_count</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase> <co id="fiber.migration.c34" linkends="fiber.migration.c35" />
        <phrase role="identifier">lk</phrase><phrase role="special">.</phrase><phrase role="identifier">unlock</phrase><phrase role="special">();</phrase>
        <phrase role="identifier">cnd_count</phrase><phrase role="special">.</phrase><phrase role="identifier">notify_all</phrase><phrase role="special">();</phrase> <co id="fiber.migration.c36" linkends="fiber.migration.c37" />
    <phrase role="special">}</phrase>
<phrase role="special">}</phrase>
</programlisting>
    </para>
    <calloutlist>
      <callout arearefs="fiber.migration.c24" id="fiber.migration.c25">
        <para>
          get ID of initial thread
        </para>
      </callout>
      <callout arearefs="fiber.migration.c26" id="fiber.migration.c27">
        <para>
          loop ten times
        </para>
      </callout>
      <callout arearefs="fiber.migration.c28" id="fiber.migration.c29">
        <para>
          yield to other fibers
        </para>
      </callout>
      <callout arearefs="fiber.migration.c30" id="fiber.migration.c31">
        <para>
          get ID of current thread
        </para>
      </callout>
      <callout arearefs="fiber.migration.c32" id="fiber.migration.c33">
        <para>
          test if fiber was migrated to another thread
        </para>
      </callout>
      <callout arearefs="fiber.migration.c34" id="fiber.migration.c35">
        <para>
          Decrement fiber counter for each completed fiber.
        </para>
      </callout>
      <callout arearefs="fiber.migration.c36" id="fiber.migration.c37">
        <para>
          Notify all fibers waiting on <code><phrase role="identifier">cnd_count</phrase></code>.
        </para>
      </callout>
    </calloutlist>
    <bridgehead renderas="sect3" id="fiber.migration.h3">
      <phrase id="fiber.migration.scheduling_fibers"/><link linkend="fiber.migration.scheduling_fibers">Scheduling
      fibers</link>
    </bridgehead>
    <para>
      The fiber scheduler <code><phrase role="identifier">shared_ready_queue</phrase></code>
      is like <code><phrase role="identifier">round_robin</phrase></code>, except
      that it shares a common ready queue among all participating threads. A thread
      participates in this pool by executing <link linkend="use_scheduling_algorithm"><code>use_scheduling_algorithm()</code></link>
before
      any other <emphasis role="bold">Boost.Fiber</emphasis> operation.
    </para>
    <para>
      The important point about the ready queue is that it&#8217;s a class static, common
      to all instances of shared_ready_queue. Fibers that are enqueued via <link linkend="algorithm_awakened"><code>algorithm::awakened()</code></link> (fibers
      that are ready to be resumed) are thus available to all threads. It is required
      to reserve a separate, scheduler-specific queue for the thread&#8217;s main fiber
      and dispatcher fibers: these may <emphasis>not</emphasis> be shared between
      threads! When we&#8217;re passed either of these fibers, push it there instead of
      in the shared queue: it would be Bad News for thread B to retrieve and attempt
      to execute thread A&#8217;s main fiber.
    </para>
    <para>
      [awakened_ws]
    </para>
    <para>
      When <link linkend="algorithm_pick_next"><code>algorithm::pick_next()</code></link> gets called inside one thread,
      a fiber is dequeued from <emphasis>rqueue_</emphasis> and will be resumed in
      that thread.
    </para>
    <para>
      [pick_next_ws]
    </para>
    <para>
      The source code above is found in <ulink url="../../examples/work_sharing.cpp">work_sharing.cpp</ulink>.
    </para>
  </section>
  <section id="fiber.callbacks">
    <title><anchor id="callbacks"/><link linkend="fiber.callbacks">Integrating Fibers
    with Asynchronous Callbacks</link></title>
    <section id="fiber.callbacks.overview">
      <title><link linkend="fiber.callbacks.overview">Overview</link></title>
      <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">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">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">Fn</phrase> <phrase role="special">&amp;&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">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">void</phrase> <phrase role="identifier">init_read</phrase><phrase role="special">(</phrase> <phrase role="identifier">Fn</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="identifier">callback</phrase><phrase role="special">);</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&#8217;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>
    </section>
    <section id="fiber.callbacks.return_errorcode">
      <title><link linkend="fiber.callbacks.return_errorcode">Return Errorcode</link></title>
      <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">// In general, even though we block waiting for future::get() and therefore</phrase>
    <phrase role="comment">// won't destroy 'promise' until promise::set_value() has been called, we</phrase>
    <phrase role="comment">// are advised that with threads it's possible for ~promise() to be</phrase>
    <phrase role="comment">// entered before promise::set_value() has returned. While that shouldn't</phrase>
    <phrase role="comment">// happen with fibers::promise, a robust way to deal with the lifespan</phrase>
    <phrase role="comment">// issue is to bind 'promise' into our lambda. Since promise is move-only,</phrase>
    <phrase role="comment">// use initialization capture.</phrase>
<phrase role="preprocessor">#if</phrase> <phrase role="special">!</phrase> <phrase role="identifier">defined</phrase><phrase role="special">(</phrase><phrase role="identifier">BOOST_NO_CXX14_INITIALIZED_LAMBDA_CAPTURES</phrase><phrase role="special">)</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">[</phrase><phrase role="identifier">promise</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">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="keyword">mutable</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="preprocessor">#else</phrase> <phrase role="comment">// defined(BOOST_NO_CXX14_INITIALIZED_LAMBDA_CAPTURES)</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="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">bind</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="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="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="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">move</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">placeholders</phrase><phrase role="special">::</phrase><phrase role="identifier">_1</phrase><phrase role="special">)</phrase> <phrase role="special">);</phrase>
<phrase role="preprocessor">#endif</phrase> <phrase role="comment">// BOOST_NO_CXX14_INITIALIZED_LAMBDA_CAPTURES</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&#8217;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>
    </section>
    <section id="fiber.callbacks.success_or_exception">
      <title><link linkend="fiber.callbacks.success_or_exception">Success or Exception</link></title>
      <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>
    </section>
    <section id="fiber.callbacks.return_errorcode_or_data">
      <title><link linkend="fiber.callbacks.return_errorcode_or_data">Return Errorcode
      or Data</link></title>
      <para>
        Things get a bit more interesting when the async operation&#8217;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="preprocessor">#if</phrase> <phrase role="special">!</phrase> <phrase role="identifier">defined</phrase><phrase role="special">(</phrase><phrase role="identifier">BOOST_NO_CXX14_INITIALIZED_LAMBDA_CAPTURES</phrase><phrase role="special">)</phrase>
    <phrase role="identifier">api</phrase><phrase role="special">.</phrase><phrase role="identifier">init_read</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">move</phrase><phrase role="special">(</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">mutable</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="preprocessor">#else</phrase> <phrase role="comment">// defined(BOOST_NO_CXX14_INITIALIZED_LAMBDA_CAPTURES)</phrase>
    <phrase role="identifier">api</phrase><phrase role="special">.</phrase><phrase role="identifier">init_read</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">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="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">mutable</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="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">move</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">placeholders</phrase><phrase role="special">::</phrase><phrase role="identifier">_1</phrase><phrase role="special">,</phrase>
                  <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">placeholders</phrase><phrase role="special">::</phrase><phrase role="identifier">_2</phrase><phrase role="special">)</phrase> <phrase role="special">);</phrase>
<phrase role="preprocessor">#endif</phrase> <phrase role="comment">// BOOST_NO_CXX14_INITIALIZED_LAMBDA_CAPTURES</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>
    </section>
    <section id="fiber.callbacks.data_or_exception">
      <title><anchor id="Data_or_Exception"/><link linkend="fiber.callbacks.data_or_exception">Data
      or Exception</link></title>
      <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&#8217;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&#8217;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="preprocessor">#if</phrase> <phrase role="special">!</phrase> <phrase role="identifier">defined</phrase><phrase role="special">(</phrase><phrase role="identifier">BOOST_NO_CXX14_INITIALIZED_LAMBDA_CAPTURES</phrase><phrase role="special">)</phrase>
    <phrase role="identifier">api</phrase><phrase role="special">.</phrase><phrase role="identifier">init_read</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">mutable</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="preprocessor">#else</phrase> <phrase role="comment">// defined(BOOST_NO_CXX14_INITIALIZED_LAMBDA_CAPTURES)</phrase>
    <phrase role="identifier">api</phrase><phrase role="special">.</phrase><phrase role="identifier">init_read</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">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="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">mutable</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="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">move</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">placeholders</phrase><phrase role="special">::</phrase><phrase role="identifier">_1</phrase><phrase role="special">,</phrase>
                  <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">placeholders</phrase><phrase role="special">::</phrase><phrase role="identifier">_2</phrase><phrase role="special">)</phrase> <phrase role="special">);</phrase>
<phrase role="preprocessor">#endif</phrase> <phrase role="comment">// BOOST_NO_CXX14_INITIALIZED_LAMBDA_CAPTURES</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>
    </section>
    <section id="fiber.callbacks.success_error_virtual_methods">
      <title><link linkend="fiber.callbacks.success_error_virtual_methods">Success/Error
      Virtual Methods</link></title>
      <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>
    </section>
    <section id="fiber.callbacks.then_there_s____boost_asio__">
      <title><anchor id="callbacks_asio"/><link linkend="fiber.callbacks.then_there_s____boost_asio__">Then
      There&#8217;s <ulink url="http://www.boost.org/doc/libs/release/libs/asio/index.html">Boost.Asio</ulink></link></title>
      <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<footnote id="fiber.callbacks.then_there_s____boost_asio__.f0">
        <para>
          This mechanism has been proposed as a conventional way to allow the caller
          of an arbitrary async function to specify completion handling: <ulink url="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4045.pdf">N4045</ulink>.
        </para>
        </footnote> by which the caller can customize the notification behavior of
        any 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.
      </para>
      <para>
        A typical Asio async function might look something like this:<footnote id="fiber.callbacks.then_there_s____boost_asio__.f1">
        <para>
          per <ulink url="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4045.pdf">N4045</ulink>
        </para>
        </footnote>
      </para>
<programlisting><phrase role="keyword">template</phrase> <phrase role="special">&lt;</phrase> <phrase role="special">...,</phrase> <phrase role="keyword">class</phrase> <phrase role="identifier">CompletionToken</phrase> <phrase role="special">&gt;</phrase>
<emphasis>deduced_return_type</emphasis>
<phrase role="identifier">async_something</phrase><phrase role="special">(</phrase> <phrase role="special">...</phrase> <phrase role="special">,</phrase> <phrase role="identifier">CompletionToken</phrase><phrase role="special">&amp;&amp;</phrase> <phrase role="identifier">token</phrase><phrase role="special">)</phrase>
<phrase role="special">{</phrase>
    <phrase role="comment">// construct handler_type instance from CompletionToken</phrase>
    <phrase role="identifier">handler_type</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">CompletionToken</phrase><phrase role="special">,</phrase> <phrase role="special">...&gt;::</phrase><phrase role="identifier">type</phrase> <emphasis role="bold"><!--quickbook-escape-prefix--><code><!--quickbook-escape-postfix-->handler(token)<!--quickbook-escape-prefix--></code><!--quickbook-escape-postfix--></emphasis><phrase role="special">;</phrase>
    <phrase role="comment">// construct async_result instance from handler_type</phrase>
    <phrase role="identifier">async_result</phrase><phrase role="special">&lt;</phrase><phrase role="keyword">decltype</phrase><phrase role="special">(</phrase><phrase role="identifier">handler</phrase><phrase role="special">)&gt;</phrase> <emphasis role="bold"><!--quickbook-escape-prefix--><code><!--quickbook-escape-postfix-->result(handler)<!--quickbook-escape-prefix--></code><!--quickbook-escape-postfix--></emphasis><phrase role="special">;</phrase>

    <phrase role="comment">// ... arrange to call handler on completion ...</phrase>
    <phrase role="comment">// ... initiate actual I/O operation ...</phrase>

    <phrase role="keyword">return</phrase> <emphasis role="bold"><!--quickbook-escape-prefix--><code><!--quickbook-escape-postfix-->result.get()<!--quickbook-escape-prefix--></code><!--quickbook-escape-postfix--></emphasis><phrase role="special">;</phrase>
<phrase role="special">}</phrase>
</programlisting>
      <para>
        We will engage that mechanism, which is based on specializing Asio&#8217;s <code><phrase
        role="identifier">handler_type</phrase><phrase role="special">&lt;&gt;</phrase></code>
        template for the <code><phrase role="identifier">CompletionToken</phrase></code>
        type and the signature of the specific callback. The remainder of this discussion
        will refer back to <code><phrase role="identifier">async_something</phrase><phrase
        role="special">()</phrase></code> as the Asio async function under consideration.
      </para>
      <para>
        The implementation described below uses lower-level facilities than <code><phrase
        role="identifier">promise</phrase></code> and <code><phrase role="identifier">future</phrase></code>
        because the <code><phrase role="identifier">promise</phrase></code> mechanism
        interacts badly with <ulink url="http://www.boost.org/doc/libs/release/doc/html/boost_asio/reference/io_service/stop.html"><code><phrase
        role="identifier">io_service</phrase><phrase role="special">::</phrase><phrase
        role="identifier">stop</phrase><phrase role="special">()</phrase></code></ulink>.
        It produces <code><phrase role="identifier">broken_promise</phrase></code>
        exceptions.
      </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 a completion token of this kind.
        <code><phrase role="identifier">yield</phrase></code> is an instance of
        <code><phrase role="identifier">yield_t</phrase></code>:
      </para>
      <para>
<programlisting><phrase role="keyword">class</phrase> <phrase role="identifier">yield_t</phrase> <phrase role="special">{</phrase>
<phrase role="keyword">public</phrase><phrase role="special">:</phrase>
    <phrase role="identifier">yield_t</phrase><phrase role="special">()</phrase> <phrase role="special">=</phrase> <phrase role="keyword">default</phrase><phrase role="special">;</phrase>

    <phrase role="comment">/**
     * @code
     * static yield_t yield;
     * boost::system::error_code myec;
     * func(yield[myec]);
     * @endcode
     * @c yield[myec] returns an instance of @c yield_t whose @c ec_ points
     * to @c myec. The expression @c yield[myec] &quot;binds&quot; @c myec to that
     * (anonymous) @c yield_t instance, instructing @c func() to store any
     * @c error_code it might produce into @c myec rather than throwing @c
     * boost::system::system_error.
     */</phrase>
    <phrase role="identifier">yield_t</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="special">&amp;</phrase> <phrase role="identifier">ec</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase> <phrase role="special">{</phrase>
        <phrase role="identifier">yield_t</phrase> <phrase role="identifier">tmp</phrase><phrase role="special">;</phrase>
        <phrase role="identifier">tmp</phrase><phrase role="special">.</phrase><phrase role="identifier">ec_</phrase> <phrase role="special">=</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">ec</phrase><phrase role="special">;</phrase>
        <phrase role="keyword">return</phrase> <phrase role="identifier">tmp</phrase><phrase role="special">;</phrase>
    <phrase role="special">}</phrase>

<phrase role="comment">//private:</phrase>
    <phrase role="comment">// ptr to bound error_code instance if any</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">nullptr</phrase> <phrase role="special">};</phrase>
<phrase role="special">};</phrase>
</programlisting>
      </para>
      <para>
        <code><phrase role="identifier">yield_t</phrase></code> is in fact only a
        placeholder, a way to trigger Boost.Asio customization. It can bind a <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>
        <code><phrase role="identifier">yield</phrase></code> is declared as:
      </para>
      <para>
<programlisting><phrase role="comment">// canonical instance</phrase>
<phrase role="keyword">thread_local</phrase> <phrase role="identifier">yield_t</phrase> <phrase role="identifier">yield</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="comment">// Handler type specialisation for fibers::asio::yield.</phrase>
<phrase role="comment">// When 'yield' is passed as a completion handler which accepts only</phrase>
<phrase role="comment">// error_code, use yield_handler&lt;void&gt;. yield_handler will take care of the</phrase>
<phrase role="comment">// error_code one way or another.</phrase>
<phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">ReturnType</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">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">asio</phrase><phrase role="special">::</phrase><phrase role="identifier">yield_t</phrase><phrase role="special">,</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="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="keyword">void</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.)
      </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. There&#8217;s a generic <code><phrase role="identifier">yield_handler</phrase><phrase
        role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase></code>
        implementation and a <code><phrase role="identifier">yield_handler</phrase><phrase
        role="special">&lt;</phrase><phrase role="keyword">void</phrase><phrase role="special">&gt;</phrase></code>
        specialization. Let&#8217;s start with the <code><phrase role="special">&lt;</phrase><phrase
        role="keyword">void</phrase><phrase role="special">&gt;</phrase></code> specialization:
      </para>
      <para>
<programlisting><phrase role="comment">// yield_handler&lt;void&gt; is like yield_handler&lt;T&gt; without value_. In fact it's</phrase>
<phrase role="comment">// just like yield_handler_base.</phrase>
<phrase role="keyword">template</phrase><phrase role="special">&lt;&gt;</phrase>
<phrase role="keyword">class</phrase> <phrase role="identifier">yield_handler</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">void</phrase> <phrase role="special">&gt;:</phrase> <phrase role="keyword">public</phrase> <phrase role="identifier">yield_handler_base</phrase> <phrase role="special">{</phrase>
<phrase role="keyword">public</phrase><phrase role="special">:</phrase>
    <phrase role="keyword">explicit</phrase> <phrase role="identifier">yield_handler</phrase><phrase role="special">(</phrase> <phrase role="identifier">yield_t</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">y</phrase><phrase role="special">)</phrase> <phrase role="special">:</phrase>
        <phrase role="identifier">yield_handler_base</phrase><phrase role="special">{</phrase> <phrase role="identifier">y</phrase> <phrase role="special">}</phrase> <phrase role="special">{</phrase>
    <phrase role="special">}</phrase>

    <phrase role="comment">// nullary completion callback</phrase>
    <phrase role="keyword">void</phrase> <phrase role="keyword">operator</phrase><phrase role="special">()()</phrase> <phrase role="special">{</phrase>
        <phrase role="special">(</phrase> <phrase role="special">*</phrase> <phrase role="keyword">this</phrase><phrase role="special">)(</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">system</phrase><phrase role="special">::</phrase><phrase role="identifier">error_code</phrase><phrase role="special">()</phrase> <phrase role="special">);</phrase>
    <phrase role="special">}</phrase>

    <phrase role="comment">// inherit operator()(error_code) overload from base class</phrase>
    <phrase role="keyword">using</phrase> <phrase role="identifier">yield_handler_base</phrase><phrase role="special">::</phrase><phrase role="keyword">operator</phrase><phrase role="special">();</phrase>
<phrase role="special">};</phrase>
</programlisting>
      </para>
      <para>
        <code><phrase role="identifier">async_something</phrase><phrase role="special">()</phrase></code>,
        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><phrase role="special">&lt;</phrase><phrase
        role="keyword">void</phrase><phrase role="special">&gt;</phrase></code> to
        be passed as the actual callback for the async operation. <code><phrase role="identifier">yield_handler</phrase></code>&#8217;s
        constructor accepts the <code><phrase role="identifier">yield_t</phrase></code>
        instance (the <code><phrase role="identifier">yield</phrase></code> object
        passed to the async function) and passes it along to <code><phrase role="identifier">yield_handler_base</phrase></code>:
      </para>
      <para>
<programlisting><phrase role="comment">// This class encapsulates common elements between yield_handler&lt;T&gt; (capturing</phrase>
<phrase role="comment">// a value to return from asio async function) and yield_handler&lt;void&gt; (no</phrase>
<phrase role="comment">// such value). See yield_handler&lt;T&gt; and its &lt;void&gt; specialization below. Both</phrase>
<phrase role="comment">// yield_handler&lt;T&gt; and yield_handler&lt;void&gt; are passed by value through</phrase>
<phrase role="comment">// various layers of asio functions. In other words, they're potentially</phrase>
<phrase role="comment">// copied multiple times. So key data such as the yield_completion instance</phrase>
<phrase role="comment">// must be stored in our async_result&lt;yield_handler&lt;&gt;&gt; specialization, which</phrase>
<phrase role="comment">// should be instantiated only once.</phrase>
<phrase role="keyword">class</phrase> <phrase role="identifier">yield_handler_base</phrase> <phrase role="special">{</phrase>
<phrase role="keyword">public</phrase><phrase role="special">:</phrase>
    <phrase role="identifier">yield_handler_base</phrase><phrase role="special">(</phrase> <phrase role="identifier">yield_t</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">y</phrase><phrase role="special">)</phrase> <phrase role="special">:</phrase>
        <phrase role="comment">// capture the context* associated with the running fiber</phrase>
        <phrase role="identifier">ctx_</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">active</phrase><phrase role="special">()</phrase> <phrase role="special">},</phrase>
        <phrase role="comment">// capture the passed yield_t</phrase>
        <phrase role="identifier">yt_</phrase><phrase role="special">(</phrase> <phrase role="identifier">y</phrase> <phrase role="special">)</phrase> <phrase role="special">{</phrase>
    <phrase role="special">}</phrase>

    <phrase role="comment">// completion callback passing only (error_code)</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="special">{</phrase>
        <phrase role="identifier">BOOST_ASSERT_MSG</phrase><phrase role="special">(</phrase> <phrase role="identifier">ycomp_</phrase><phrase role="special">,</phrase>
                          <phrase role="string">&quot;Must inject yield_completion* &quot;</phrase>
                          <phrase role="string">&quot;before calling yield_handler_base::operator()()&quot;</phrase><phrase role="special">);</phrase>
        <phrase role="identifier">BOOST_ASSERT_MSG</phrase><phrase role="special">(</phrase> <phrase role="identifier">yt_</phrase><phrase role="special">.</phrase><phrase role="identifier">ec_</phrase><phrase role="special">,</phrase>
                          <phrase role="string">&quot;Must inject boost::system::error_code* &quot;</phrase>
                          <phrase role="string">&quot;before calling yield_handler_base::operator()()&quot;</phrase><phrase role="special">);</phrase>
        <phrase role="comment">// If originating fiber is busy testing state_ flag, wait until it</phrase>
        <phrase role="comment">// has observed (completed != state_).</phrase>
        <phrase role="identifier">yield_completion</phrase><phrase role="special">::</phrase><phrase role="identifier">lock_t</phrase> <phrase role="identifier">lk</phrase><phrase role="special">{</phrase> <phrase role="identifier">ycomp_</phrase><phrase role="special">-&gt;</phrase><phrase role="identifier">mtx_</phrase> <phrase role="special">};</phrase>
        <phrase role="identifier">yield_completion</phrase><phrase role="special">::</phrase><phrase role="identifier">state_t</phrase> <phrase role="identifier">state</phrase> <phrase role="special">=</phrase> <phrase role="identifier">ycomp_</phrase><phrase role="special">-&gt;</phrase><phrase role="identifier">state_</phrase><phrase role="special">;</phrase>
        <phrase role="comment">// Notify a subsequent yield_completion::wait() call that it need not</phrase>
        <phrase role="comment">// suspend.</phrase>
        <phrase role="identifier">ycomp_</phrase><phrase role="special">-&gt;</phrase><phrase role="identifier">state_</phrase> <phrase role="special">=</phrase> <phrase role="identifier">yield_completion</phrase><phrase role="special">::</phrase><phrase role="identifier">complete</phrase><phrase role="special">;</phrase>
        <phrase role="comment">// set the error_code bound by yield_t</phrase>
        <phrase role="special">*</phrase> <phrase role="identifier">yt_</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="comment">// unlock the lock that protects state_</phrase>
        <phrase role="identifier">lk</phrase><phrase role="special">.</phrase><phrase role="identifier">unlock</phrase><phrase role="special">();</phrase>
        <phrase role="comment">// If ctx_ is still active, e.g. because the async operation</phrase>
        <phrase role="comment">// immediately called its callback (this method!) before the asio</phrase>
        <phrase role="comment">// async function called async_result_base::get(), we must not set it</phrase>
        <phrase role="comment">// ready.</phrase>
        <phrase role="keyword">if</phrase> <phrase role="special">(</phrase> <phrase role="identifier">yield_completion</phrase><phrase role="special">::</phrase><phrase role="identifier">waiting</phrase> <phrase role="special">==</phrase> <phrase role="identifier">state</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
            <phrase role="comment">// wake the fiber</phrase>
            <phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">context</phrase><phrase role="special">::</phrase><phrase role="identifier">active</phrase><phrase role="special">()-&gt;</phrase><phrase role="identifier">schedule</phrase><phrase role="special">(</phrase> <phrase role="identifier">ctx_</phrase><phrase role="special">);</phrase>
        <phrase role="special">}</phrase>
    <phrase role="special">}</phrase>

<phrase role="comment">//private:</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">ctx_</phrase><phrase role="special">;</phrase>
    <phrase role="identifier">yield_t</phrase>                         <phrase role="identifier">yt_</phrase><phrase role="special">;</phrase>
    <phrase role="comment">// We depend on this pointer to yield_completion, which will be injected</phrase>
    <phrase role="comment">// by async_result.</phrase>
    <phrase role="identifier">yield_completion</phrase><phrase role="special">::</phrase><phrase role="identifier">ptr_t</phrase>         <phrase role="identifier">ycomp_</phrase><phrase role="special">{};</phrase>
<phrase role="special">};</phrase>
</programlisting>
      </para>
      <para>
        <code><phrase role="identifier">yield_handler_base</phrase></code> stores
        a copy of the <code><phrase role="identifier">yield_t</phrase></code> instance
        &mdash; which, as shown above, contains only an <code><phrase role="identifier">error_code</phrase><phrase
        role="special">*</phrase></code>. It also captures the <link linkend="class_context"><code>context</code></link>*
        for the currently-running fiber by calling <link linkend="context_active"><code>context::active()</code></link>.
      </para>
      <para>
        You will notice that <code><phrase role="identifier">yield_handler_base</phrase></code>
        has one more data member (<code><phrase role="identifier">ycomp_</phrase></code>)
        that is initialized to <code><phrase role="keyword">nullptr</phrase></code>
        by its constructor &mdash; though its <code><phrase role="keyword">operator</phrase><phrase
        role="special">()()</phrase></code> method relies on <code><phrase role="identifier">ycomp_</phrase></code>
        being non-null. More on this in a moment.
      </para>
      <para>
        Having constructed the <code><phrase role="identifier">yield_handler</phrase><phrase
        role="special">&lt;</phrase><phrase role="keyword">void</phrase><phrase role="special">&gt;</phrase></code>
        instance, <code><phrase role="identifier">async_something</phrase><phrase
        role="special">()</phrase></code> goes on to construct an <code><phrase role="identifier">async_result</phrase></code>
        specialized for the <code><phrase role="identifier">handler_type</phrase><phrase
        role="special">&lt;&gt;::</phrase><phrase role="identifier">type</phrase></code>:
        in this case, <code><phrase role="identifier">async_result</phrase><phrase
        role="special">&lt;</phrase><phrase role="identifier">yield_handler</phrase><phrase
        role="special">&lt;</phrase><phrase role="keyword">void</phrase><phrase role="special">&gt;&gt;</phrase></code>.
        It passes the <code><phrase role="identifier">yield_handler</phrase><phrase
        role="special">&lt;</phrase><phrase role="keyword">void</phrase><phrase role="special">&gt;</phrase></code>
        instance to the new <code><phrase role="identifier">async_result</phrase></code>
        instance.
      </para>
      <para>
<programlisting><phrase role="comment">// Without the need to handle a passed value, our yield_handler&lt;void&gt;</phrase>
<phrase role="comment">// specialization is just like async_result_base.</phrase>
<phrase role="keyword">template</phrase><phrase role="special">&lt;&gt;</phrase>
<phrase role="keyword">class</phrase> <phrase role="identifier">async_result</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">detail</phrase><phrase role="special">::</phrase><phrase role="identifier">yield_handler</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">void</phrase> <phrase role="special">&gt;</phrase> <phrase role="special">&gt;</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">asio</phrase><phrase role="special">::</phrase><phrase role="identifier">detail</phrase><phrase role="special">::</phrase><phrase role="identifier">async_result_base</phrase> <phrase role="special">{</phrase>
<phrase role="keyword">public</phrase><phrase role="special">:</phrase>
    <phrase role="keyword">typedef</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">type</phrase><phrase role="special">;</phrase>

    <phrase role="keyword">explicit</phrase> <phrase role="identifier">async_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">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="keyword">void</phrase> <phrase role="special">&gt;</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">h</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">detail</phrase><phrase role="special">::</phrase><phrase role="identifier">async_result_base</phrase><phrase role="special">{</phrase> <phrase role="identifier">h</phrase> <phrase role="special">}</phrase> <phrase role="special">{</phrase>
    <phrase role="special">}</phrase>
<phrase role="special">};</phrase>
</programlisting>
      </para>
      <para>
        Naturally that leads us straight to <code><phrase role="identifier">async_result_base</phrase></code>:
      </para>
      <para>
<programlisting><phrase role="comment">// Factor out commonality between async_result&lt;yield_handler&lt;T&gt;&gt; and</phrase>
<phrase role="comment">// async_result&lt;yield_handler&lt;void&gt;&gt;</phrase>
<phrase role="keyword">class</phrase> <phrase role="identifier">async_result_base</phrase> <phrase role="special">{</phrase>
<phrase role="keyword">public</phrase><phrase role="special">:</phrase>
    <phrase role="keyword">explicit</phrase> <phrase role="identifier">async_result_base</phrase><phrase role="special">(</phrase> <phrase role="identifier">yield_handler_base</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">h</phrase><phrase role="special">)</phrase> <phrase role="special">:</phrase>
            <phrase role="identifier">ycomp_</phrase><phrase role="special">{</phrase> <phrase role="keyword">new</phrase> <phrase role="identifier">yield_completion</phrase><phrase role="special">{}</phrase> <phrase role="special">}</phrase> <phrase role="special">{</phrase>
        <phrase role="comment">// Inject ptr to our yield_completion instance into this</phrase>
        <phrase role="comment">// yield_handler&lt;&gt;.</phrase>
        <phrase role="identifier">h</phrase><phrase role="special">.</phrase><phrase role="identifier">ycomp_</phrase> <phrase role="special">=</phrase> <phrase role="keyword">this</phrase><phrase role="special">-&gt;</phrase><phrase role="identifier">ycomp_</phrase><phrase role="special">;</phrase>
        <phrase role="comment">// if yield_t didn't bind an error_code, make yield_handler_base's</phrase>
        <phrase role="comment">// error_code* point to an error_code local to this object so</phrase>
        <phrase role="comment">// yield_handler_base::operator() can unconditionally store through</phrase>
        <phrase role="comment">// its error_code*</phrase>
        <phrase role="keyword">if</phrase> <phrase role="special">(</phrase> <phrase role="special">!</phrase> <phrase role="identifier">h</phrase><phrase role="special">.</phrase><phrase role="identifier">yt_</phrase><phrase role="special">.</phrase><phrase role="identifier">ec_</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
            <phrase role="identifier">h</phrase><phrase role="special">.</phrase><phrase role="identifier">yt_</phrase><phrase role="special">.</phrase><phrase role="identifier">ec_</phrase> <phrase role="special">=</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">ec_</phrase><phrase role="special">;</phrase>
        <phrase role="special">}</phrase>
    <phrase role="special">}</phrase>

    <phrase role="keyword">void</phrase> <phrase role="identifier">get</phrase><phrase role="special">()</phrase> <phrase role="special">{</phrase>
        <phrase role="comment">// Unless yield_handler_base::operator() has already been called,</phrase>
        <phrase role="comment">// suspend the calling fiber until that call.</phrase>
        <phrase role="identifier">ycomp_</phrase><phrase role="special">-&gt;</phrase><phrase role="identifier">wait</phrase><phrase role="special">();</phrase>
        <phrase role="comment">// The only way our own ec_ member could have a non-default value is</phrase>
        <phrase role="comment">// if our yield_handler did not have a bound error_code AND the</phrase>
        <phrase role="comment">// completion callback passed a non-default error_code.</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="identifier">throw_exception</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="special">}</phrase>

<phrase role="keyword">private</phrase><phrase role="special">:</phrase>
    <phrase role="comment">// If yield_t does not bind an error_code instance, store into here.</phrase>
    <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">system</phrase><phrase role="special">::</phrase><phrase role="identifier">error_code</phrase>       <phrase role="identifier">ec_</phrase><phrase role="special">{};</phrase>
    <phrase role="identifier">yield_completion</phrase><phrase role="special">::</phrase><phrase role="identifier">ptr_t</phrase>         <phrase role="identifier">ycomp_</phrase><phrase role="special">;</phrase>
<phrase role="special">};</phrase>
</programlisting>
      </para>
      <para>
        This is how <code><phrase role="identifier">yield_handler_base</phrase><phrase
        role="special">::</phrase><phrase role="identifier">ycomp_</phrase></code>
        becomes non-null: <code><phrase role="identifier">async_result_base</phrase></code>&#8217;s
        constructor injects a pointer back to its own <code><phrase role="identifier">yield_completion</phrase></code>
        member.
      </para>
      <para>
        Recall that the canonical <code><phrase role="identifier">yield_t</phrase></code>
        instance <code><phrase role="identifier">yield</phrase></code> initializes
        its <code><phrase role="identifier">error_code</phrase><phrase role="special">*</phrase></code>
        member <code><phrase role="identifier">ec_</phrase></code> to <code><phrase
        role="keyword">nullptr</phrase></code>. If this instance is passed to <code><phrase
        role="identifier">async_something</phrase><phrase role="special">()</phrase></code>
        (<code><phrase role="identifier">ec_</phrase></code> is still <code><phrase
        role="keyword">nullptr</phrase></code>), the copy stored in <code><phrase
        role="identifier">yield_handler_base</phrase></code> will likewise have null
        <code><phrase role="identifier">ec_</phrase></code>. <code><phrase role="identifier">async_result_base</phrase></code>&#8217;s
        constructor sets <code><phrase role="identifier">yield_handler_base</phrase></code>&#8217;s
        <code><phrase role="identifier">yield_t</phrase></code>&#8217;s <code><phrase role="identifier">ec_</phrase></code>
        member to point to its own <code><phrase role="identifier">error_code</phrase></code>
        member.
      </para>
      <para>
        The stage is now set. <code><phrase role="identifier">async_something</phrase><phrase
        role="special">()</phrase></code> initiates the actual async operation, arranging
        to call its <code><phrase role="identifier">yield_handler</phrase><phrase
        role="special">&lt;</phrase><phrase role="keyword">void</phrase><phrase role="special">&gt;</phrase></code>
        instance on completion. Let&#8217;s say, for the sake of argument, that the actual
        async operation&#8217;s callback has signature <code><phrase role="keyword">void</phrase><phrase
        role="special">(</phrase><phrase role="identifier">error_code</phrase><phrase
        role="special">)</phrase></code>.
      </para>
      <para>
        But since it&#8217;s an async operation, control returns at once to <code><phrase
        role="identifier">async_something</phrase><phrase role="special">()</phrase></code>.
        <code><phrase role="identifier">async_something</phrase><phrase role="special">()</phrase></code>
        calls <code><phrase role="identifier">async_result</phrase><phrase role="special">&lt;</phrase><phrase
        role="identifier">yield_handler</phrase><phrase role="special">&lt;</phrase><phrase
        role="keyword">void</phrase><phrase role="special">&gt;&gt;::</phrase><phrase
        role="identifier">get</phrase><phrase role="special">()</phrase></code>,
        and will return its return value.
      </para>
      <para>
        <code><phrase role="identifier">async_result</phrase><phrase role="special">&lt;</phrase><phrase
        role="identifier">yield_handler</phrase><phrase role="special">&lt;</phrase><phrase
        role="keyword">void</phrase><phrase role="special">&gt;&gt;::</phrase><phrase
        role="identifier">get</phrase><phrase role="special">()</phrase></code> inherits
        <code><phrase role="identifier">async_result_base</phrase><phrase role="special">::</phrase><phrase
        role="identifier">get</phrase><phrase role="special">()</phrase></code>.
      </para>
      <para>
        <code><phrase role="identifier">async_result_base</phrase><phrase role="special">::</phrase><phrase
        role="identifier">get</phrase><phrase role="special">()</phrase></code> immediately
        calls <code><phrase role="identifier">yield_completion</phrase><phrase role="special">::</phrase><phrase
        role="identifier">wait</phrase><phrase role="special">()</phrase></code>.
      </para>
      <para>
<programlisting><phrase role="comment">// Bundle a completion bool flag with a spinlock to protect it.</phrase>
<phrase role="keyword">struct</phrase> <phrase role="identifier">yield_completion</phrase> <phrase role="special">{</phrase>
    <phrase role="keyword">enum</phrase> <phrase role="identifier">state_t</phrase> <phrase role="special">{</phrase>
        <phrase role="identifier">init</phrase><phrase role="special">,</phrase>
        <phrase role="identifier">waiting</phrase><phrase role="special">,</phrase>
        <phrase role="identifier">complete</phrase>
    <phrase role="special">};</phrase>

    <phrase role="keyword">typedef</phrase> <phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">detail</phrase><phrase role="special">::</phrase><phrase role="identifier">spinlock</phrase>                    <phrase role="identifier">mutex_t</phrase><phrase role="special">;</phrase>
    <phrase role="keyword">typedef</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">unique_lock</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">mutex_t</phrase> <phrase role="special">&gt;</phrase>                 <phrase role="identifier">lock_t</phrase><phrase role="special">;</phrase>
    <phrase role="keyword">typedef</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">intrusive_ptr</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">yield_completion</phrase> <phrase role="special">&gt;</phrase>    <phrase role="identifier">ptr_t</phrase><phrase role="special">;</phrase>

    <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">atomic</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="special">&gt;</phrase>  <phrase role="identifier">use_count_</phrase><phrase role="special">{</phrase> <phrase role="number">0</phrase> <phrase role="special">};</phrase>
    <phrase role="identifier">mutex_t</phrase>                     <phrase role="identifier">mtx_</phrase><phrase role="special">{};</phrase>
    <phrase role="identifier">state_t</phrase>                     <phrase role="identifier">state_</phrase><phrase role="special">{</phrase> <phrase role="identifier">init</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="comment">// yield_handler_base::operator()() will set state_ `complete` and</phrase>
        <phrase role="comment">// attempt to wake a suspended fiber. It would be Bad if that call</phrase>
        <phrase role="comment">// happened between our detecting (complete != state_) and suspending.</phrase>
        <phrase role="identifier">lock_t</phrase> <phrase role="identifier">lk</phrase><phrase role="special">{</phrase> <phrase role="identifier">mtx_</phrase> <phrase role="special">};</phrase>
        <phrase role="comment">// If state_ is already set, we're done here: don't suspend.</phrase>
        <phrase role="keyword">if</phrase> <phrase role="special">(</phrase> <phrase role="identifier">complete</phrase> <phrase role="special">!=</phrase> <phrase role="identifier">state_</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
            <phrase role="identifier">state_</phrase> <phrase role="special">=</phrase> <phrase role="identifier">waiting</phrase><phrase role="special">;</phrase>
            <phrase role="comment">// suspend(unique_lock&lt;spinlock&gt;) unlocks the lock in the act of</phrase>
            <phrase role="comment">// resuming another fiber</phrase>
            <phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">context</phrase><phrase role="special">::</phrase><phrase role="identifier">active</phrase><phrase role="special">()-&gt;</phrase><phrase role="identifier">suspend</phrase><phrase role="special">(</phrase> <phrase role="identifier">lk</phrase><phrase role="special">);</phrase>
        <phrase role="special">}</phrase>
    <phrase role="special">}</phrase>

    <phrase role="keyword">friend</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">intrusive_ptr_add_ref</phrase><phrase role="special">(</phrase> <phrase role="identifier">yield_completion</phrase> <phrase role="special">*</phrase> <phrase role="identifier">yc</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase> <phrase role="special">{</phrase>
        <phrase role="identifier">BOOST_ASSERT</phrase><phrase role="special">(</phrase> <phrase role="keyword">nullptr</phrase> <phrase role="special">!=</phrase> <phrase role="identifier">yc</phrase><phrase role="special">);</phrase>
        <phrase role="identifier">yc</phrase><phrase role="special">-&gt;</phrase><phrase role="identifier">use_count_</phrase><phrase role="special">.</phrase><phrase role="identifier">fetch_add</phrase><phrase role="special">(</phrase> <phrase role="number">1</phrase><phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">memory_order_relaxed</phrase><phrase role="special">);</phrase>
    <phrase role="special">}</phrase>

    <phrase role="keyword">friend</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">intrusive_ptr_release</phrase><phrase role="special">(</phrase> <phrase role="identifier">yield_completion</phrase> <phrase role="special">*</phrase> <phrase role="identifier">yc</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase> <phrase role="special">{</phrase>
        <phrase role="identifier">BOOST_ASSERT</phrase><phrase role="special">(</phrase> <phrase role="keyword">nullptr</phrase> <phrase role="special">!=</phrase> <phrase role="identifier">yc</phrase><phrase role="special">);</phrase>
        <phrase role="keyword">if</phrase> <phrase role="special">(</phrase> <phrase role="number">1</phrase> <phrase role="special">==</phrase> <phrase role="identifier">yc</phrase><phrase role="special">-&gt;</phrase><phrase role="identifier">use_count_</phrase><phrase role="special">.</phrase><phrase role="identifier">fetch_sub</phrase><phrase role="special">(</phrase> <phrase role="number">1</phrase><phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">memory_order_release</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">atomic_thread_fence</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">memory_order_acquire</phrase><phrase role="special">);</phrase>
            <phrase role="keyword">delete</phrase> <phrase role="identifier">yc</phrase><phrase role="special">;</phrase>
        <phrase role="special">}</phrase>
    <phrase role="special">}</phrase>
<phrase role="special">};</phrase>
</programlisting>
      </para>
      <para>
        Supposing that the pending async operation has not yet completed, <code><phrase
        role="identifier">yield_completion</phrase><phrase role="special">::</phrase><phrase
        role="identifier">completed_</phrase></code> will still be <code><phrase
        role="keyword">false</phrase></code>, and <code><phrase role="identifier">wait</phrase><phrase
        role="special">()</phrase></code> will call <link linkend="context_suspend"><code>context::suspend()</code></link> on
        the currently-running fiber.
      </para>
      <para>
        Other fibers will now have a chance to run.
      </para>
      <para>
        Some time later, the async operation completes. It calls <code><phrase role="identifier">yield_handler</phrase><phrase
        role="special">&lt;</phrase><phrase role="keyword">void</phrase><phrase role="special">&gt;::</phrase><phrase
        role="keyword">operator</phrase><phrase role="special">()(</phrase><phrase
        role="identifier">error_code</phrase> <phrase role="keyword">const</phrase><phrase
        role="special">&amp;)</phrase></code> with an <code><phrase role="identifier">error_code</phrase></code>
        indicating either success or failure. We&#8217;ll consider both cases.
      </para>
      <para>
        <code><phrase role="identifier">yield_handler</phrase><phrase role="special">&lt;</phrase><phrase
        role="keyword">void</phrase><phrase role="special">&gt;</phrase></code> explicitly
        inherits <code><phrase role="keyword">operator</phrase><phrase role="special">()(</phrase><phrase
        role="identifier">error_code</phrase> <phrase role="keyword">const</phrase><phrase
        role="special">&amp;)</phrase></code> from <code><phrase role="identifier">yield_handler_base</phrase></code>.
      </para>
      <para>
        <code><phrase role="identifier">yield_handler_base</phrase><phrase role="special">::</phrase><phrase
        role="keyword">operator</phrase><phrase role="special">()(</phrase><phrase
        role="identifier">error_code</phrase> <phrase role="keyword">const</phrase><phrase
        role="special">&amp;)</phrase></code> first sets <code><phrase role="identifier">yield_completion</phrase><phrase
        role="special">::</phrase><phrase role="identifier">completed_</phrase></code>
        <code><phrase role="keyword">true</phrase></code>. This way, if <code><phrase
        role="identifier">async_something</phrase><phrase role="special">()</phrase></code>&#8217;s
        async operation completes immediately &mdash; if <code><phrase role="identifier">yield_handler_base</phrase><phrase
        role="special">::</phrase><phrase role="keyword">operator</phrase><phrase
        role="special">()</phrase></code> is called even before <code><phrase role="identifier">async_result_base</phrase><phrase
        role="special">::</phrase><phrase role="identifier">get</phrase><phrase role="special">()</phrase></code>
        &mdash; the calling fiber will <emphasis>not</emphasis> suspend.
      </para>
      <para>
        The actual <code><phrase role="identifier">error_code</phrase></code> produced
        by the async operation is then stored through the stored <code><phrase role="identifier">yield_t</phrase><phrase
        role="special">::</phrase><phrase role="identifier">ec_</phrase></code> pointer.
        If <code><phrase role="identifier">async_something</phrase><phrase role="special">()</phrase></code>&#8217;s
        caller used (e.g.) <code><phrase role="identifier">yield</phrase><phrase
        role="special">[</phrase><phrase role="identifier">my_ec</phrase><phrase
        role="special">]</phrase></code> to bind a local <code><phrase role="identifier">error_code</phrase></code>
        instance, the actual <code><phrase role="identifier">error_code</phrase></code>
        value is stored into the caller&#8217;s variable. Otherwise, it is stored into
        <code><phrase role="identifier">async_result_base</phrase><phrase role="special">::</phrase><phrase
        role="identifier">ec_</phrase></code>.
      </para>
      <para>
        If the stored fiber context <code><phrase role="identifier">yield_handler_base</phrase><phrase
        role="special">::</phrase><phrase role="identifier">ctx_</phrase></code>
        is not already running, it is marked as ready to run by passing it to <link linkend="context_schedule"><code>context::schedule()</code></link>.
        Control then returns from <code><phrase role="identifier">yield_handler_base</phrase><phrase
        role="special">::</phrase><phrase role="keyword">operator</phrase><phrase
        role="special">()</phrase></code>: the callback is done.
      </para>
      <para>
        In due course, that fiber is resumed. Control returns from <link linkend="context_suspend"><code>context::suspend()</code></link> to
        <code><phrase role="identifier">yield_completion</phrase><phrase role="special">::</phrase><phrase
        role="identifier">wait</phrase><phrase role="special">()</phrase></code>,
        which returns to <code><phrase role="identifier">async_result_base</phrase><phrase
        role="special">::</phrase><phrase role="identifier">get</phrase><phrase role="special">()</phrase></code>.
      </para>
      <itemizedlist>
        <listitem>
          <simpara>
            If the original caller passed <code><phrase role="identifier">yield</phrase><phrase
            role="special">[</phrase><phrase role="identifier">my_ec</phrase><phrase
            role="special">]</phrase></code> to <code><phrase role="identifier">async_something</phrase><phrase
            role="special">()</phrase></code> to bind a local <code><phrase role="identifier">error_code</phrase></code>
            instance, then <code><phrase role="identifier">yield_handler_base</phrase><phrase
            role="special">::</phrase><phrase role="keyword">operator</phrase><phrase
            role="special">()</phrase></code> stored its <code><phrase role="identifier">error_code</phrase></code>
            to the caller&#8217;s <code><phrase role="identifier">my_ec</phrase></code>
            instance, leaving <code><phrase role="identifier">async_result_base</phrase><phrase
            role="special">::</phrase><phrase role="identifier">ec_</phrase></code>
            initialized to success.
          </simpara>
        </listitem>
        <listitem>
          <simpara>
            If the original caller passed <code><phrase role="identifier">yield</phrase></code>
            to <code><phrase role="identifier">async_something</phrase><phrase role="special">()</phrase></code>
            without binding a local <code><phrase role="identifier">error_code</phrase></code>
            variable, then <code><phrase role="identifier">yield_handler_base</phrase><phrase
            role="special">::</phrase><phrase role="keyword">operator</phrase><phrase
            role="special">()</phrase></code> stored its <code><phrase role="identifier">error_code</phrase></code>
            into <code><phrase role="identifier">async_result_base</phrase><phrase
            role="special">::</phrase><phrase role="identifier">ec_</phrase></code>.
            If in fact that <code><phrase role="identifier">error_code</phrase></code>
            is success, then all is well.
          </simpara>
        </listitem>
        <listitem>
          <simpara>
            Otherwise &mdash; the original caller did not bind a local <code><phrase role="identifier">error_code</phrase></code>
            and <code><phrase role="identifier">yield_handler_base</phrase><phrase
            role="special">::</phrase><phrase role="keyword">operator</phrase><phrase
            role="special">()</phrase></code> was called with an <code><phrase role="identifier">error_code</phrase></code>
            indicating error &mdash; <code><phrase role="identifier">async_result_base</phrase><phrase
            role="special">::</phrase><phrase role="identifier">get</phrase><phrase
            role="special">()</phrase></code> throws <code><phrase role="identifier">system_error</phrase></code>
            with that <code><phrase role="identifier">error_code</phrase></code>.
          </simpara>
        </listitem>
      </itemizedlist>
      <para>
        The case in which <code><phrase role="identifier">async_something</phrase><phrase
        role="special">()</phrase></code>&#8217;s completion callback has signature <code><phrase
        role="keyword">void</phrase><phrase role="special">()</phrase></code> is
        similar. <code><phrase role="identifier">yield_handler</phrase><phrase role="special">&lt;</phrase><phrase
        role="keyword">void</phrase><phrase role="special">&gt;::</phrase><phrase
        role="keyword">operator</phrase><phrase role="special">()()</phrase></code>
        invokes the machinery above with a <quote>success</quote> <code><phrase role="identifier">error_code</phrase></code>.
      </para>
      <para>
        A completion callback with signature <code><phrase role="keyword">void</phrase><phrase
        role="special">(</phrase><phrase role="identifier">error_code</phrase><phrase
        role="special">,</phrase> <phrase role="identifier">T</phrase><phrase role="special">)</phrase></code>
        (that is: in addition to <code><phrase role="identifier">error_code</phrase></code>,
        callback receives some data item) is handled somewhat differently. For this
        kind of signature, <code><phrase role="identifier">handler_type</phrase><phrase
        role="special">&lt;&gt;::</phrase><phrase role="identifier">type</phrase></code>
        specifies <code><phrase role="identifier">yield_handler</phrase><phrase role="special">&lt;</phrase><phrase
        role="identifier">T</phrase><phrase role="special">&gt;</phrase></code> (for
        <code><phrase role="identifier">T</phrase></code> other than <code><phrase
        role="keyword">void</phrase></code>).
      </para>
      <para>
        A <code><phrase role="identifier">yield_handler</phrase><phrase role="special">&lt;</phrase><phrase
        role="identifier">T</phrase><phrase role="special">&gt;</phrase></code> reserves
        a <code><phrase role="identifier">value_</phrase></code> pointer to a value
        of type <code><phrase role="identifier">T</phrase></code>:
      </para>
      <para>
<programlisting><phrase role="comment">// asio uses handler_type&lt;completion token type, signature&gt;::type to decide</phrase>
<phrase role="comment">// what to instantiate as the actual handler. Below, we specialize</phrase>
<phrase role="comment">// handler_type&lt; yield_t, ... &gt; to indicate yield_handler&lt;&gt;. So when you pass</phrase>
<phrase role="comment">// an instance of yield_t as an asio completion token, asio selects</phrase>
<phrase role="comment">// yield_handler&lt;&gt; as the actual handler class.</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">yield_handler</phrase><phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <phrase role="identifier">yield_handler_base</phrase> <phrase role="special">{</phrase>
<phrase role="keyword">public</phrase><phrase role="special">:</phrase>
    <phrase role="comment">// asio passes the completion token to the handler constructor</phrase>
    <phrase role="keyword">explicit</phrase> <phrase role="identifier">yield_handler</phrase><phrase role="special">(</phrase> <phrase role="identifier">yield_t</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">y</phrase><phrase role="special">)</phrase> <phrase role="special">:</phrase>
        <phrase role="identifier">yield_handler_base</phrase><phrase role="special">{</phrase> <phrase role="identifier">y</phrase> <phrase role="special">}</phrase> <phrase role="special">{</phrase>
    <phrase role="special">}</phrase>

    <phrase role="comment">// completion callback passing only value (T)</phrase>
    <phrase role="keyword">void</phrase> <phrase role="keyword">operator</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="comment">// just like callback passing success error_code</phrase>
        <phrase role="special">(*</phrase><phrase role="keyword">this</phrase><phrase role="special">)(</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">system</phrase><phrase role="special">::</phrase><phrase role="identifier">error_code</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">t</phrase><phrase role="special">)</phrase> <phrase role="special">);</phrase>
    <phrase role="special">}</phrase>

    <phrase role="comment">// completion callback passing (error_code, T)</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="identifier">BOOST_ASSERT_MSG</phrase><phrase role="special">(</phrase> <phrase role="identifier">value_</phrase><phrase role="special">,</phrase>
                          <phrase role="string">&quot;Must inject value ptr &quot;</phrase>
                          <phrase role="string">&quot;before caling yield_handler&lt;T&gt;::operator()()&quot;</phrase><phrase role="special">);</phrase>
        <phrase role="comment">// move the value to async_result&lt;&gt; instance BEFORE waking up a</phrase>
        <phrase role="comment">// suspended fiber</phrase>
        <phrase role="special">*</phrase> <phrase role="identifier">value_</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">t</phrase><phrase role="special">);</phrase>
        <phrase role="comment">// forward the call to base-class completion handler</phrase>
        <phrase role="identifier">yield_handler_base</phrase><phrase role="special">::</phrase><phrase role="keyword">operator</phrase><phrase role="special">()(</phrase> <phrase role="identifier">ec</phrase><phrase role="special">);</phrase>
    <phrase role="special">}</phrase>

<phrase role="comment">//private:</phrase>
    <phrase role="comment">// pointer to destination for eventual value</phrase>
    <phrase role="comment">// this must be injected by async_result before operator()() is called</phrase>
    <phrase role="identifier">T</phrase>   <phrase role="special">*</phrase>   <phrase role="identifier">value_</phrase><phrase role="special">{</phrase> <phrase role="keyword">nullptr</phrase> <phrase role="special">};</phrase>
<phrase role="special">};</phrase>
</programlisting>
      </para>
      <para>
        This pointer is initialized to <code><phrase role="keyword">nullptr</phrase></code>.
      </para>
      <para>
        When <code><phrase role="identifier">async_something</phrase><phrase role="special">()</phrase></code>
        instantiates <code><phrase role="identifier">async_result</phrase><phrase
        role="special">&lt;</phrase><phrase role="identifier">yield_handler</phrase><phrase
        role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;&gt;</phrase></code>:
      </para>
      <para>
<programlisting><phrase role="comment">// asio constructs an async_result&lt;&gt; instance from the yield_handler specified</phrase>
<phrase role="comment">// by handler_type&lt;&gt;::type. A particular asio async method constructs the</phrase>
<phrase role="comment">// yield_handler, constructs this async_result specialization from it, then</phrase>
<phrase role="comment">// returns the result of calling its get() method.</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">async_result</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">detail</phrase><phrase role="special">::</phrase><phrase role="identifier">yield_handler</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">T</phrase> <phrase role="special">&gt;</phrase> <phrase role="special">&gt;</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">asio</phrase><phrase role="special">::</phrase><phrase role="identifier">detail</phrase><phrase role="special">::</phrase><phrase role="identifier">async_result_base</phrase> <phrase role="special">{</phrase>
<phrase role="keyword">public</phrase><phrase role="special">:</phrase>
    <phrase role="comment">// type returned by get()</phrase>
    <phrase role="keyword">typedef</phrase> <phrase role="identifier">T</phrase> <phrase role="identifier">type</phrase><phrase role="special">;</phrase>

    <phrase role="keyword">explicit</phrase> <phrase role="identifier">async_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">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">T</phrase> <phrase role="special">&gt;</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">h</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">asio</phrase><phrase role="special">::</phrase><phrase role="identifier">detail</phrase><phrase role="special">::</phrase><phrase role="identifier">async_result_base</phrase><phrase role="special">{</phrase> <phrase role="identifier">h</phrase> <phrase role="special">}</phrase> <phrase role="special">{</phrase>
        <phrase role="comment">// Inject ptr to our value_ member into yield_handler&lt;&gt;: result will</phrase>
        <phrase role="comment">// be stored here.</phrase>
        <phrase role="identifier">h</phrase><phrase role="special">.</phrase><phrase role="identifier">value_</phrase> <phrase role="special">=</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">value_</phrase><phrase role="special">;</phrase>
    <phrase role="special">}</phrase>

    <phrase role="comment">// asio async method returns result of calling get()</phrase>
    <phrase role="identifier">type</phrase> <phrase role="identifier">get</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">asio</phrase><phrase role="special">::</phrase><phrase role="identifier">detail</phrase><phrase role="special">::</phrase><phrase role="identifier">async_result_base</phrase><phrase role="special">::</phrase><phrase role="identifier">get</phrase><phrase role="special">();</phrase>
        <phrase role="keyword">return</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">move</phrase><phrase role="special">(</phrase> <phrase role="identifier">value_</phrase><phrase role="special">);</phrase>
    <phrase role="special">}</phrase>

<phrase role="keyword">private</phrase><phrase role="special">:</phrase>
    <phrase role="identifier">type</phrase>                            <phrase role="identifier">value_</phrase><phrase role="special">{};</phrase>
<phrase role="special">};</phrase>
</programlisting>
      </para>
      <para>
        this <code><phrase role="identifier">async_result</phrase><phrase role="special">&lt;&gt;</phrase></code>
        specialization reserves a member of type <code><phrase role="identifier">T</phrase></code>
        to receive the passed data item, and sets <code><phrase role="identifier">yield_handler</phrase><phrase
        role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase
        role="identifier">value_</phrase></code> to point to its own data member.
      </para>
      <para>
        <code><phrase role="identifier">async_result</phrase><phrase role="special">&lt;</phrase><phrase
        role="identifier">yield_handler</phrase><phrase role="special">&lt;</phrase><phrase
        role="identifier">T</phrase><phrase role="special">&gt;&gt;</phrase></code>
        overrides <code><phrase role="identifier">get</phrase><phrase role="special">()</phrase></code>.
        The override calls <code><phrase role="identifier">async_result_base</phrase><phrase
        role="special">::</phrase><phrase role="identifier">get</phrase><phrase role="special">()</phrase></code>,
        so the calling fiber suspends as described above.
      </para>
      <para>
        <code><phrase role="identifier">yield_handler</phrase><phrase role="special">&lt;</phrase><phrase
        role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase
        role="keyword">operator</phrase><phrase role="special">()(</phrase><phrase
        role="identifier">error_code</phrase><phrase role="special">,</phrase> <phrase
        role="identifier">T</phrase><phrase role="special">)</phrase></code> stores
        its passed <code><phrase role="identifier">T</phrase></code> value into
        <code><phrase role="identifier">async_result</phrase><phrase role="special">&lt;</phrase><phrase
        role="identifier">yield_handler</phrase><phrase role="special">&lt;</phrase><phrase
        role="identifier">T</phrase><phrase role="special">&gt;&gt;::</phrase><phrase
        role="identifier">value_</phrase></code>.
      </para>
      <para>
        Then it passes control to <code><phrase role="identifier">yield_handler_base</phrase><phrase
        role="special">::</phrase><phrase role="keyword">operator</phrase><phrase
        role="special">()(</phrase><phrase role="identifier">error_code</phrase><phrase
        role="special">)</phrase></code> to deal with waking the original fiber as
        described above.
      </para>
      <para>
        When <code><phrase role="identifier">async_result</phrase><phrase role="special">&lt;</phrase><phrase
        role="identifier">yield_handler</phrase><phrase role="special">&lt;</phrase><phrase
        role="identifier">T</phrase><phrase role="special">&gt;&gt;::</phrase><phrase
        role="identifier">get</phrase><phrase role="special">()</phrase></code> resumes,
        it returns the stored <code><phrase role="identifier">value_</phrase></code>
        to <code><phrase role="identifier">async_something</phrase><phrase role="special">()</phrase></code>
        and ultimately to <code><phrase role="identifier">async_something</phrase><phrase
        role="special">()</phrase></code>&#8217;s caller.
      </para>
      <para>
        The case of a callback signature <code><phrase role="keyword">void</phrase><phrase
        role="special">(</phrase><phrase role="identifier">T</phrase><phrase role="special">)</phrase></code>
        is handled by having <code><phrase role="identifier">yield_handler</phrase><phrase
        role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase
        role="keyword">operator</phrase><phrase role="special">()(</phrase><phrase
        role="identifier">T</phrase><phrase role="special">)</phrase></code> engage
        the <code><phrase role="keyword">void</phrase><phrase role="special">(</phrase><phrase
        role="identifier">error_code</phrase><phrase role="special">,</phrase> <phrase
        role="identifier">T</phrase><phrase role="special">)</phrase></code> machinery,
        passing a <quote>success</quote> <code><phrase role="identifier">error_code</phrase></code>.
      </para>
      <para>
        The source code above is found in <ulink url="../../examples/asio/yield.hpp">yield.hpp</ulink>
        and <ulink url="../../examples/asio/detail/yield.hpp">detail/yield.hpp</ulink>.
      </para>
    </section>
  </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 <quote>do something</quote> 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 <quote>do something</quote> 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> <quote>front ends</quote> 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="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="keyword">this</phrase><phrase role="special">](){</phrase> <phrase role="keyword">return</phrase> <phrase role="identifier">ready</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_buffered_channel"><code>buffered_channel&lt;&gt;</code></link>.
          We'll only need to enqueue the first value, so we'll <link linkend="buffered_channel_close"><code>buffered_channel::close()</code></link> it
          once we've retrieved that value. 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">buffered_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="keyword">auto</phrase> <phrase role="identifier">chanp</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">64</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">chanp</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">chanp</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">chanp</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">buffered_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">chan</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">chan</phrase><phrase role="special">,</phrase> <phrase role="identifier">function</phrase><phrase role="special">](){</phrase>
                              <phrase role="comment">// Ignore channel_op_status returned by push():</phrase>
                              <phrase role="comment">// might be closed; we simply don't care.</phrase>
                              <phrase role="identifier">chan</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_buffered_channel"><code>buffered_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">buffered_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="keyword">auto</phrase> <phrase role="identifier">chanp</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">64</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">chanp</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">chanp</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">chanp</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="buffered_channel_push"><code>buffered_channel::push()</code></link> on the queue?
        </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">queue</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 queue 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 queue, 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 queue! 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 queue.
        </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">CHANP</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">CHANP</phrase> <phrase role="identifier">chan</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="comment">// Use std::bind() here for C++11 compatibility. C++11 lambda capture</phrase>
        <phrase role="comment">// can't move a move-only Fn type, but bind() can. Let bind() move the</phrase>
        <phrase role="comment">// channel pointer and the function into the bound object, passing</phrase>
        <phrase role="comment">// references into the lambda.</phrase>
        <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">bind</phrase><phrase role="special">(</phrase>
            <phrase role="special">[](</phrase> <phrase role="identifier">CHANP</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">chan</phrase><phrase role="special">,</phrase>
                <phrase role="keyword">typename</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">decay</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Fn</phrase> <phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">function</phrase><phrase role="special">)</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</phrase>
                <phrase role="comment">// channel_op_status returned by push(): might be closed; we</phrase>
                <phrase role="comment">// simply don't care.</phrase>
                <phrase role="identifier">chan</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">chan</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="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 <quote>when_any</quote> 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">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>, using <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 queue, 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="buffered_channel_pop"><code>buffered_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 <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 queue.
        </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="keyword">typename</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">decay</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Fn</phrase> <phrase role="special">&gt;::</phrase><phrase role="identifier">type</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">buffered_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="keyword">auto</phrase> <phrase role="identifier">chanp</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">64</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">chanp</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">chanp</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">chanp</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 queue'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 buffered_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">buffered_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="keyword">auto</phrase> <phrase role="identifier">chanp</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">64</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">chanp</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">chanp</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">chanp</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 id="fiber.when_any.when_any.when_any__a_dubious_alternative">
        <title><link linkend="fiber.when_any.when_any.when_any__a_dubious_alternative">when_any,
        a dubious alternative</link></title>
        <para>
          Certain topics in C++ can arouse strong passions, and exceptions are no
          exception. We cannot resist mentioning &mdash; for purely informational purposes
          &mdash; that when you need only the <emphasis>first</emphasis> result from some
          number of concurrently-running fibers, it would be possible to pass a
          <literal>shared_ptr&lt;<link linkend="class_promise"><code>promise&lt;&gt;</code></link>&gt;</literal> to the
          participating fibers, then cause the initiating fiber to call <link linkend="future_get"><code>future::get()</code></link> on
          its <link linkend="class_future"><code>future&lt;&gt;</code></link>. The first fiber to call <link linkend="promise_set_value"><code>promise::set_value()</code></link> on
          that shared <code><phrase role="identifier">promise</phrase></code> will
          succeed; subsequent <code><phrase role="identifier">set_value</phrase><phrase
          role="special">()</phrase></code> calls on the same <code><phrase role="identifier">promise</phrase></code>
          instance will throw <code><phrase role="identifier">future_error</phrase></code>.
        </para>
        <para>
          Use this information at your own discretion. Beware the dark side.
        </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="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">bind</phrase><phrase role="special">(</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="special">&amp;</phrase> <phrase role="identifier">barrier</phrase><phrase role="special">,</phrase>
                    <phrase role="keyword">typename</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">decay</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Fn</phrase> <phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">function</phrase><phrase role="special">)</phrase> <phrase role="keyword">mutable</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">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">Fn</phrase> <phrase role="special">&gt;(</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="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
          queue&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">buffered_channel</phrase><phrase
          role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase
          role="special">&gt;&gt;</phrase></code>.
        </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">buffered_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">chan</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">chan</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="buffered_channel_close"><code>buffered_channel::close()</code></link> the
          queue 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="buffered_channel_push"><code>buffered_channel::push()</code></link> a
          value.
        </para>
        <para>
          <anchor id="wait_nqueue"/>We can address that problem with a counting façade
          for the <code><phrase role="identifier">queue</phrase><phrase role="special">&lt;&gt;</phrase></code>.
          In fact, our façade need only support the producer end of the queue.
        </para>
        <para>
          [wait_nqueue]
        </para>
        <para>
          <anchor id="wait_all_values_source"/>Armed with <code><phrase role="identifier">nqueue</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">queue</phrase><phrase role="special">&lt;</phrase><phrase
          role="identifier">T</phrase><phrase role="special">&gt;</phrase></code>
          with an <code><phrase role="identifier">nqueue</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 queue
          and returning it, we simply return the <code><phrase role="identifier">shared_ptr</phrase><phrase
          role="special">&lt;</phrase><phrase role="identifier">queue</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;buffered_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">buffered_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">buffered_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">chanp</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">64</phrase><phrase role="special">)</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">chanp</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">chanp</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">buffered_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">chan</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">chan</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">nqueue</phrase><phrase
          role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase
          role="special">&gt;</phrase></code> rather than <code><phrase role="identifier">queue</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">chan</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">chan</phrase><phrase role="special">,</phrase> <phrase role="identifier">function</phrase><phrase role="special">](){</phrase>
                              <phrase role="identifier">chan</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">buffered_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">chan</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">chan</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 queue 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. Notice, however, that we
          can reuse <link linkend="wait_first_outcome_impl"><code><phrase role="identifier">wait_first_outcome_impl</phrase><phrase
          role="special">()</phrase></code></link>, passing the <code><phrase role="identifier">nqueue</phrase><phrase
          role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase
          role="special">&gt;</phrase></code> rather than <code><phrase role="identifier">queue</phrase><phrase
          role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase
          role="special">&gt;</phrase></code>.
        </para>
        <para>
<programlisting><phrase role="comment">// Return a shared_ptr&lt;buffered_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">buffered_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">buffered_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">chanp</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">64</phrase><phrase role="special">)</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">chanp</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_first_outcome_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">chanp</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">buffered_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">chan</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">chan</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>
      </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">buffered_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">chan</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">chan</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">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="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>
    <section id="fiber.integration.overview">
      <title><link linkend="fiber.integration.overview">Overview</link></title>
      <para>
        As always with cooperative concurrency, it is important not to let any one
        fiber monopolize the processor too long: that could <quote>starve</quote>
        other ready fibers. This section discusses a couple of solutions.
      </para>
    </section>
    <section id="fiber.integration.event_driven_program">
      <title><link linkend="fiber.integration.event_driven_program">Event-Driven
      Program</link></title>
      <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&#8217;s main thread because certain
        of their actions will affect its user interface, and the application&#8217;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&#8217;s main loop <emphasis>itself</emphasis>
        doesn&#8217;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&#8217;s main loop with <emphasis role="bold">Boost.Fiber</emphasis>&#8217;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&#8217;s main
        loop. When these fibers have had a turn, control passes to the thread&#8217;s main
        fiber, which returns from <code><phrase role="identifier">yield</phrase><phrase
        role="special">()</phrase></code> and resumes the application&#8217;s main loop.
      </para>
    </section>
    <section id="fiber.integration.embedded_main_loop">
      <title><anchor id="embedded_main_loop"/><link linkend="fiber.integration.embedded_main_loop">Embedded
      Main Loop</link></title>
      <para>
        More challenging is when the application&#8217;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>
        In general, the trick is to arrange to pass control to <link linkend="this_fiber_yield"><code>this_fiber::yield()</code></link> frequently.
        You could use an <ulink url="http://www.boost.org/doc/libs/release/doc/html/boost_asio/reference/high_resolution_timer.html">Asio
        timer</ulink> for that purpose. You could instantiate the timer, arranging
        to call a handler function when the timer expires. The handler function could
        call <code><phrase role="identifier">yield</phrase><phrase role="special">()</phrase></code>,
        then reset the timer and arrange to wake up again on its next expiration.
      </para>
      <para>
        Since, in this thought experiment, 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 calls <link linkend="algorithm_suspend_until"><code>algorithm::suspend_until()</code></link>.
      </para>
      <para>
        Using <ulink url="http://www.boost.org/doc/libs/release/doc/html/boost_asio/reference/io_service/post.html"><code><phrase
        role="identifier">io_service</phrase><phrase role="special">::</phrase><phrase
        role="identifier">post</phrase><phrase role="special">()</phrase></code></ulink>
        instead of setting a timer for some nonzero 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. Using a timer allows tuning the responsiveness
        of this thread relative to others.
      </para>
    </section>
    <section id="fiber.integration.deeper_dive_into___boost_asio__">
      <title><link linkend="fiber.integration.deeper_dive_into___boost_asio__">Deeper
      Dive into <ulink url="http://www.boost.org/doc/libs/release/libs/asio/index.html">Boost.Asio</ulink></link></title>
      <para>
        By now the alert reader is thinking: but surely, with Asio in particular,
        we ought to be able to do much better than periodic polling pings!
      </para>
      <para>
        This turns out to be surprisingly tricky. We present a possible approach
        in <ulink url="../../examples/asio/round_robin.hpp"><code><phrase role="identifier">examples</phrase><phrase
        role="special">/</phrase><phrase role="identifier">asio</phrase><phrase role="special">/</phrase><phrase
        role="identifier">round_robin</phrase><phrase role="special">.</phrase><phrase
        role="identifier">hpp</phrase></code></ulink>.
      </para>
      <para>
        One consequence of using <ulink url="http://www.boost.org/doc/libs/release/libs/asio/index.html">Boost.Asio</ulink>
        is that you must always let Asio suspend the running thread. Since Asio is
        aware of pending I/O requests, it can arrange to suspend the thread in such
        a way that the OS will wake it on I/O completion. No one else has sufficient
        knowledge.
      </para>
      <para>
        So the fiber scheduler must depend on Asio for suspension and resumption.
        It requires Asio handler calls to wake it.
      </para>
      <para>
        One dismaying implication is that we cannot support multiple threads calling
        <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>
        on the same <code><phrase role="identifier">io_service</phrase></code> instance.
        The reason is that Asio provides no way to constrain a particular handler
        to be called only on a specified thread. A fiber scheduler instance is locked
        to a particular thread: that instance cannot manage any other thread&#8217;s fibers.
        Yet if we allow multiple threads to call <code><phrase role="identifier">io_service</phrase><phrase
        role="special">::</phrase><phrase role="identifier">run</phrase><phrase role="special">()</phrase></code>
        on the same <code><phrase role="identifier">io_service</phrase></code> instance,
        a fiber scheduler which needs to sleep can have no guarantee that it will
        reawaken in a timely manner. It can set an Asio timer, as described above
        &mdash; but that timer&#8217;s handler may well execute on a different thread!
      </para>
      <para>
        Another implication is that since an Asio-aware fiber scheduler (not to mention
        <link linkend="callbacks_asio"><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></link>)
        depends on handler calls from the <code><phrase role="identifier">io_service</phrase></code>,
        it is the application&#8217;s responsibility to ensure that <ulink url="http://www.boost.org/doc/libs/release/doc/html/boost_asio/reference/io_service/stop.html"><code><phrase
        role="identifier">io_service</phrase><phrase role="special">::</phrase><phrase
        role="identifier">stop</phrase><phrase role="special">()</phrase></code></ulink>
        is not called until every fiber has terminated.
      </para>
      <para>
        It is easier to reason about the behavior of the presented <code><phrase
        role="identifier">asio</phrase><phrase role="special">::</phrase><phrase
        role="identifier">round_robin</phrase></code> scheduler if we require that
        after initial setup, the thread&#8217;s main fiber is the fiber that calls <code><phrase
        role="identifier">io_service</phrase><phrase role="special">::</phrase><phrase
        role="identifier">run</phrase><phrase role="special">()</phrase></code>,
        so let&#8217;s impose that requirement.
      </para>
      <para>
        Naturally, the first thing we must do on each thread using a custom fiber
        scheduler is call <link linkend="use_scheduling_algorithm"><code>use_scheduling_algorithm()</code></link>. However,
        since <code><phrase role="identifier">asio</phrase><phrase role="special">::</phrase><phrase
        role="identifier">round_robin</phrase></code> requires an <code><phrase role="identifier">io_service</phrase></code>
        instance, we must first declare that.
      </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">asio</phrase><phrase role="special">::</phrase><phrase role="identifier">io_service</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">io_svc</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">asio</phrase><phrase role="special">::</phrase><phrase role="identifier">io_service</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">use_scheduling_algorithm</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">round_robin</phrase> <phrase role="special">&gt;(</phrase> <phrase role="identifier">io_svc</phrase><phrase role="special">);</phrase>
</programlisting>
      </para>
      <para>
        <code><phrase role="identifier">use_scheduling_algorithm</phrase><phrase
        role="special">()</phrase></code> instantiates <code><phrase role="identifier">asio</phrase><phrase
        role="special">::</phrase><phrase role="identifier">round_robin</phrase></code>,
        which naturally calls its constructor:
      </para>
      <para>
<programlisting><phrase role="identifier">round_robin</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">asio</phrase><phrase role="special">::</phrase><phrase role="identifier">io_service</phrase> <phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">io_svc</phrase><phrase role="special">)</phrase> <phrase role="special">:</phrase>
    <phrase role="identifier">io_svc_</phrase><phrase role="special">(</phrase> <phrase role="identifier">io_svc</phrase><phrase role="special">),</phrase>
    <phrase role="identifier">suspend_timer_</phrase><phrase role="special">(</phrase> <phrase role="special">*</phrase> <phrase role="identifier">io_svc_</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
    <phrase role="comment">// We use add_service() very deliberately. This will throw</phrase>
    <phrase role="comment">// service_already_exists if you pass the same io_service instance to</phrase>
    <phrase role="comment">// more than one round_robin instance.</phrase>
    <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">asio</phrase><phrase role="special">::</phrase><phrase role="identifier">add_service</phrase><phrase role="special">(</phrase> <phrase role="special">*</phrase> <phrase role="identifier">io_svc_</phrase><phrase role="special">,</phrase> <phrase role="keyword">new</phrase> <phrase role="identifier">service</phrase><phrase role="special">(</phrase> <phrase role="special">*</phrase> <phrase role="identifier">io_svc_</phrase><phrase role="special">)</phrase> <phrase role="special">);</phrase>
    <phrase role="identifier">io_svc_</phrase><phrase role="special">-&gt;</phrase><phrase role="identifier">post</phrase><phrase role="special">([</phrase><phrase role="keyword">this</phrase><phrase role="special">]()</phrase> <phrase role="keyword">mutable</phrase> <phrase role="special">{</phrase>
</programlisting>
      </para>
      <para>
        <code><phrase role="identifier">asio</phrase><phrase role="special">::</phrase><phrase
        role="identifier">round_robin</phrase></code> binds the passed <code><phrase
        role="identifier">io_service</phrase></code> pointer and initializes a <ulink
        url="http://www.boost.org/doc/libs/release/doc/html/boost_asio/reference/steady_timer.html"><code><phrase
        role="identifier">boost</phrase><phrase role="special">::</phrase><phrase
        role="identifier">asio</phrase><phrase role="special">::</phrase><phrase
        role="identifier">steady_timer</phrase></code></ulink>:
      </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">asio</phrase><phrase role="special">::</phrase><phrase role="identifier">io_service</phrase> <phrase role="special">&gt;</phrase>      <phrase role="identifier">io_svc_</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">steady_timer</phrase>                       <phrase role="identifier">suspend_timer_</phrase><phrase role="special">;</phrase>
</programlisting>
      </para>
      <para>
        Then it calls <ulink url="http://www.boost.org/doc/libs/release/doc/html/boost_asio/reference/add_service.html"><code><phrase
        role="identifier">boost</phrase><phrase role="special">::</phrase><phrase
        role="identifier">asio</phrase><phrase role="special">::</phrase><phrase
        role="identifier">add_service</phrase><phrase role="special">()</phrase></code></ulink>
        with a nested <code><phrase role="identifier">service</phrase></code> struct:
      </para>
      <para>
<programlisting><phrase role="keyword">struct</phrase> <phrase role="identifier">service</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">asio</phrase><phrase role="special">::</phrase><phrase role="identifier">io_service</phrase><phrase role="special">::</phrase><phrase role="identifier">service</phrase> <phrase role="special">{</phrase>
    <phrase role="keyword">static</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">asio</phrase><phrase role="special">::</phrase><phrase role="identifier">io_service</phrase><phrase role="special">::</phrase><phrase role="identifier">id</phrase>                  <phrase role="identifier">id</phrase><phrase role="special">;</phrase>

    <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">unique_ptr</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">asio</phrase><phrase role="special">::</phrase><phrase role="identifier">io_service</phrase><phrase role="special">::</phrase><phrase role="identifier">work</phrase> <phrase role="special">&gt;</phrase>    <phrase role="identifier">work_</phrase><phrase role="special">;</phrase>

    <phrase role="identifier">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_svc</phrase><phrase role="special">)</phrase> <phrase role="special">:</phrase>
        <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">asio</phrase><phrase role="special">::</phrase><phrase role="identifier">io_service</phrase><phrase role="special">::</phrase><phrase role="identifier">service</phrase><phrase role="special">(</phrase> <phrase role="identifier">io_svc</phrase><phrase role="special">),</phrase>
        <phrase role="identifier">work_</phrase><phrase role="special">{</phrase> <phrase role="keyword">new</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">asio</phrase><phrase role="special">::</phrase><phrase role="identifier">io_service</phrase><phrase role="special">::</phrase><phrase role="identifier">work</phrase><phrase role="special">(</phrase> <phrase role="identifier">io_svc</phrase><phrase role="special">)</phrase> <phrase role="special">}</phrase> <phrase role="special">{</phrase>
    <phrase role="special">}</phrase>

    <phrase role="keyword">virtual</phrase> <phrase role="special">~</phrase><phrase role="identifier">service</phrase><phrase role="special">()</phrase> <phrase role="special">{}</phrase>

    <phrase role="identifier">service</phrase><phrase role="special">(</phrase> <phrase role="identifier">service</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">service</phrase> <phrase role="special">&amp;</phrase> <phrase role="keyword">operator</phrase><phrase role="special">=(</phrase> <phrase role="identifier">service</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">shutdown_service</phrase><phrase role="special">()</phrase> <phrase role="identifier">override</phrase> <phrase role="identifier">final</phrase> <phrase role="special">{</phrase>
        <phrase role="identifier">work_</phrase><phrase role="special">.</phrase><phrase role="identifier">reset</phrase><phrase role="special">();</phrase>
    <phrase role="special">}</phrase>
<phrase role="special">};</phrase>
</programlisting>
      </para>
      <para>
        ... [asio_rr_service_bottom]
      </para>
      <para>
        The <code><phrase role="identifier">service</phrase></code> struct has a
        couple of roles.
      </para>
      <para>
        Its foremost role is to manage a <literal>std::unique_ptr&lt;<ulink url="http://www.boost.org/doc/libs/release/doc/html/boost_asio/reference/io_service__work.html"><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><phrase role="special">::</phrase><phrase
        role="identifier">work</phrase></code></ulink>&gt;</literal>. We want the
        <code><phrase role="identifier">io_service</phrase></code> instance to continue
        its main loop even when there is no pending Asio I/O.
      </para>
      <para>
        But when <ulink url="http://www.boost.org/doc/libs/release/doc/html/boost_asio/reference/io_service__service/shutdown_service.html"><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><phrase role="special">::</phrase><phrase
        role="identifier">service</phrase><phrase role="special">::</phrase><phrase
        role="identifier">shutdown_service</phrase><phrase role="special">()</phrase></code></ulink>
        is called, we discard the <code><phrase role="identifier">io_service</phrase><phrase
        role="special">::</phrase><phrase role="identifier">work</phrase></code>
        instance so the <code><phrase role="identifier">io_service</phrase></code>
        can shut down properly.
      </para>
      <para>
        Its other purpose is to <ulink url="http://www.boost.org/doc/libs/release/doc/html/boost_asio/reference/io_service/post.html"><code><phrase
        role="identifier">post</phrase><phrase role="special">()</phrase></code></ulink>
        a lambda (not yet shown). Let&#8217;s walk further through the example program before
        coming back to explain that lambda.
      </para>
      <para>
        The <code><phrase role="identifier">service</phrase></code> constructor returns
        to <code><phrase role="identifier">asio</phrase><phrase role="special">::</phrase><phrase
        role="identifier">round_robin</phrase></code>&#8217;s constructor, which returns
        to <code><phrase role="identifier">use_scheduling_algorithm</phrase><phrase
        role="special">()</phrase></code>, which returns to the application code.
      </para>
      <para>
        Once it has called <code><phrase role="identifier">use_scheduling_algorithm</phrase><phrase
        role="special">()</phrase></code>, the application may now launch some number
        of fibers:
      </para>
      <para>
<programlisting><phrase role="comment">// server</phrase>
<phrase role="identifier">tcp</phrase><phrase role="special">::</phrase><phrase role="identifier">acceptor</phrase> <phrase role="identifier">a</phrase><phrase role="special">(</phrase> <phrase role="special">*</phrase> <phrase role="identifier">io_svc</phrase><phrase role="special">,</phrase> <phrase role="identifier">tcp</phrase><phrase role="special">::</phrase><phrase role="identifier">endpoint</phrase><phrase role="special">(</phrase> <phrase role="identifier">tcp</phrase><phrase role="special">::</phrase><phrase role="identifier">v4</phrase><phrase role="special">(),</phrase> <phrase role="number">9999</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="identifier">server</phrase><phrase role="special">,</phrase> <phrase role="identifier">io_svc</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">a</phrase><phrase role="special">)</phrase> <phrase role="special">).</phrase><phrase role="identifier">detach</phrase><phrase role="special">();</phrase>
<phrase role="comment">// client</phrase>
<phrase role="keyword">const</phrase> <phrase role="keyword">unsigned</phrase> <phrase role="identifier">iterations</phrase> <phrase role="special">=</phrase> <phrase role="number">2</phrase><phrase role="special">;</phrase>
<phrase role="keyword">const</phrase> <phrase role="keyword">unsigned</phrase> <phrase role="identifier">clients</phrase> <phrase role="special">=</phrase> <phrase role="number">3</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">barrier</phrase> <phrase role="identifier">b</phrase><phrase role="special">(</phrase> <phrase role="identifier">clients</phrase><phrase role="special">);</phrase>
<phrase role="keyword">for</phrase> <phrase role="special">(</phrase> <phrase role="keyword">unsigned</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">clients</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">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">client</phrase><phrase role="special">,</phrase> <phrase role="identifier">io_svc</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">a</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">b</phrase><phrase role="special">),</phrase> <phrase role="identifier">iterations</phrase><phrase role="special">).</phrase><phrase role="identifier">detach</phrase><phrase role="special">();</phrase>
<phrase role="special">}</phrase>
</programlisting>
      </para>
      <para>
        Since we don&#8217;t specify a <link linkend="class_launch"><code>launch</code></link>, these fibers are ready to run,
        but have not yet been entered.
      </para>
      <para>
        Having set everything up, the application calls <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>:
      </para>
      <para>
<programlisting><phrase role="identifier">io_svc</phrase><phrase role="special">-&gt;</phrase><phrase role="identifier">run</phrase><phrase role="special">();</phrase>
</programlisting>
      </para>
      <para>
        Now what?
      </para>
      <para>
        Because this <code><phrase role="identifier">io_service</phrase></code> instance
        owns an <code><phrase role="identifier">io_service</phrase><phrase role="special">::</phrase><phrase
        role="identifier">work</phrase></code> instance, <code><phrase role="identifier">run</phrase><phrase
        role="special">()</phrase></code> does not immediately return. But &mdash; none of
        the fibers that will perform actual work has even been entered yet!
      </para>
      <para>
        Without that initial <code><phrase role="identifier">post</phrase><phrase
        role="special">()</phrase></code> call in <code><phrase role="identifier">service</phrase></code>&#8217;s
        constructor, <emphasis>nothing</emphasis> would happen. The application would
        hang right here.
      </para>
      <para>
        So, what should the <code><phrase role="identifier">post</phrase><phrase
        role="special">()</phrase></code> handler execute? Simply <link linkend="this_fiber_yield"><code>this_fiber::yield()</code></link>?
      </para>
      <para>
        That would be a promising start. But we have no guarantee that any of the
        other fibers will initiate any Asio operations to keep the ball rolling.
        For all we know, every other fiber could reach a similar <code><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></code> call first. Control would return to the
        <code><phrase role="identifier">post</phrase><phrase role="special">()</phrase></code>
        handler, which would return to Asio, and... the application would hang.
      </para>
      <para>
        The <code><phrase role="identifier">post</phrase><phrase role="special">()</phrase></code>
        handler could <code><phrase role="identifier">post</phrase><phrase role="special">()</phrase></code>
        itself again. But as discussed in <link linkend="embedded_main_loop">the
        previous section</link>, once there are actual I/O operations in flight &mdash; once
        we reach a state in which no fiber is ready &mdash;
that would cause the thread to
        spin.
      </para>
      <para>
        We could, of course, set an Asio timer &mdash; again as <link linkend="embedded_main_loop">previously
        discussed</link>. But in this <quote>deeper dive,</quote> we&#8217;re trying to
        do a little better.
      </para>
      <para>
        The key to doing better is that since we&#8217;re in a fiber, we can run an actual
        loop &mdash; not just a chain of callbacks. We can wait for <quote>something to happen</quote>
        by calling <ulink url="http://www.boost.org/doc/libs/release/doc/html/boost_asio/reference/io_service/run_one.html"><code><phrase
        role="identifier">io_service</phrase><phrase role="special">::</phrase><phrase
        role="identifier">run_one</phrase><phrase role="special">()</phrase></code></ulink>
        &mdash; or we can execute already-queued Asio handlers by calling <ulink url="http://www.boost.org/doc/libs/release/doc/html/boost_asio/reference/io_service/poll.html"><code><phrase
        role="identifier">io_service</phrase><phrase role="special">::</phrase><phrase
        role="identifier">poll</phrase><phrase role="special">()</phrase></code></ulink>.
      </para>
      <para>
        Here&#8217;s the body of the lambda passed to the <code><phrase role="identifier">post</phrase><phrase
        role="special">()</phrase></code> call.
      </para>
      <para>
<programlisting> <phrase role="keyword">while</phrase> <phrase role="special">(</phrase> <phrase role="special">!</phrase> <phrase role="identifier">io_svc_</phrase><phrase role="special">-&gt;</phrase><phrase role="identifier">stopped</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">has_ready_fibers</phrase><phrase role="special">()</phrase> <phrase role="special">)</phrase> <phrase role="special">{</phrase>
         <phrase role="comment">// run all pending handlers in round_robin</phrase>
         <phrase role="keyword">while</phrase> <phrase role="special">(</phrase> <phrase role="identifier">io_svc_</phrase><phrase role="special">-&gt;</phrase><phrase role="identifier">poll</phrase><phrase role="special">()</phrase> <phrase role="special">);</phrase>
         <phrase role="comment">// block this fiber till all pending (ready) fibers are processed</phrase>
         <phrase role="comment">// == round_robin::suspend_until() has been called</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">cnd_</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="keyword">else</phrase> <phrase role="special">{</phrase>
         <phrase role="comment">// run one handler inside io_service</phrase>
         <phrase role="comment">// if no handler available, block this thread</phrase>
         <phrase role="keyword">if</phrase> <phrase role="special">(</phrase> <phrase role="special">!</phrase> <phrase role="identifier">io_svc_</phrase><phrase role="special">-&gt;</phrase><phrase role="identifier">run_one</phrase><phrase role="special">()</phrase> <phrase role="special">)</phrase> <phrase role="special">{</phrase>
             <phrase role="keyword">break</phrase><phrase role="special">;</phrase>
         <phrase role="special">}</phrase>
     <phrase role="special">}</phrase>
<phrase role="special">}</phrase>
</programlisting>
      </para>
      <para>
        We want this loop to exit once the <code><phrase role="identifier">io_service</phrase></code>
        instance has been <ulink url="http://www.boost.org/doc/libs/release/doc/html/boost_asio/reference/io_service/stopped.html"><code><phrase
        role="identifier">stopped</phrase><phrase role="special">()</phrase></code></ulink>.
      </para>
      <para>
        As long as there are ready fibers, we interleave running ready Asio handlers
        with running ready fibers.
      </para>
      <para>
        If there are no ready fibers, we wait by calling <code><phrase role="identifier">run_one</phrase><phrase
        role="special">()</phrase></code>. Once any Asio handler has been called
        &mdash; no matter which &mdash; <code><phrase role="identifier">run_one</phrase><phrase role="special">()</phrase></code>
        returns. That handler may have transitioned some fiber to ready state, so
        we loop back to check again.
      </para>
      <para>
        (We won&#8217;t describe <code><phrase role="identifier">awakened</phrase><phrase
        role="special">()</phrase></code>, <code><phrase role="identifier">pick_next</phrase><phrase
        role="special">()</phrase></code> or <code><phrase role="identifier">has_ready_fibers</phrase><phrase
        role="special">()</phrase></code>, as these are just like <link linkend="round_robin_awakened"><code>round_robin::awakened()</code></link>,
        <link linkend="round_robin_pick_next"><code>round_robin::pick_next()</code></link> and <link linkend="round_robin_has_ready_fibers"><code>round_robin::has_ready_fibers()</code></link>.)
      </para>
      <para>
        That leaves <code><phrase role="identifier">suspend_until</phrase><phrase
        role="special">()</phrase></code> and <code><phrase role="identifier">notify</phrase><phrase
        role="special">()</phrase></code>.
      </para>
      <para>
        Doubtless you have been asking yourself: why are we calling <code><phrase
        role="identifier">io_service</phrase><phrase role="special">::</phrase><phrase
        role="identifier">run_one</phrase><phrase role="special">()</phrase></code>
        in the lambda loop? Why not call it in <code><phrase role="identifier">suspend_until</phrase><phrase
        role="special">()</phrase></code>, whose very API was designed for just such
        a purpose?
      </para>
      <para>
        Under normal circumstances, when the fiber manager finds no ready fibers,
        it calls <link linkend="algorithm_suspend_until"><code>algorithm::suspend_until()</code></link>. Why test <code><phrase
        role="identifier">has_ready_fibers</phrase><phrase role="special">()</phrase></code>
        in the lambda loop? Why not leverage the normal mechanism?
      </para>
      <para>
        The answer is: it matters who&#8217;s asking.
      </para>
      <para>
        Consider the lambda loop shown above. The only <emphasis role="bold">Boost.Fiber</emphasis>
        APIs it engages are <code><phrase role="identifier">has_ready_fibers</phrase><phrase
        role="special">()</phrase></code> and <link linkend="this_fiber_yield"><code>this_fiber::yield()</code></link>.
        <code><phrase role="identifier">yield</phrase><phrase role="special">()</phrase></code>
        does not <emphasis>block</emphasis> the calling fiber: the calling fiber
        does not become unready. It is immediately passed back to <link linkend="algorithm_awakened"><code>algorithm::awakened()</code></link>,
        to be resumed in its turn when all other ready fibers have had a chance to
        run. In other words: during a <code><phrase role="identifier">yield</phrase><phrase
        role="special">()</phrase></code> call, <emphasis>there is always at least
        one ready fiber.</emphasis>
      </para>
      <para>
        As long as this lambda loop is still running, the fiber manager does not
        call <code><phrase role="identifier">suspend_until</phrase><phrase role="special">()</phrase></code>
        because it always has a fiber ready to run.
      </para>
      <para>
        However, the lambda loop <emphasis>itself</emphasis> can detect the case
        when no <emphasis>other</emphasis> fibers are ready to run: the running fiber
        is not <emphasis>ready</emphasis> but <emphasis>running.</emphasis>
      </para>
      <para>
        That said, <code><phrase role="identifier">suspend_until</phrase><phrase
        role="special">()</phrase></code> and <code><phrase role="identifier">notify</phrase><phrase
        role="special">()</phrase></code> are in fact called during orderly shutdown
        processing, so let&#8217;s try a plausible implementation.
      </para>
      <para>
<programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">suspend_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">steady_clock</phrase><phrase role="special">::</phrase><phrase role="identifier">time_point</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">abs_time</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase> <phrase role="special">{</phrase>
    <phrase role="comment">// Set a timer so at least one handler will eventually fire, causing</phrase>
    <phrase role="comment">// run_one() to eventually return.</phrase>
    <phrase role="keyword">if</phrase> <phrase role="special">(</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">steady_clock</phrase><phrase role="special">::</phrase><phrase role="identifier">time_point</phrase><phrase role="special">::</phrase><phrase role="identifier">max</phrase><phrase role="special">)()</phrase> <phrase role="special">!=</phrase> <phrase role="identifier">abs_time</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
        <phrase role="comment">// Each expires_at(time_point) call cancels any previous pending</phrase>
        <phrase role="comment">// call. We could inadvertently spin like this:</phrase>
        <phrase role="comment">// dispatcher calls suspend_until() with earliest wake time</phrase>
        <phrase role="comment">// suspend_until() sets suspend_timer_</phrase>
        <phrase role="comment">// lambda loop calls run_one()</phrase>
        <phrase role="comment">// some other asio handler runs before timer expires</phrase>
        <phrase role="comment">// run_one() returns to lambda loop</phrase>
        <phrase role="comment">// lambda loop yields to dispatcher</phrase>
        <phrase role="comment">// dispatcher finds no ready fibers</phrase>
        <phrase role="comment">// dispatcher calls suspend_until() with SAME wake time</phrase>
        <phrase role="comment">// suspend_until() sets suspend_timer_ to same time, canceling</phrase>
        <phrase role="comment">// previous async_wait()</phrase>
        <phrase role="comment">// lambda loop calls run_one()</phrase>
        <phrase role="comment">// asio calls suspend_timer_ handler with operation_aborted</phrase>
        <phrase role="comment">// run_one() returns to lambda loop... etc. etc.</phrase>
        <phrase role="comment">// So only actually set the timer when we're passed a DIFFERENT</phrase>
        <phrase role="comment">// abs_time value.</phrase>
        <phrase role="identifier">suspend_timer_</phrase><phrase role="special">.</phrase><phrase role="identifier">expires_at</phrase><phrase role="special">(</phrase> <phrase role="identifier">abs_time</phrase><phrase role="special">);</phrase>
        <phrase role="identifier">suspend_timer_</phrase><phrase role="special">.</phrase><phrase role="identifier">async_wait</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">this_fiber</phrase><phrase role="special">::</phrase><phrase role="identifier">yield</phrase><phrase role="special">();</phrase>
                                  <phrase role="special">});</phrase>
    <phrase role="special">}</phrase>
    <phrase role="identifier">cnd_</phrase><phrase role="special">.</phrase><phrase role="identifier">notify_one</phrase><phrase role="special">();</phrase>
<phrase role="special">}</phrase>
</programlisting>
      </para>
      <para>
        As you might expect, <code><phrase role="identifier">suspend_until</phrase><phrase
        role="special">()</phrase></code> sets an <ulink url="http://www.boost.org/doc/libs/release/doc/html/boost_asio/reference/steady_timer.html"><code><phrase
        role="identifier">asio</phrase><phrase role="special">::</phrase><phrase
        role="identifier">steady_timer</phrase></code></ulink> to <ulink url="http://www.boost.org/doc/libs/release/doc/html/boost_asio/reference/basic_waitable_timer/expires_at.html"><code><phrase
        role="identifier">expires_at</phrase><phrase role="special">()</phrase></code></ulink>
        the passed <ulink url="http://en.cppreference.com/w/cpp/chrono/steady_clock"><code><phrase
        role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase
        role="special">::</phrase><phrase role="identifier">steady_clock</phrase><phrase
        role="special">::</phrase><phrase role="identifier">time_point</phrase></code></ulink>.
        Usually.
      </para>
      <para>
        As indicated in comments, we avoid setting <code><phrase role="identifier">suspend_timer_</phrase></code>
        multiple times to the <emphasis>same</emphasis> <code><phrase role="identifier">time_point</phrase></code>
        value since every <code><phrase role="identifier">expires_at</phrase><phrase
        role="special">()</phrase></code> call cancels any previous <ulink url="http://www.boost.org/doc/libs/release/doc/html/boost_asio/reference/basic_waitable_timer/async_wait.html"><code><phrase
        role="identifier">async_wait</phrase><phrase role="special">()</phrase></code></ulink>
        call. There is a chance that we could spin. Reaching <code><phrase role="identifier">suspend_until</phrase><phrase
        role="special">()</phrase></code> means the fiber manager intends to yield
        the processor to Asio. Cancelling the previous <code><phrase role="identifier">async_wait</phrase><phrase
        role="special">()</phrase></code> call would fire its handler, causing <code><phrase
        role="identifier">run_one</phrase><phrase role="special">()</phrase></code>
        to return, potentially causing the fiber manager to call <code><phrase role="identifier">suspend_until</phrase><phrase
        role="special">()</phrase></code> again with the same <code><phrase role="identifier">time_point</phrase></code>
        value...
      </para>
      <para>
        Given that we suspend the thread by calling <code><phrase role="identifier">io_service</phrase><phrase
        role="special">::</phrase><phrase role="identifier">run_one</phrase><phrase
        role="special">()</phrase></code>, what&#8217;s important is that our <code><phrase
        role="identifier">async_wait</phrase><phrase role="special">()</phrase></code>
        call will cause a handler to run, which will cause <code><phrase role="identifier">run_one</phrase><phrase
        role="special">()</phrase></code> to return. It&#8217;s not so important specifically
        what that handler does.
      </para>
      <para>
<programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">notify</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase> <phrase role="special">{</phrase>
    <phrase role="comment">// Something has happened that should wake one or more fibers BEFORE</phrase>
    <phrase role="comment">// suspend_timer_ expires. Reset the timer to cause it to fire</phrase>
    <phrase role="comment">// immediately, causing the run_one() call to return. In theory we</phrase>
    <phrase role="comment">// could use cancel() because we don't care whether suspend_timer_'s</phrase>
    <phrase role="comment">// handler is called with operation_aborted or success. However --</phrase>
    <phrase role="comment">// cancel() doesn't change the expiration time, and we use</phrase>
    <phrase role="comment">// suspend_timer_'s expiration time to decide whether it's already</phrase>
    <phrase role="comment">// set. If suspend_until() set some specific wake time, then notify()</phrase>
    <phrase role="comment">// canceled it, then suspend_until() was called again with the same</phrase>
    <phrase role="comment">// wake time, it would match suspend_timer_'s expiration time and we'd</phrase>
    <phrase role="comment">// refrain from setting the timer. So instead of simply calling</phrase>
    <phrase role="comment">// cancel(), reset the timer, which cancels the pending sleep AND sets</phrase>
    <phrase role="comment">// a new expiration time. This will cause us to spin the loop twice --</phrase>
    <phrase role="comment">// once for the operation_aborted handler, once for timer expiration</phrase>
    <phrase role="comment">// -- but that shouldn't be a big problem.</phrase>
    <phrase role="identifier">suspend_timer_</phrase><phrase role="special">.</phrase><phrase role="identifier">async_wait</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">this_fiber</phrase><phrase role="special">::</phrase><phrase role="identifier">yield</phrase><phrase role="special">();</phrase>
                              <phrase role="special">});</phrase>
    <phrase role="identifier">suspend_timer_</phrase><phrase role="special">.</phrase><phrase role="identifier">expires_at</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">steady_clock</phrase><phrase role="special">::</phrase><phrase role="identifier">now</phrase><phrase role="special">()</phrase> <phrase role="special">);</phrase>
<phrase role="special">}</phrase>
</programlisting>
      </para>
      <para>
        Since an <code><phrase role="identifier">expires_at</phrase><phrase role="special">()</phrase></code>
        call cancels any previous <code><phrase role="identifier">async_wait</phrase><phrase
        role="special">()</phrase></code> call, we can make <code><phrase role="identifier">notify</phrase><phrase
        role="special">()</phrase></code> simply call <code><phrase role="identifier">steady_timer</phrase><phrase
        role="special">::</phrase><phrase role="identifier">expires_at</phrase><phrase
        role="special">()</phrase></code>. That should cause the <code><phrase role="identifier">io_service</phrase></code>
        to call the <code><phrase role="identifier">async_wait</phrase><phrase role="special">()</phrase></code>
        handler with <code><phrase role="identifier">operation_aborted</phrase></code>.
      </para>
      <para>
        The comments in <code><phrase role="identifier">notify</phrase><phrase role="special">()</phrase></code>
        explain why we call <code><phrase role="identifier">expires_at</phrase><phrase
        role="special">()</phrase></code> rather than <ulink url="http://www.boost.org/doc/libs/release/doc/html/boost_asio/reference/basic_waitable_timer/cancel.html"><code><phrase
        role="identifier">cancel</phrase><phrase role="special">()</phrase></code></ulink>.
      </para>
      <para>
        This <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">round_robin</phrase></code> implementation is used in
        <ulink url="../../examples/asio/autoecho.cpp"><code><phrase role="identifier">examples</phrase><phrase
        role="special">/</phrase><phrase role="identifier">asio</phrase><phrase role="special">/</phrase><phrase
        role="identifier">autoecho</phrase><phrase role="special">.</phrase><phrase
        role="identifier">cpp</phrase></code></ulink>.
      </para>
      <para>
        It seems possible that you could put together a more elegant Fiber / Asio
        integration. But as noted at the outset: it&#8217;s tricky.
      </para>
    </section>
  </section>
  <section id="fiber.speculation">
    <title><anchor id="speculation"/><link linkend="fiber.speculation">Specualtive
    execution</link></title>
    <bridgehead renderas="sect3" id="fiber.speculation.h0">
      <phrase id="fiber.speculation.hardware_transactional_memory"/><link linkend="fiber.speculation.hardware_transactional_memory">Hardware
      transactional memory</link>
    </bridgehead>
    <para>
      With help of hardware transactional memory multiple logical processors execute
      a critical region speculatively, e.g. without explicit synchronization.<sbr/>
      If the transactional execution completes successfully, then all memory operations
      performed within the transactional region are commited without any inter-thread
      serialization.<sbr/> When the optimistic execution fails, the processor aborts
      the transaction and discards all performed modifications.<sbr/> In non-transactional
      code a single lock serializes the access to a critical region. With a transactional
      memory, multiple logical processor start a transaction and update the memory
      (the data) inside the ciritical region. Unless some logical processors try
      to update the same data, the transactions would always succeed.
    </para>
    <bridgehead renderas="sect3" id="fiber.speculation.h1">
      <phrase id="fiber.speculation.intel_transactional_synchronisation_extensions__tsx_"/><link
      linkend="fiber.speculation.intel_transactional_synchronisation_extensions__tsx_">Intel
      Transactional Synchronisation Extensions (TSX)</link>
    </bridgehead>
    <para>
      TSX is Intel's implementation of hardware transactional memory in modern Intel
      processors<footnote id="fiber.speculation.f0">
      <para>
        intel.com: <ulink url="https://software.intel.com/en-us/node/695149">Intel
        Transactional Synchronization Extensions</ulink>
      </para>
      </footnote>.<sbr/> In TSX the hardware keeps track of which cachelines have
      been read from and which have been written to in a transaction. The cache-line
      size (64-byte) and the n-way set associative cache determine the maximum size
      of memory in a transaction. For instance if a transaction modifies 9 cache-lines
      at a processor with a 8-way set associative cache, the transaction will always
      be aborted.
    </para>
    <note>
      <para>
        TXS is enabled if property <code><phrase role="identifier">htm</phrase><phrase
        role="special">=</phrase><phrase role="identifier">tsx</phrase></code> is
        specified at b2 command-line and <code><phrase role="identifier">BOOST_USE_TSX</phrase></code>
        is applied to the compiler.
      </para>
    </note>
    <note>
      <para>
        A TSX-transaction will be aborted if the floating point state is modified
        inside a critical region. As a consequence floating point operations, e.g.
        store/load of floating point related registers during a fiber (context) switch
        are disabled.
      </para>
    </note>
    <important>
      <para>
        TSX can not be used together with MSVC at this time!
      </para>
    </important>
    <para>
      Boost.Fiber uses TSX-enabled spinlocks to protect critical regions (see section
      <link linkend="tuning">Tuning</link>).
    </para>
  </section>
  <section id="fiber.numa">
    <title><anchor id="numa"/><link linkend="fiber.numa">NUMA</link></title>
    <para>
      Modern micro-processors contain integrated memory controllers that are connected
      via channels to the memory. Accessing the memory can be organized in two kinds:<sbr/>
      Uniform Memory Access (UMA) and Non-Uniform Memory Access (NUMA).
    </para>
    <para>
      In contrast to UMA, that provides a centralized pool of memory (and thus does
      not scale after a certain number of processors), a NUMA architecture divides
      the memory into local and remote memory relative to the micro-processor.<sbr/>
      Local memory is directly attached to the processor's integrated memory controller.
      Memory connected to the memory controller of another micro-processor (multi-socket
      systems) is considered as remote memory. If a memory controller access remote
      memory it has to traverse the interconnect<footnote id="fiber.numa.f0">
      <para>
        On x86 the interconnection is implemented by Intel's Quick Path Interconnect
        (QPI) and AMD's HyperTransport.
      </para>
      </footnote> and connect to the remote memory controller.<sbr/> Thus accessing
      remote memory adds additional latency overhead to local memory access. Because
      of the different memory locations, a NUMA-system experiences <emphasis>non-uniform</emphasis>
      memory access time.<sbr/> As a consequence the best performance is achieved
      by keeping the memory access local.
    </para>
    <para>
      <inlinemediaobject><imageobject><imagedata align="center" fileref="../../../../libs/fiber/doc/NUMA.png"></imagedata></imageobject>
      <textobject>
        <phrase>NUMA</phrase>
      </textobject>
      </inlinemediaobject>
    </para>
    <bridgehead renderas="sect3" id="fiber.numa.h0">
      <phrase id="fiber.numa.numa_support_in_boost_fiber"/><link linkend="fiber.numa.numa_support_in_boost_fiber">NUMA
      support in Boost.Fiber</link>
    </bridgehead>
    <para>
      Because only a subset of the NUMA-functionality is exposed by several operating
      systems, Boost.Fiber provides only a minimalistic NUMA API.
    </para>
    <important>
      <para>
        In order to enable NUMA support, b2 property <code><phrase role="identifier">numa</phrase><phrase
        role="special">=</phrase><phrase role="identifier">on</phrase></code> must
        be specified and linked against additional library <code><phrase role="identifier">libboost_fiber_numa</phrase><phrase
        role="special">.</phrase><phrase role="identifier">so</phrase></code>.
      </para>
    </important>
    <important>
      <para>
        MinGW using pthread implementation is not supported on Windows.
      </para>
    </important>
    <table frame="all" id="fiber.numa.supported_functionality_operating_systems">
      <title>Supported functionality/operating systems</title>
      <tgroup cols="7">
        <thead>
          <row>
            <entry>
            </entry>
            <entry>
              <para>
                AIX
              </para>
            </entry>
            <entry>
              <para>
                FreeBSD
              </para>
            </entry>
            <entry>
              <para>
                HP/UX
              </para>
            </entry>
            <entry>
              <para>
                Linux
              </para>
            </entry>
            <entry>
              <para>
                Solaris
              </para>
            </entry>
            <entry>
              <para>
                Windows
              </para>
            </entry>
          </row>
        </thead>
        <tbody>
          <row>
            <entry>
              <para>
                pin thread
              </para>
            </entry>
            <entry>
              <para>
                +
              </para>
            </entry>
            <entry>
              <para>
                +
              </para>
            </entry>
            <entry>
              <para>
                +
              </para>
            </entry>
            <entry>
              <para>
                +
              </para>
            </entry>
            <entry>
              <para>
                +
              </para>
            </entry>
            <entry>
              <para>
                +
              </para>
            </entry>
          </row>
          <row>
            <entry>
              <para>
                logical CPUs/NUMA nodes
              </para>
            </entry>
            <entry>
              <para>
                +
              </para>
            </entry>
            <entry>
              <para>
                +
              </para>
            </entry>
            <entry>
              <para>
                +
              </para>
            </entry>
            <entry>
              <para>
                +
              </para>
            </entry>
            <entry>
              <para>
                +
              </para>
            </entry>
            <entry>
              <para>
                +<footnote id="fiber.numa.f1">
                <para>
                  Windows organizes logical cpus in groups of 64; boost.fiber maps
                  {group-id,cpud-id} to a scalar equivalent to cpu ID of Linux (64
                  * group ID + cpu ID).
                </para>
                </footnote>
              </para>
            </entry>
          </row>
          <row>
            <entry>
              <para>
                NUMA node distance
              </para>
            </entry>
            <entry>
              <para>
                -
              </para>
            </entry>
            <entry>
              <para>
                -
              </para>
            </entry>
            <entry>
              <para>
                -
              </para>
            </entry>
            <entry>
              <para>
                +
              </para>
            </entry>
            <entry>
              <para>
                -
              </para>
            </entry>
            <entry>
              <para>
                -
              </para>
            </entry>
          </row>
          <row>
            <entry>
              <para>
                tested on
              </para>
            </entry>
            <entry>
              <para>
                AIX 7.2
              </para>
            </entry>
            <entry>
              <para>
                FreeBSD 11
              </para>
            </entry>
            <entry>
              <para>
                -
              </para>
            </entry>
            <entry>
              <para>
                Arch Linux (4.10.13)
              </para>
            </entry>
            <entry>
              <para>
                OpenIndiana HIPSTER
              </para>
            </entry>
            <entry>
              <para>
                Windows 10
              </para>
            </entry>
          </row>
        </tbody>
      </tgroup>
    </table>
    <para>
      In order to keep the memory access local as possible, the NUMA topology must
      be evaluated.
    </para>
<programlisting><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">vector</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">numa</phrase><phrase role="special">::</phrase><phrase role="identifier">node</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">topo</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">numa</phrase><phrase role="special">::</phrase><phrase role="identifier">topology</phrase><phrase role="special">();</phrase>
<phrase role="keyword">for</phrase> <phrase role="special">(</phrase> <phrase role="keyword">auto</phrase> <phrase role="identifier">n</phrase> <phrase role="special">:</phrase> <phrase role="identifier">topo</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;node: &quot;</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="identifier">n</phrase><phrase role="special">.</phrase><phrase role="identifier">id</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="string">&quot; | &quot;</phrase><phrase role="special">;</phrase>
    <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cout</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="string">&quot;cpus: &quot;</phrase><phrase role="special">;</phrase>
    <phrase role="keyword">for</phrase> <phrase role="special">(</phrase> <phrase role="keyword">auto</phrase> <phrase role="identifier">cpu_id</phrase> <phrase role="special">:</phrase> <phrase role="identifier">n</phrase><phrase role="special">.</phrase><phrase role="identifier">logical_cpus</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">cpu_id</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="string">&quot;| distance: &quot;</phrase><phrase role="special">;</phrase>
    <phrase role="keyword">for</phrase> <phrase role="special">(</phrase> <phrase role="keyword">auto</phrase> <phrase role="identifier">d</phrase> <phrase role="special">:</phrase> <phrase role="identifier">n</phrase><phrase role="special">.</phrase><phrase role="identifier">distance</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">d</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>
<phrase role="special">}</phrase>
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cout</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="string">&quot;done&quot;</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">endl</phrase><phrase role="special">;</phrase>

<phrase role="identifier">output</phrase><phrase role="special">:</phrase>
    <phrase role="identifier">node</phrase><phrase role="special">:</phrase> <phrase role="number">0</phrase> <phrase role="special">|</phrase> <phrase role="identifier">cpus</phrase><phrase role="special">:</phrase> <phrase role="number">0</phrase> <phrase role="number">1</phrase> <phrase role="number">2</phrase> <phrase role="number">3</phrase> <phrase role="number">4</phrase> <phrase role="number">5</phrase> <phrase role="number">6</phrase> <phrase role="number">7</phrase> <phrase role="number">16</phrase> <phrase role="number">17</phrase> <phrase role="number">18</phrase> <phrase role="number">19</phrase> <phrase role="number">20</phrase> <phrase role="number">21</phrase> <phrase role="number">22</phrase> <phrase role="number">23</phrase> <phrase role="special">|</phrase> <phrase role="identifier">distance</phrase><phrase role="special">:</phrase> <phrase role="number">10</phrase> <phrase role="number">21</phrase>
    <phrase role="identifier">node</phrase><phrase role="special">:</phrase> <phrase role="number">1</phrase> <phrase role="special">|</phrase> <phrase role="identifier">cpus</phrase><phrase role="special">:</phrase> <phrase role="number">8</phrase> <phrase role="number">9</phrase> <phrase role="number">10</phrase> <phrase role="number">11</phrase> <phrase role="number">12</phrase> <phrase role="number">13</phrase> <phrase role="number">14</phrase> <phrase role="number">15</phrase> <phrase role="number">24</phrase> <phrase role="number">25</phrase> <phrase role="number">26</phrase> <phrase role="number">27</phrase> <phrase role="number">28</phrase> <phrase role="number">29</phrase> <phrase role="number">30</phrase> <phrase role="number">31</phrase> <phrase role="special">|</phrase> <phrase role="identifier">distance</phrase><phrase role="special">:</phrase> <phrase role="number">21</phrase> <phrase role="number">10</phrase>
    <phrase role="identifier">done</phrase>
</programlisting>
    <para>
      The example shows that the systems consits out of 2 NUMA-nodes, to each NUMA-node
      belong 16 logical cpus. The distance measures the costs to access the memory
      of another NUMA-node. A NUMA-node has always a distance <code><phrase role="number">10</phrase></code>
      to itself (lowest possible value).<sbr/> The position in the array corresponds
      with the NUMA-node ID.
    </para>
    <para>
      Some work-loads benefit from pinning threads to a logical cpus. For instance
      scheduling algorithm <link linkend="class_numa_work_stealing"><code>numa::work_stealing</code></link> pins the thread
      that runs the fiber scheduler to a logical cpu. This prevents the operating
      system scheduler to move the thread to another logical cpu that might run other
      fiber scheduler(s) or migrating the thread to a logical cpu part of another
      NUMA-node.
    </para>
<programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">thread</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">uint32_t</phrase> <phrase role="identifier">cpu_id</phrase><phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">uint32_t</phrase> <phrase role="identifier">node_id</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">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">numa</phrase><phrase role="special">::</phrase><phrase role="identifier">node</phrase> <phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">topo</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
    <phrase role="comment">// thread registers itself at work-stealing scheduler</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">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">algo</phrase><phrase role="special">::</phrase><phrase role="identifier">numa</phrase><phrase role="special">::</phrase><phrase role="identifier">work_stealing</phrase> <phrase role="special">&gt;(</phrase> <phrase role="identifier">cpu_id</phrase><phrase role="special">,</phrase> <phrase role="identifier">node_id</phrase><phrase role="special">,</phrase> <phrase role="identifier">topo</phrase><phrase role="special">);</phrase>
    <phrase role="special">...</phrase>
<phrase role="special">}</phrase>

<phrase role="comment">// evaluate the NUMA topology</phrase>
<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">vector</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">numa</phrase><phrase role="special">::</phrase><phrase role="identifier">node</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">topo</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">numa</phrase><phrase role="special">::</phrase><phrase role="identifier">topology</phrase><phrase role="special">();</phrase>
<phrase role="comment">// start-thread runs on NUMA-node `0`</phrase>
<phrase role="keyword">auto</phrase> <phrase role="identifier">node</phrase> <phrase role="special">=</phrase> <phrase role="identifier">topo</phrase><phrase role="special">[</phrase><phrase role="number">0</phrase><phrase role="special">];</phrase>
<phrase role="comment">// start-thread is pinnded to first cpu ID in the list of logical cpus of NUMA-node `0`</phrase>
<phrase role="keyword">auto</phrase> <phrase role="identifier">start_cpu_id</phrase> <phrase role="special">=</phrase> <phrase role="special">*</phrase> <phrase role="identifier">node</phrase><phrase role="special">.</phrase><phrase role="identifier">logical_cpus</phrase><phrase role="special">.</phrase><phrase role="identifier">begin</phrase><phrase role="special">();</phrase>
<phrase role="comment">// start worker-threads first</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">thread</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">threads</phrase><phrase role="special">;</phrase>
<phrase role="keyword">for</phrase> <phrase role="special">(</phrase> <phrase role="keyword">auto</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">node</phrase> <phrase role="special">:</phrase> <phrase role="identifier">topo</phrase><phrase role="special">)</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">uint32_t</phrase> <phrase role="identifier">cpu_id</phrase> <phrase role="special">:</phrase> <phrase role="identifier">node</phrase><phrase role="special">.</phrase><phrase role="identifier">logical_cpus</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
        <phrase role="comment">// exclude start-thread</phrase>
        <phrase role="keyword">if</phrase> <phrase role="special">(</phrase> <phrase role="identifier">start_cpu_id</phrase> <phrase role="special">!=</phrase> <phrase role="identifier">cpu_id</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
            <phrase role="comment">// spawn thread</phrase>
            <phrase role="identifier">threads</phrase><phrase role="special">.</phrase><phrase role="identifier">emplace_back</phrase><phrase role="special">(</phrase> <phrase role="identifier">thread</phrase><phrase role="special">,</phrase> <phrase role="identifier">cpu_id</phrase><phrase role="special">,</phrase> <phrase role="identifier">node</phrase><phrase role="special">.</phrase><phrase role="identifier">id</phrase><phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cref</phrase><phrase role="special">(</phrase> <phrase role="identifier">topo</phrase><phrase role="special">)</phrase> <phrase role="special">);</phrase>
        <phrase role="special">}</phrase>
    <phrase role="special">}</phrase>
<phrase role="special">}</phrase>
<phrase role="comment">// start-thread registers itself on work-stealing scheduler</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">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">algo</phrase><phrase role="special">::</phrase><phrase role="identifier">numa</phrase><phrase role="special">::</phrase><phrase role="identifier">work_stealing</phrase> <phrase role="special">&gt;(</phrase> <phrase role="identifier">start_cpu_id</phrase><phrase role="special">,</phrase> <phrase role="identifier">node</phrase><phrase role="special">.</phrase><phrase role="identifier">id</phrase><phrase role="special">,</phrase> <phrase role="identifier">topo</phrase><phrase role="special">);</phrase>
<phrase role="special">...</phrase>
</programlisting>
    <para>
      The example evaluates the NUMA topology with <code><phrase role="identifier">boost</phrase><phrase
      role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase
      role="special">::</phrase><phrase role="identifier">numa</phrase><phrase role="special">::</phrase><phrase
      role="identifier">topology</phrase><phrase role="special">()</phrase></code>
      and spawns for each logical cpu a thread. Each spawned thread installs the
      NUMA-aware work-stealing scheduler. The scheduler pins the thread to the logical
      cpu that was specified at construction.<sbr/> If the local queue of one thread
      runs out of ready fibers, the thread tries to steal a ready fiber from another
      thread running at logical cpu that belong to the same NUMA-node (local memory
      access). If no fiber could be stolen, the thread tries to steal fibers from
      logical cpus part of other NUMA-nodes (remote memory access).
    </para>
    <bridgehead renderas="sect3" id="fiber.numa.h1">
      <phrase id="fiber.numa.synopsis"/><link linkend="fiber.numa.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">numa</phrase><phrase role="special">/</phrase><phrase role="identifier">pin_thread</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase>
<phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">fiber</phrase><phrase role="special">/</phrase><phrase role="identifier">numa</phrase><phrase role="special">/</phrase><phrase role="identifier">topology</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">namespace</phrase> <phrase role="identifier">numa</phrase> <phrase role="special">{</phrase>

<phrase role="keyword">struct</phrase> <phrase role="identifier">node</phrase> <phrase role="special">{</phrase>
    <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">uint32_t</phrase>                   <phrase role="identifier">id</phrase><phrase role="special">;</phrase>
    <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">set</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">uint32_t</phrase> <phrase role="special">&gt;</phrase>       <phrase role="identifier">logical_cpus</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">uint32_t</phrase> <phrase role="special">&gt;</phrase>    <phrase role="identifier">distance</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">node</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;,</phrase> <phrase role="identifier">node</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;)</phrase> <phrase role="keyword">noexcept</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">node</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">topology</phrase><phrase role="special">();</phrase>

<phrase role="keyword">void</phrase> <phrase role="identifier">pin_thread</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">uint32_t</phrase><phrase role="special">);</phrase>
<phrase role="keyword">void</phrase> <phrase role="identifier">pin_thread</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">uint32_t</phrase><phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">thread</phrase><phrase role="special">::</phrase><phrase role="identifier">native_handle_type</phrase><phrase role="special">);</phrase>

<phrase role="special">}}}</phrase>

<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">numa</phrase><phrase role="special">/</phrase><phrase role="identifier">algo</phrase><phrase role="special">/</phrase><phrase role="identifier">work_stealing</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">namespace</phrase> <phrase role="identifier">numa</phrase> <phrase role="special">{</phrase>
<phrase role="keyword">namespace</phrase> <phrase role="identifier">algo</phrase> <phrase role="special">{</phrase>

<phrase role="keyword">class</phrase> <phrase role="identifier">work_stealing</phrase><phrase role="special">;</phrase>

<phrase role="special">}}}</phrase>
</programlisting>
    <para>
      <bridgehead renderas="sect4" id="class_numa_node_bridgehead">
  <phrase id="class_numa_node"/>
  <link linkend="class_numa_node">Class <code>numa::node</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">numa</phrase><phrase role="special">/</phrase><phrase role="identifier">topology</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">namespace</phrase> <phrase role="identifier">numa</phrase> <phrase role="special">{</phrase>

<phrase role="keyword">struct</phrase> <phrase role="identifier">node</phrase> <phrase role="special">{</phrase>
    <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">uint32_t</phrase>                   <phrase role="identifier">id</phrase><phrase role="special">;</phrase>
    <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">set</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">uint32_t</phrase> <phrase role="special">&gt;</phrase>       <phrase role="identifier">logical_cpus</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">uint32_t</phrase> <phrase role="special">&gt;</phrase>    <phrase role="identifier">distance</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">node</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;,</phrase> <phrase role="identifier">node</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>

<phrase role="special">}}}</phrase>
</programlisting>
    <para>
      <bridgehead renderas="sect4" id="numa_node_id_bridgehead">
  <phrase id="numa_node_id"/>
  <link linkend="numa_node_id">Data member <code>id</code></link>
</bridgehead>
    </para>
<programlisting><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">uint32_t</phrase> <phrase role="identifier">id</phrase><phrase role="special">;</phrase>
</programlisting>
    <variablelist>
      <title></title>
      <varlistentry>
        <term>Effects:</term>
        <listitem>
          <para>
            ID of the NUMA-node
          </para>
        </listitem>
      </varlistentry>
    </variablelist>
    <para>
      <bridgehead renderas="sect4" id="numa_node_logical_cpus_bridgehead">
  <phrase id="numa_node_logical_cpus"/>
  <link linkend="numa_node_logical_cpus">Data
      member <code>logical_cpus</code></link>
</bridgehead>
    </para>
<programlisting><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">set</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">uint32_t</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">logical_cpus</phrase><phrase role="special">;</phrase>
</programlisting>
    <variablelist>
      <title></title>
      <varlistentry>
        <term>Effects:</term>
        <listitem>
          <para>
            set of logical cpu IDs belonging to the NUMA-node
          </para>
        </listitem>
      </varlistentry>
    </variablelist>
    <para>
      <bridgehead renderas="sect4" id="numa_node_distance_bridgehead">
  <phrase id="numa_node_distance"/>
  <link linkend="numa_node_distance">Data member
      <code>distance</code></link>
</bridgehead>
    </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">uint32_t</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">distance</phrase><phrase role="special">;</phrase>
</programlisting>
    <variablelist>
      <title></title>
      <varlistentry>
        <term>Effects:</term>
        <listitem>
          <para>
            The distance between NUMA-nodes describe the cots of accessing the remote
            memory.
          </para>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term>Note:</term>
        <listitem>
          <para>
            A NUMA-node has a distance of <code><phrase role="number">10</phrase></code>
            to itself, remote NUMA-nodes have a distance &gt; <code><phrase role="number">10</phrase></code>.
            The index in the array corresponds to the ID <code><phrase role="identifier">id</phrase></code>
            of the NUMA-node. At the moment only Linux returns the correct distances,
            for all other operating systems remote NUMA-nodes get a default value
            of <code><phrase role="number">20</phrase></code>.
          </para>
        </listitem>
      </varlistentry>
    </variablelist>
    <para>
      <bridgehead renderas="sect4" id="numa_node_operator_less_bridgehead">
  <phrase id="numa_node_operator_less"/>
  <link linkend="numa_node_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">node</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">lhs</phrase><phrase role="special">,</phrase> <phrase role="identifier">node</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">rhs</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="identifier">lhs</phrase>
            <phrase role="special">!=</phrase> <phrase role="identifier">rhs</phrase></code>
            is true and the implementation-defined total order of <code><phrase role="identifier">node</phrase><phrase
            role="special">::</phrase><phrase role="identifier">id</phrase></code>
            values places <code><phrase role="identifier">lhs</phrase></code> before
            <code><phrase role="identifier">rhs</phrase></code>, false otherwise.
          </para>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term>Throws:</term>
        <listitem>
          <para>
            Nothing.
          </para>
        </listitem>
      </varlistentry>
    </variablelist>
    <para>
      <bridgehead renderas="sect4" id="numa_topology_bridgehead">
  <phrase id="numa_topology"/>
  <link linkend="numa_topology">Non-member function <code>numa::topology()</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">numa</phrase><phrase role="special">/</phrase><phrase role="identifier">topology</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">namespace</phrase> <phrase role="identifier">numa</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">node</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">topology</phrase><phrase role="special">();</phrase>

<phrase role="special">}}}</phrase>
</programlisting>
    <variablelist>
      <title></title>
      <varlistentry>
        <term>Effects:</term>
        <listitem>
          <para>
            Evaluates the NUMA topology.
          </para>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term>Returns:</term>
        <listitem>
          <para>
            a vector of NUMA-nodes describing the NUMA architecture of the system
            (each element represents a NUMA-node).
          </para>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term>Throws:</term>
        <listitem>
          <para>
            <code><phrase role="identifier">system_error</phrase></code>
          </para>
        </listitem>
      </varlistentry>
    </variablelist>
    <para>
      <bridgehead renderas="sect4" id="numa_pin_thread_bridgehead">
  <phrase id="numa_pin_thread"/>
  <link linkend="numa_pin_thread">Non-member function
      <code>numa::pin_thread()</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">numa</phrase><phrase role="special">/</phrase><phrase role="identifier">pin_thread</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">namespace</phrase> <phrase role="identifier">numa</phrase> <phrase role="special">{</phrase>

<phrase role="keyword">void</phrase> <phrase role="identifier">pin_thread</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">uint32_t</phrase> <phrase role="identifier">cpu_id</phrase><phrase role="special">);</phrase>
<phrase role="keyword">void</phrase> <phrase role="identifier">pin_thread</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">uint32_t</phrase> <phrase role="identifier">cpu_id</phrase><phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">thread</phrase><phrase role="special">::</phrase><phrase role="identifier">native_handle_type</phrase> <phrase role="identifier">h</phrase><phrase role="special">);</phrase>

<phrase role="special">}}}</phrase>
</programlisting>
    <variablelist>
      <title></title>
      <varlistentry>
        <term>Effects:</term>
        <listitem>
          <para>
            First version pins <code><phrase role="keyword">this</phrase> <phrase
            role="identifier">thread</phrase></code> to the logical cpu with ID
            <code><phrase role="identifier">cpu_id</phrase></code>, e.g. the operating
            system scheduler will not migrate the thread to another logical cpu.
            The second variant pins the thread with the native ID <code><phrase role="identifier">h</phrase></code>
            to logical cpu with ID <code><phrase role="identifier">cpu_id</phrase></code>.
          </para>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term>Throws:</term>
        <listitem>
          <para>
            <code><phrase role="identifier">system_error</phrase></code>
          </para>
        </listitem>
      </varlistentry>
    </variablelist>
    <para>
      <bridgehead renderas="sect4" id="class_numa_work_stealing_bridgehead">
  <phrase id="class_numa_work_stealing"/>
  <link linkend="class_numa_work_stealing">Class
      <code>numa::work_stealing</code></link>
</bridgehead>
    </para>
    <para>
      This class implements <link linkend="class_algorithm"><code>algorithm</code></link>; the thread running this scheduler
      is pinned to the given logical cpu. If the local ready-queue runs out of ready
      fibers, ready fibers are stolen from other schedulers that run on logical cpus
      that belong to the same NUMA-node (local memory access).<sbr/> If no ready
      fibers can be stolen from the local NUMA-node, the algorithm selects schedulers
      running on other NUMA-nodes (remote memory access).<sbr/> The victim scheduler
      (from which a ready fiber is stolen) is selected at random.
    </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">numa</phrase><phrase role="special">/</phrase><phrase role="identifier">algo</phrase><phrase role="special">/</phrase><phrase role="identifier">work_stealing</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">namespace</phrase> <phrase role="identifier">numa</phrase> <phrase role="special">{</phrase>
<phrase role="keyword">namespace</phrase> <phrase role="identifier">algo</phrase> <phrase role="special">{</phrase>

<phrase role="keyword">class</phrase> <phrase role="identifier">work_stealing</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <phrase role="identifier">algorithm</phrase> <phrase role="special">{</phrase>
<phrase role="keyword">public</phrase><phrase role="special">:</phrase>
    <phrase role="identifier">work_stealing</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">uint32_t</phrase> <phrase role="identifier">cpu_id</phrase><phrase role="special">,</phrase>
                   <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">uint32_t</phrase> <phrase role="identifier">node_id</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">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">numa</phrase><phrase role="special">::</phrase><phrase role="identifier">node</phrase> <phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">topo</phrase><phrase role="special">,</phrase>
                   <phrase role="keyword">bool</phrase> <phrase role="identifier">suspend</phrase> <phrase role="special">=</phrase> <phrase role="keyword">false</phrase><phrase role="special">);</phrase>

    <phrase role="identifier">work_stealing</phrase><phrase role="special">(</phrase> <phrase role="identifier">work_stealing</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">work_stealing</phrase><phrase role="special">(</phrase> <phrase role="identifier">work_stealing</phrase> <phrase role="special">&amp;&amp;)</phrase> <phrase role="special">=</phrase> <phrase role="keyword">delete</phrase><phrase role="special">;</phrase>

    <phrase role="identifier">work_stealing</phrase> <phrase role="special">&amp;</phrase> <phrase role="keyword">operator</phrase><phrase role="special">=(</phrase> <phrase role="identifier">work_stealing</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">work_stealing</phrase> <phrase role="special">&amp;</phrase> <phrase role="keyword">operator</phrase><phrase role="special">=(</phrase> <phrase role="identifier">work_stealing</phrase> <phrase role="special">&amp;&amp;)</phrase> <phrase role="special">=</phrase> <phrase role="keyword">delete</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">noexcept</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">noexcept</phrase><phrase role="special">;</phrase>

    <phrase role="keyword">virtual</phrase> <phrase role="keyword">bool</phrase> <phrase role="identifier">has_ready_fibers</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>

    <phrase role="keyword">virtual</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">suspend_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">steady_clock</phrase><phrase role="special">::</phrase><phrase role="identifier">time_point</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>

    <phrase role="keyword">virtual</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">notify</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
<phrase role="special">};</phrase>

<phrase role="special">}}}}</phrase>
</programlisting>
    <bridgehead renderas="sect3" id="fiber.numa.h2">
      <phrase id="fiber.numa.constructor"/><link linkend="fiber.numa.constructor">Constructor</link>
    </bridgehead>
<programlisting><phrase role="identifier">work_stealing</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">uint32_t</phrase> <phrase role="identifier">cpu_id</phrase><phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">uint32_t</phrase> <phrase role="identifier">node_id</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">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">numa</phrase><phrase role="special">::</phrase><phrase role="identifier">node</phrase> <phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">topo</phrase><phrase role="special">,</phrase>
               <phrase role="keyword">bool</phrase> <phrase role="identifier">suspend</phrase> <phrase role="special">=</phrase> <phrase role="keyword">false</phrase><phrase role="special">);</phrase>
</programlisting>
    <variablelist>
      <title></title>
      <varlistentry>
        <term>Effects:</term>
        <listitem>
          <para>
            Constructs work-stealing scheduling algorithm. The thread is pinned to
            logical cpu with ID <code><phrase role="identifier">cpu_id</phrase></code>.
            If local ready-queue runs out of ready fibers, ready fibers are stolen
            from other schedulers using <code><phrase role="identifier">topology</phrase></code>
            (represents the NUMA-topology of the system).
          </para>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term>Throws:</term>
        <listitem>
          <para>
            <code><phrase role="identifier">system_error</phrase></code>
          </para>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term>Note:</term>
        <listitem>
          <para>
            If <code><phrase role="identifier">suspend</phrase></code> is set to
            <code><phrase role="keyword">true</phrase></code>, then the scheduler
            suspends if no ready fiber could be stolen. The scheduler will by woken
            up if a sleeping fiber times out or it was notified from remote (other
            thread or fiber scheduler).
          </para>
        </listitem>
      </varlistentry>
    </variablelist>
    <para>
      <bridgehead renderas="sect4" id="numa_work_stealing_awakened_bridgehead">
  <phrase id="numa_work_stealing_awakened"/>
  <link linkend="numa_work_stealing_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="keyword">noexcept</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
            the shared ready queue.
          </para>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term>Throws:</term>
        <listitem>
          <para>
            Nothing.
          </para>
        </listitem>
      </varlistentry>
    </variablelist>
    <para>
      <bridgehead renderas="sect4" id="numa_work_stealing_pick_next_bridgehead">
  <phrase id="numa_work_stealing_pick_next"/>
  <link linkend="numa_work_stealing_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="keyword">noexcept</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 <code><phrase role="keyword">nullptr</phrase></code>
            if the queue is empty.
          </para>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term>Throws:</term>
        <listitem>
          <para>
            Nothing.
          </para>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term>Note:</term>
        <listitem>
          <para>
            Placing ready fibers onto the tail of the sahred 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="numa_work_stealing_has_ready_fibers_bridgehead">
  <phrase id="numa_work_stealing_has_ready_fibers"/>
  <link linkend="numa_work_stealing_has_ready_fibers">Member
      function <code>has_ready_fibers</code>()</link>
</bridgehead>
    </para>
<programlisting><phrase role="keyword">virtual</phrase> <phrase role="keyword">bool</phrase> <phrase role="identifier">has_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>
            <code><phrase role="keyword">true</phrase></code> if scheduler has fibers
            ready to run.
          </para>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term>Throws:</term>
        <listitem>
          <para>
            Nothing.
          </para>
        </listitem>
      </varlistentry>
    </variablelist>
    <para>
      <bridgehead renderas="sect4" id="numa_work_stealing_suspend_until_bridgehead">
  <phrase id="numa_work_stealing_suspend_until"/>
  <link linkend="numa_work_stealing_suspend_until">Member
      function <code>suspend_until</code>()</link>
</bridgehead>
    </para>
<programlisting><phrase role="keyword">virtual</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">suspend_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">steady_clock</phrase><phrase role="special">::</phrase><phrase role="identifier">time_point</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">abs_time</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
</programlisting>
    <variablelist>
      <title></title>
      <varlistentry>
        <term>Effects:</term>
        <listitem>
          <para>
            Informs <code><phrase role="identifier">work_stealing</phrase></code>
            that no ready fiber will be available until time-point <code><phrase
            role="identifier">abs_time</phrase></code>. This implementation blocks
            in <ulink url="http://en.cppreference.com/w/cpp/thread/condition_variable/wait_until"><code><phrase
            role="identifier">std</phrase><phrase role="special">::</phrase><phrase
            role="identifier">condition_variable</phrase><phrase role="special">::</phrase><phrase
            role="identifier">wait_until</phrase><phrase role="special">()</phrase></code></ulink>.
          </para>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term>Throws:</term>
        <listitem>
          <para>
            Nothing.
          </para>
        </listitem>
      </varlistentry>
    </variablelist>
    <para>
      <bridgehead renderas="sect4" id="numa_work_stealing_notify_bridgehead">
  <phrase id="numa_work_stealing_notify"/>
  <link linkend="numa_work_stealing_notify">Member
      function <code>notify</code>()</link>
</bridgehead>
    </para>
<programlisting><phrase role="keyword">virtual</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">notify</phrase><phrase role="special">()</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>Effects:</term>
        <listitem>
          <para>
            Wake up a pending call to <link linkend="work_stealing_suspend_until"><code>work_stealing::suspend_until()</code></link>,
            some fibers might be ready. This implementation wakes <code><phrase role="identifier">suspend_until</phrase><phrase
            role="special">()</phrase></code> via <ulink url="http://en.cppreference.com/w/cpp/thread/condition_variable/notify_all"><code><phrase
            role="identifier">std</phrase><phrase role="special">::</phrase><phrase
            role="identifier">condition_variable</phrase><phrase role="special">::</phrase><phrase
            role="identifier">notify_all</phrase><phrase role="special">()</phrase></code></ulink>.
          </para>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term>Throws:</term>
        <listitem>
          <para>
            Nothing.
          </para>
        </listitem>
      </varlistentry>
    </variablelist>
  </section>
  <section id="fiber.gpu_computing">
    <title><link linkend="fiber.gpu_computing">GPU computing</link></title>
    <section id="fiber.gpu_computing.cuda">
      <title><anchor id="cuda"/><link linkend="fiber.gpu_computing.cuda">CUDA</link></title>
      <para>
        <ulink url="http://developer.nvidia.com/cuda-zone/">CUDA (Compute Unified
        Device Architecture)</ulink> is a platform for parallel computing on NVIDIA
        GPUs. The application programming interface of CUDA gives access to GPU's
        instruction set and computation resources (Execution of compute kernels).
      </para>
      <bridgehead renderas="sect4" id="fiber.gpu_computing.cuda.h0">
        <phrase id="fiber.gpu_computing.cuda.synchronization_with_cuda_streams"/><link
        linkend="fiber.gpu_computing.cuda.synchronization_with_cuda_streams">Synchronization
        with CUDA streams</link>
      </bridgehead>
      <para>
        CUDA operation such as compute kernels or memory transfer (between host and
        device) can be grouped/queued by CUDA streams. are executed on the GPUs.
        Boost.Fiber enables a fiber to sleep (suspend) till a CUDA stream has completed
        its operations. This enables applications to run other fibers on the CPU
        without the need to spawn an additional OS-threads. And resume the fiber
        when the CUDA streams has finished.
      </para>
<programlisting><phrase role="identifier">__global__</phrase>
<phrase role="keyword">void</phrase> <phrase role="identifier">kernel</phrase><phrase role="special">(</phrase> <phrase role="keyword">int</phrase> <phrase role="identifier">size</phrase><phrase role="special">,</phrase> <phrase role="keyword">int</phrase> <phrase role="special">*</phrase> <phrase role="identifier">a</phrase><phrase role="special">,</phrase> <phrase role="keyword">int</phrase> <phrase role="special">*</phrase> <phrase role="identifier">b</phrase><phrase role="special">,</phrase> <phrase role="keyword">int</phrase> <phrase role="special">*</phrase> <phrase role="identifier">c</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
    <phrase role="keyword">int</phrase> <phrase role="identifier">idx</phrase> <phrase role="special">=</phrase> <phrase role="identifier">threadIdx</phrase><phrase role="special">.</phrase><phrase role="identifier">x</phrase> <phrase role="special">+</phrase> <phrase role="identifier">blockIdx</phrase><phrase role="special">.</phrase><phrase role="identifier">x</phrase> <phrase role="special">*</phrase> <phrase role="identifier">blockDim</phrase><phrase role="special">.</phrase><phrase role="identifier">x</phrase><phrase role="special">;</phrase>
    <phrase role="keyword">if</phrase> <phrase role="special">(</phrase> <phrase role="identifier">idx</phrase> <phrase role="special">&lt;</phrase> <phrase role="identifier">size</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
        <phrase role="keyword">int</phrase> <phrase role="identifier">idx1</phrase> <phrase role="special">=</phrase> <phrase role="special">(</phrase><phrase role="identifier">idx</phrase> <phrase role="special">+</phrase> <phrase role="number">1</phrase><phrase role="special">)</phrase> <phrase role="special">%</phrase> <phrase role="number">256</phrase><phrase role="special">;</phrase>
        <phrase role="keyword">int</phrase> <phrase role="identifier">idx2</phrase> <phrase role="special">=</phrase> <phrase role="special">(</phrase><phrase role="identifier">idx</phrase> <phrase role="special">+</phrase> <phrase role="number">2</phrase><phrase role="special">)</phrase> <phrase role="special">%</phrase> <phrase role="number">256</phrase><phrase role="special">;</phrase>
        <phrase role="keyword">float</phrase> <phrase role="identifier">as</phrase> <phrase role="special">=</phrase> <phrase role="special">(</phrase><phrase role="identifier">a</phrase><phrase role="special">[</phrase><phrase role="identifier">idx</phrase><phrase role="special">]</phrase> <phrase role="special">+</phrase> <phrase role="identifier">a</phrase><phrase role="special">[</phrase><phrase role="identifier">idx1</phrase><phrase role="special">]</phrase> <phrase role="special">+</phrase> <phrase role="identifier">a</phrase><phrase role="special">[</phrase><phrase role="identifier">idx2</phrase><phrase role="special">])</phrase> <phrase role="special">/</phrase> <phrase role="number">3.0f</phrase><phrase role="special">;</phrase>
        <phrase role="keyword">float</phrase> <phrase role="identifier">bs</phrase> <phrase role="special">=</phrase> <phrase role="special">(</phrase><phrase role="identifier">b</phrase><phrase role="special">[</phrase><phrase role="identifier">idx</phrase><phrase role="special">]</phrase> <phrase role="special">+</phrase> <phrase role="identifier">b</phrase><phrase role="special">[</phrase><phrase role="identifier">idx1</phrase><phrase role="special">]</phrase> <phrase role="special">+</phrase> <phrase role="identifier">b</phrase><phrase role="special">[</phrase><phrase role="identifier">idx2</phrase><phrase role="special">])</phrase> <phrase role="special">/</phrase> <phrase role="number">3.0f</phrase><phrase role="special">;</phrase>
        <phrase role="identifier">c</phrase><phrase role="special">[</phrase><phrase role="identifier">idx</phrase><phrase role="special">]</phrase> <phrase role="special">=</phrase> <phrase role="special">(</phrase><phrase role="identifier">as</phrase> <phrase role="special">+</phrase> <phrase role="identifier">bs</phrase><phrase role="special">)</phrase> <phrase role="special">/</phrase> <phrase role="number">2</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">([&amp;</phrase><phrase role="identifier">done</phrase><phrase role="special">]{</phrase>
    <phrase role="identifier">cudaStream_t</phrase> <phrase role="identifier">stream</phrase><phrase role="special">;</phrase>
    <phrase role="identifier">cudaStreamCreate</phrase><phrase role="special">(</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">stream</phrase><phrase role="special">);</phrase>
    <phrase role="keyword">int</phrase> <phrase role="identifier">size</phrase> <phrase role="special">=</phrase> <phrase role="number">1024</phrase> <phrase role="special">*</phrase> <phrase role="number">1024</phrase><phrase role="special">;</phrase>
    <phrase role="keyword">int</phrase> <phrase role="identifier">full_size</phrase> <phrase role="special">=</phrase> <phrase role="number">20</phrase> <phrase role="special">*</phrase> <phrase role="identifier">size</phrase><phrase role="special">;</phrase>
    <phrase role="keyword">int</phrase> <phrase role="special">*</phrase> <phrase role="identifier">host_a</phrase><phrase role="special">,</phrase> <phrase role="special">*</phrase> <phrase role="identifier">host_b</phrase><phrase role="special">,</phrase> <phrase role="special">*</phrase> <phrase role="identifier">host_c</phrase><phrase role="special">;</phrase>
    <phrase role="identifier">cudaHostAlloc</phrase><phrase role="special">(</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">host_a</phrase><phrase role="special">,</phrase> <phrase role="identifier">full_size</phrase> <phrase role="special">*</phrase> <phrase role="keyword">sizeof</phrase><phrase role="special">(</phrase> <phrase role="keyword">int</phrase><phrase role="special">),</phrase> <phrase role="identifier">cudaHostAllocDefault</phrase><phrase role="special">);</phrase>
    <phrase role="identifier">cudaHostAlloc</phrase><phrase role="special">(</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">host_b</phrase><phrase role="special">,</phrase> <phrase role="identifier">full_size</phrase> <phrase role="special">*</phrase> <phrase role="keyword">sizeof</phrase><phrase role="special">(</phrase> <phrase role="keyword">int</phrase><phrase role="special">),</phrase> <phrase role="identifier">cudaHostAllocDefault</phrase><phrase role="special">);</phrase>
    <phrase role="identifier">cudaHostAlloc</phrase><phrase role="special">(</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">host_c</phrase><phrase role="special">,</phrase> <phrase role="identifier">full_size</phrase> <phrase role="special">*</phrase> <phrase role="keyword">sizeof</phrase><phrase role="special">(</phrase> <phrase role="keyword">int</phrase><phrase role="special">),</phrase> <phrase role="identifier">cudaHostAllocDefault</phrase><phrase role="special">);</phrase>
    <phrase role="keyword">int</phrase> <phrase role="special">*</phrase> <phrase role="identifier">dev_a</phrase><phrase role="special">,</phrase> <phrase role="special">*</phrase> <phrase role="identifier">dev_b</phrase><phrase role="special">,</phrase> <phrase role="special">*</phrase> <phrase role="identifier">dev_c</phrase><phrase role="special">;</phrase>
    <phrase role="identifier">cudaMalloc</phrase><phrase role="special">(</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">dev_a</phrase><phrase role="special">,</phrase> <phrase role="identifier">size</phrase> <phrase role="special">*</phrase> <phrase role="keyword">sizeof</phrase><phrase role="special">(</phrase> <phrase role="keyword">int</phrase><phrase role="special">)</phrase> <phrase role="special">);</phrase>
    <phrase role="identifier">cudaMalloc</phrase><phrase role="special">(</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">dev_b</phrase><phrase role="special">,</phrase> <phrase role="identifier">size</phrase> <phrase role="special">*</phrase> <phrase role="keyword">sizeof</phrase><phrase role="special">(</phrase> <phrase role="keyword">int</phrase><phrase role="special">)</phrase> <phrase role="special">);</phrase>
    <phrase role="identifier">cudaMalloc</phrase><phrase role="special">(</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">dev_c</phrase><phrase role="special">,</phrase> <phrase role="identifier">size</phrase> <phrase role="special">*</phrase> <phrase role="keyword">sizeof</phrase><phrase role="special">(</phrase> <phrase role="keyword">int</phrase><phrase role="special">)</phrase> <phrase role="special">);</phrase>
    <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">minstd_rand</phrase> <phrase role="identifier">generator</phrase><phrase role="special">;</phrase>
    <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">uniform_int_distribution</phrase><phrase role="special">&lt;&gt;</phrase> <phrase role="identifier">distribution</phrase><phrase role="special">(</phrase><phrase role="number">1</phrase><phrase role="special">,</phrase> <phrase role="number">6</phrase><phrase role="special">);</phrase>
    <phrase role="keyword">for</phrase> <phrase role="special">(</phrase> <phrase role="keyword">int</phrase> <phrase role="identifier">i</phrase> <phrase role="special">=</phrase> <phrase role="number">0</phrase><phrase role="special">;</phrase> <phrase role="identifier">i</phrase> <phrase role="special">&lt;</phrase> <phrase role="identifier">full_size</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">host_a</phrase><phrase role="special">[</phrase><phrase role="identifier">i</phrase><phrase role="special">]</phrase> <phrase role="special">=</phrase> <phrase role="identifier">distribution</phrase><phrase role="special">(</phrase> <phrase role="identifier">generator</phrase><phrase role="special">);</phrase>
        <phrase role="identifier">host_b</phrase><phrase role="special">[</phrase><phrase role="identifier">i</phrase><phrase role="special">]</phrase> <phrase role="special">=</phrase> <phrase role="identifier">distribution</phrase><phrase role="special">(</phrase> <phrase role="identifier">generator</phrase><phrase role="special">);</phrase>
    <phrase role="special">}</phrase>
    <phrase role="keyword">for</phrase> <phrase role="special">(</phrase> <phrase role="keyword">int</phrase> <phrase role="identifier">i</phrase> <phrase role="special">=</phrase> <phrase role="number">0</phrase><phrase role="special">;</phrase> <phrase role="identifier">i</phrase> <phrase role="special">&lt;</phrase> <phrase role="identifier">full_size</phrase><phrase role="special">;</phrase> <phrase role="identifier">i</phrase> <phrase role="special">+=</phrase> <phrase role="identifier">size</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
        <phrase role="identifier">cudaMemcpyAsync</phrase><phrase role="special">(</phrase> <phrase role="identifier">dev_a</phrase><phrase role="special">,</phrase> <phrase role="identifier">host_a</phrase> <phrase role="special">+</phrase> <phrase role="identifier">i</phrase><phrase role="special">,</phrase> <phrase role="identifier">size</phrase> <phrase role="special">*</phrase> <phrase role="keyword">sizeof</phrase><phrase role="special">(</phrase> <phrase role="keyword">int</phrase><phrase role="special">),</phrase> <phrase role="identifier">cudaMemcpyHostToDevice</phrase><phrase role="special">,</phrase> <phrase role="identifier">stream</phrase><phrase role="special">);</phrase>
        <phrase role="identifier">cudaMemcpyAsync</phrase><phrase role="special">(</phrase> <phrase role="identifier">dev_b</phrase><phrase role="special">,</phrase> <phrase role="identifier">host_b</phrase> <phrase role="special">+</phrase> <phrase role="identifier">i</phrase><phrase role="special">,</phrase> <phrase role="identifier">size</phrase> <phrase role="special">*</phrase> <phrase role="keyword">sizeof</phrase><phrase role="special">(</phrase> <phrase role="keyword">int</phrase><phrase role="special">),</phrase> <phrase role="identifier">cudaMemcpyHostToDevice</phrase><phrase role="special">,</phrase> <phrase role="identifier">stream</phrase><phrase role="special">);</phrase>
        <phrase role="identifier">kernel</phrase><phrase role="special">&lt;&lt;&lt;</phrase> <phrase role="identifier">size</phrase> <phrase role="special">/</phrase> <phrase role="number">256</phrase><phrase role="special">,</phrase> <phrase role="number">256</phrase><phrase role="special">,</phrase> <phrase role="number">0</phrase><phrase role="special">,</phrase> <phrase role="identifier">stream</phrase> <phrase role="special">&gt;&gt;&gt;(</phrase> <phrase role="identifier">size</phrase><phrase role="special">,</phrase> <phrase role="identifier">dev_a</phrase><phrase role="special">,</phrase> <phrase role="identifier">dev_b</phrase><phrase role="special">,</phrase> <phrase role="identifier">dev_c</phrase><phrase role="special">);</phrase>
        <phrase role="identifier">cudaMemcpyAsync</phrase><phrase role="special">(</phrase> <phrase role="identifier">host_c</phrase> <phrase role="special">+</phrase> <phrase role="identifier">i</phrase><phrase role="special">,</phrase> <phrase role="identifier">dev_c</phrase><phrase role="special">,</phrase> <phrase role="identifier">size</phrase> <phrase role="special">*</phrase> <phrase role="keyword">sizeof</phrase><phrase role="special">(</phrase> <phrase role="keyword">int</phrase><phrase role="special">),</phrase> <phrase role="identifier">cudaMemcpyDeviceToHost</phrase><phrase role="special">,</phrase> <phrase role="identifier">stream</phrase><phrase role="special">);</phrase>
    <phrase role="special">}</phrase>
    <phrase role="keyword">auto</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">cuda</phrase><phrase role="special">::</phrase><phrase role="identifier">waitfor_all</phrase><phrase role="special">(</phrase> <phrase role="identifier">stream</phrase><phrase role="special">);</phrase> <phrase role="comment">// suspend fiber till CUDA stream has finished</phrase>
    <phrase role="identifier">BOOST_ASSERT</phrase><phrase role="special">(</phrase> <phrase role="identifier">stream</phrase> <phrase role="special">==</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">get</phrase><phrase role="special">&lt;</phrase> <phrase role="number">0</phrase> <phrase role="special">&gt;(</phrase> <phrase role="identifier">result</phrase><phrase role="special">)</phrase> <phrase role="special">);</phrase>
    <phrase role="identifier">BOOST_ASSERT</phrase><phrase role="special">(</phrase> <phrase role="identifier">cudaSuccess</phrase> <phrase role="special">==</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">get</phrase><phrase role="special">&lt;</phrase> <phrase role="number">1</phrase> <phrase role="special">&gt;(</phrase> <phrase role="identifier">result</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;f1: GPU computation finished&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">cudaFreeHost</phrase><phrase role="special">(</phrase> <phrase role="identifier">host_a</phrase><phrase role="special">);</phrase>
    <phrase role="identifier">cudaFreeHost</phrase><phrase role="special">(</phrase> <phrase role="identifier">host_b</phrase><phrase role="special">);</phrase>
    <phrase role="identifier">cudaFreeHost</phrase><phrase role="special">(</phrase> <phrase role="identifier">host_c</phrase><phrase role="special">);</phrase>
    <phrase role="identifier">cudaFree</phrase><phrase role="special">(</phrase> <phrase role="identifier">dev_a</phrase><phrase role="special">);</phrase>
    <phrase role="identifier">cudaFree</phrase><phrase role="special">(</phrase> <phrase role="identifier">dev_b</phrase><phrase role="special">);</phrase>
    <phrase role="identifier">cudaFree</phrase><phrase role="special">(</phrase> <phrase role="identifier">dev_c</phrase><phrase role="special">);</phrase>
    <phrase role="identifier">cudaStreamDestroy</phrase><phrase role="special">(</phrase> <phrase role="identifier">stream</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>
      <bridgehead renderas="sect4" id="fiber.gpu_computing.cuda.h1">
        <phrase id="fiber.gpu_computing.cuda.synopsis"/><link linkend="fiber.gpu_computing.cuda.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">cuda</phrase><phrase role="special">/</phrase><phrase role="identifier">waitfor</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">namespace</phrase> <phrase role="identifier">cuda</phrase> <phrase role="special">{</phrase>

<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">tuple</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">cudaStream_t</phrase><phrase role="special">,</phrase> <phrase role="identifier">cudaError_t</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">waitfor_all</phrase><phrase role="special">(</phrase> <phrase role="identifier">cudaStream_t</phrase> <phrase role="identifier">st</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">tuple</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">cudaStream_t</phrase><phrase role="special">,</phrase> <phrase role="identifier">cudaError_t</phrase> <phrase role="special">&gt;</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">waitfor_all</phrase><phrase role="special">(</phrase> <phrase role="identifier">cudaStream_t</phrase> <phrase role="special">...</phrase> <phrase role="identifier">st</phrase><phrase role="special">);</phrase>

<phrase role="special">}}}</phrase>
</programlisting>
      <para>
        <bridgehead renderas="sect4" id="cuda_waitfor_bridgehead">
  <phrase id="cuda_waitfor"/>
  <link linkend="cuda_waitfor">Non-member function <code>cuda::waitfor()</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">cuda</phrase><phrase role="special">/</phrase><phrase role="identifier">waitfor</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">namespace</phrase> <phrase role="identifier">cuda</phrase> <phrase role="special">{</phrase>

<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">tuple</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">cudaStream_t</phrase><phrase role="special">,</phrase> <phrase role="identifier">cudaError_t</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">waitfor_all</phrase><phrase role="special">(</phrase> <phrase role="identifier">cudaStream_t</phrase> <phrase role="identifier">st</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">tuple</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">cudaStream_t</phrase><phrase role="special">,</phrase> <phrase role="identifier">cudaError_t</phrase> <phrase role="special">&gt;</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">waitfor_all</phrase><phrase role="special">(</phrase> <phrase role="identifier">cudaStream_t</phrase> <phrase role="special">...</phrase> <phrase role="identifier">st</phrase><phrase role="special">);</phrase>

<phrase role="special">}}}</phrase>
</programlisting>
      <variablelist>
        <title></title>
        <varlistentry>
          <term>Effects:</term>
          <listitem>
            <para>
              Suspends active fiber till CUDA stream has finished its operations.
            </para>
          </listitem>
        </varlistentry>
        <varlistentry>
          <term>Returns:</term>
          <listitem>
            <para>
              tuple of stream reference and the CUDA stream status
            </para>
          </listitem>
        </varlistentry>
      </variablelist>
    </section>
    <section id="fiber.gpu_computing.hip">
      <title><anchor id="hip"/><link linkend="fiber.gpu_computing.hip">ROCm/HIP</link></title>
      <para>
        <ulink url="http://github.com/ROCm-Developer-Tools/HIP/tree/roc-1.6.0/">HIP</ulink>
        is part of the <ulink url="http://rocm.github.io/">ROC (Radeon Open Compute)</ulink>
        platform for parallel computing on AMD and NVIDIA GPUs. The application programming
        interface of HIP gives access to GPU's instruction set and computation resources
        (Execution of compute kernels).
      </para>
      <bridgehead renderas="sect4" id="fiber.gpu_computing.hip.h0">
        <phrase id="fiber.gpu_computing.hip.synchronization_with_rocm_hip_streams"/><link
        linkend="fiber.gpu_computing.hip.synchronization_with_rocm_hip_streams">Synchronization
        with ROCm/HIP streams</link>
      </bridgehead>
      <para>
        HIP operation such as compute kernels or memory transfer (between host and
        device) can be grouped/queued by HIP streams. are executed on the GPUs. Boost.Fiber
        enables a fiber to sleep (suspend) till a HIP stream has completed its operations.
        This enables applications to run other fibers on the CPU without the need
        to spawn an additional OS-threads. And resume the fiber when the HIP streams
        has finished.
      </para>
<programlisting><phrase role="identifier">__global__</phrase>
<phrase role="keyword">void</phrase> <phrase role="identifier">kernel</phrase><phrase role="special">(</phrase> <phrase role="keyword">int</phrase> <phrase role="identifier">size</phrase><phrase role="special">,</phrase> <phrase role="keyword">int</phrase> <phrase role="special">*</phrase> <phrase role="identifier">a</phrase><phrase role="special">,</phrase> <phrase role="keyword">int</phrase> <phrase role="special">*</phrase> <phrase role="identifier">b</phrase><phrase role="special">,</phrase> <phrase role="keyword">int</phrase> <phrase role="special">*</phrase> <phrase role="identifier">c</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
    <phrase role="keyword">int</phrase> <phrase role="identifier">idx</phrase> <phrase role="special">=</phrase> <phrase role="identifier">threadIdx</phrase><phrase role="special">.</phrase><phrase role="identifier">x</phrase> <phrase role="special">+</phrase> <phrase role="identifier">blockIdx</phrase><phrase role="special">.</phrase><phrase role="identifier">x</phrase> <phrase role="special">*</phrase> <phrase role="identifier">blockDim</phrase><phrase role="special">.</phrase><phrase role="identifier">x</phrase><phrase role="special">;</phrase>
    <phrase role="keyword">if</phrase> <phrase role="special">(</phrase> <phrase role="identifier">idx</phrase> <phrase role="special">&lt;</phrase> <phrase role="identifier">size</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
        <phrase role="keyword">int</phrase> <phrase role="identifier">idx1</phrase> <phrase role="special">=</phrase> <phrase role="special">(</phrase><phrase role="identifier">idx</phrase> <phrase role="special">+</phrase> <phrase role="number">1</phrase><phrase role="special">)</phrase> <phrase role="special">%</phrase> <phrase role="number">256</phrase><phrase role="special">;</phrase>
        <phrase role="keyword">int</phrase> <phrase role="identifier">idx2</phrase> <phrase role="special">=</phrase> <phrase role="special">(</phrase><phrase role="identifier">idx</phrase> <phrase role="special">+</phrase> <phrase role="number">2</phrase><phrase role="special">)</phrase> <phrase role="special">%</phrase> <phrase role="number">256</phrase><phrase role="special">;</phrase>
        <phrase role="keyword">float</phrase> <phrase role="identifier">as</phrase> <phrase role="special">=</phrase> <phrase role="special">(</phrase><phrase role="identifier">a</phrase><phrase role="special">[</phrase><phrase role="identifier">idx</phrase><phrase role="special">]</phrase> <phrase role="special">+</phrase> <phrase role="identifier">a</phrase><phrase role="special">[</phrase><phrase role="identifier">idx1</phrase><phrase role="special">]</phrase> <phrase role="special">+</phrase> <phrase role="identifier">a</phrase><phrase role="special">[</phrase><phrase role="identifier">idx2</phrase><phrase role="special">])</phrase> <phrase role="special">/</phrase> <phrase role="number">3.0f</phrase><phrase role="special">;</phrase>
        <phrase role="keyword">float</phrase> <phrase role="identifier">bs</phrase> <phrase role="special">=</phrase> <phrase role="special">(</phrase><phrase role="identifier">b</phrase><phrase role="special">[</phrase><phrase role="identifier">idx</phrase><phrase role="special">]</phrase> <phrase role="special">+</phrase> <phrase role="identifier">b</phrase><phrase role="special">[</phrase><phrase role="identifier">idx1</phrase><phrase role="special">]</phrase> <phrase role="special">+</phrase> <phrase role="identifier">b</phrase><phrase role="special">[</phrase><phrase role="identifier">idx2</phrase><phrase role="special">])</phrase> <phrase role="special">/</phrase> <phrase role="number">3.0f</phrase><phrase role="special">;</phrase>
        <phrase role="identifier">c</phrase><phrase role="special">[</phrase><phrase role="identifier">idx</phrase><phrase role="special">]</phrase> <phrase role="special">=</phrase> <phrase role="special">(</phrase><phrase role="identifier">as</phrase> <phrase role="special">+</phrase> <phrase role="identifier">bs</phrase><phrase role="special">)</phrase> <phrase role="special">/</phrase> <phrase role="number">2</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">([&amp;</phrase><phrase role="identifier">done</phrase><phrase role="special">]{</phrase>
    <phrase role="identifier">hipStream_t</phrase> <phrase role="identifier">stream</phrase><phrase role="special">;</phrase>
    <phrase role="identifier">hipStreamCreate</phrase><phrase role="special">(</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">stream</phrase><phrase role="special">);</phrase>
    <phrase role="keyword">int</phrase> <phrase role="identifier">size</phrase> <phrase role="special">=</phrase> <phrase role="number">1024</phrase> <phrase role="special">*</phrase> <phrase role="number">1024</phrase><phrase role="special">;</phrase>
    <phrase role="keyword">int</phrase> <phrase role="identifier">full_size</phrase> <phrase role="special">=</phrase> <phrase role="number">20</phrase> <phrase role="special">*</phrase> <phrase role="identifier">size</phrase><phrase role="special">;</phrase>
    <phrase role="keyword">int</phrase> <phrase role="special">*</phrase> <phrase role="identifier">host_a</phrase><phrase role="special">,</phrase> <phrase role="special">*</phrase> <phrase role="identifier">host_b</phrase><phrase role="special">,</phrase> <phrase role="special">*</phrase> <phrase role="identifier">host_c</phrase><phrase role="special">;</phrase>
    <phrase role="identifier">hipHostMalloc</phrase><phrase role="special">(</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">host_a</phrase><phrase role="special">,</phrase> <phrase role="identifier">full_size</phrase> <phrase role="special">*</phrase> <phrase role="keyword">sizeof</phrase><phrase role="special">(</phrase> <phrase role="keyword">int</phrase><phrase role="special">),</phrase> <phrase role="identifier">hipHostMallocDefault</phrase><phrase role="special">);</phrase>
    <phrase role="identifier">hipHostMalloc</phrase><phrase role="special">(</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">host_b</phrase><phrase role="special">,</phrase> <phrase role="identifier">full_size</phrase> <phrase role="special">*</phrase> <phrase role="keyword">sizeof</phrase><phrase role="special">(</phrase> <phrase role="keyword">int</phrase><phrase role="special">),</phrase> <phrase role="identifier">hipHostMallocDefault</phrase><phrase role="special">);</phrase>
    <phrase role="identifier">hipHostMalloc</phrase><phrase role="special">(</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">host_c</phrase><phrase role="special">,</phrase> <phrase role="identifier">full_size</phrase> <phrase role="special">*</phrase> <phrase role="keyword">sizeof</phrase><phrase role="special">(</phrase> <phrase role="keyword">int</phrase><phrase role="special">),</phrase> <phrase role="identifier">hipHostMallocDefault</phrase><phrase role="special">);</phrase>
    <phrase role="keyword">int</phrase> <phrase role="special">*</phrase> <phrase role="identifier">dev_a</phrase><phrase role="special">,</phrase> <phrase role="special">*</phrase> <phrase role="identifier">dev_b</phrase><phrase role="special">,</phrase> <phrase role="special">*</phrase> <phrase role="identifier">dev_c</phrase><phrase role="special">;</phrase>
    <phrase role="identifier">hipMalloc</phrase><phrase role="special">(</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">dev_a</phrase><phrase role="special">,</phrase> <phrase role="identifier">size</phrase> <phrase role="special">*</phrase> <phrase role="keyword">sizeof</phrase><phrase role="special">(</phrase> <phrase role="keyword">int</phrase><phrase role="special">)</phrase> <phrase role="special">);</phrase>
    <phrase role="identifier">hipMalloc</phrase><phrase role="special">(</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">dev_b</phrase><phrase role="special">,</phrase> <phrase role="identifier">size</phrase> <phrase role="special">*</phrase> <phrase role="keyword">sizeof</phrase><phrase role="special">(</phrase> <phrase role="keyword">int</phrase><phrase role="special">)</phrase> <phrase role="special">);</phrase>
    <phrase role="identifier">hipMalloc</phrase><phrase role="special">(</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">dev_c</phrase><phrase role="special">,</phrase> <phrase role="identifier">size</phrase> <phrase role="special">*</phrase> <phrase role="keyword">sizeof</phrase><phrase role="special">(</phrase> <phrase role="keyword">int</phrase><phrase role="special">)</phrase> <phrase role="special">);</phrase>
    <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">minstd_rand</phrase> <phrase role="identifier">generator</phrase><phrase role="special">;</phrase>
    <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">uniform_int_distribution</phrase><phrase role="special">&lt;&gt;</phrase> <phrase role="identifier">distribution</phrase><phrase role="special">(</phrase><phrase role="number">1</phrase><phrase role="special">,</phrase> <phrase role="number">6</phrase><phrase role="special">);</phrase>
    <phrase role="keyword">for</phrase> <phrase role="special">(</phrase> <phrase role="keyword">int</phrase> <phrase role="identifier">i</phrase> <phrase role="special">=</phrase> <phrase role="number">0</phrase><phrase role="special">;</phrase> <phrase role="identifier">i</phrase> <phrase role="special">&lt;</phrase> <phrase role="identifier">full_size</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">host_a</phrase><phrase role="special">[</phrase><phrase role="identifier">i</phrase><phrase role="special">]</phrase> <phrase role="special">=</phrase> <phrase role="identifier">distribution</phrase><phrase role="special">(</phrase> <phrase role="identifier">generator</phrase><phrase role="special">);</phrase>
        <phrase role="identifier">host_b</phrase><phrase role="special">[</phrase><phrase role="identifier">i</phrase><phrase role="special">]</phrase> <phrase role="special">=</phrase> <phrase role="identifier">distribution</phrase><phrase role="special">(</phrase> <phrase role="identifier">generator</phrase><phrase role="special">);</phrase>
    <phrase role="special">}</phrase>
    <phrase role="keyword">for</phrase> <phrase role="special">(</phrase> <phrase role="keyword">int</phrase> <phrase role="identifier">i</phrase> <phrase role="special">=</phrase> <phrase role="number">0</phrase><phrase role="special">;</phrase> <phrase role="identifier">i</phrase> <phrase role="special">&lt;</phrase> <phrase role="identifier">full_size</phrase><phrase role="special">;</phrase> <phrase role="identifier">i</phrase> <phrase role="special">+=</phrase> <phrase role="identifier">size</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
        <phrase role="identifier">hipMemcpyAsync</phrase><phrase role="special">(</phrase> <phrase role="identifier">dev_a</phrase><phrase role="special">,</phrase> <phrase role="identifier">host_a</phrase> <phrase role="special">+</phrase> <phrase role="identifier">i</phrase><phrase role="special">,</phrase> <phrase role="identifier">size</phrase> <phrase role="special">*</phrase> <phrase role="keyword">sizeof</phrase><phrase role="special">(</phrase> <phrase role="keyword">int</phrase><phrase role="special">),</phrase> <phrase role="identifier">hipMemcpyHostToDevice</phrase><phrase role="special">,</phrase> <phrase role="identifier">stream</phrase><phrase role="special">);</phrase>
        <phrase role="identifier">hipMemcpyAsync</phrase><phrase role="special">(</phrase> <phrase role="identifier">dev_b</phrase><phrase role="special">,</phrase> <phrase role="identifier">host_b</phrase> <phrase role="special">+</phrase> <phrase role="identifier">i</phrase><phrase role="special">,</phrase> <phrase role="identifier">size</phrase> <phrase role="special">*</phrase> <phrase role="keyword">sizeof</phrase><phrase role="special">(</phrase> <phrase role="keyword">int</phrase><phrase role="special">),</phrase> <phrase role="identifier">hipMemcpyHostToDevice</phrase><phrase role="special">,</phrase> <phrase role="identifier">stream</phrase><phrase role="special">);</phrase>
        <phrase role="identifier">hipLaunchKernel</phrase><phrase role="special">(</phrase><phrase role="identifier">kernel</phrase><phrase role="special">,</phrase> <phrase role="identifier">dim3</phrase><phrase role="special">(</phrase><phrase role="identifier">size</phrase> <phrase role="special">/</phrase> <phrase role="number">256</phrase><phrase role="special">),</phrase> <phrase role="identifier">dim3</phrase><phrase role="special">(</phrase><phrase role="number">256</phrase><phrase role="special">),</phrase> <phrase role="number">0</phrase><phrase role="special">,</phrase> <phrase role="identifier">stream</phrase><phrase role="special">,</phrase> <phrase role="identifier">size</phrase><phrase role="special">,</phrase> <phrase role="identifier">dev_a</phrase><phrase role="special">,</phrase> <phrase role="identifier">dev_b</phrase><phrase role="special">,</phrase> <phrase role="identifier">dev_c</phrase><phrase role="special">);</phrase>
        <phrase role="identifier">hipMemcpyAsync</phrase><phrase role="special">(</phrase> <phrase role="identifier">host_c</phrase> <phrase role="special">+</phrase> <phrase role="identifier">i</phrase><phrase role="special">,</phrase> <phrase role="identifier">dev_c</phrase><phrase role="special">,</phrase> <phrase role="identifier">size</phrase> <phrase role="special">*</phrase> <phrase role="keyword">sizeof</phrase><phrase role="special">(</phrase> <phrase role="keyword">int</phrase><phrase role="special">),</phrase> <phrase role="identifier">hipMemcpyDeviceToHost</phrase><phrase role="special">,</phrase> <phrase role="identifier">stream</phrase><phrase role="special">);</phrase>
    <phrase role="special">}</phrase>
    <phrase role="keyword">auto</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">hip</phrase><phrase role="special">::</phrase><phrase role="identifier">waitfor_all</phrase><phrase role="special">(</phrase> <phrase role="identifier">stream</phrase><phrase role="special">);</phrase> <phrase role="comment">// suspend fiber till HIP stream has finished</phrase>
    <phrase role="identifier">BOOST_ASSERT</phrase><phrase role="special">(</phrase> <phrase role="identifier">stream</phrase> <phrase role="special">==</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">get</phrase><phrase role="special">&lt;</phrase> <phrase role="number">0</phrase> <phrase role="special">&gt;(</phrase> <phrase role="identifier">result</phrase><phrase role="special">)</phrase> <phrase role="special">);</phrase>
    <phrase role="identifier">BOOST_ASSERT</phrase><phrase role="special">(</phrase> <phrase role="identifier">hipSuccess</phrase> <phrase role="special">==</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">get</phrase><phrase role="special">&lt;</phrase> <phrase role="number">1</phrase> <phrase role="special">&gt;(</phrase> <phrase role="identifier">result</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;f1: GPU computation finished&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">hipHostFree</phrase><phrase role="special">(</phrase> <phrase role="identifier">host_a</phrase><phrase role="special">);</phrase>
    <phrase role="identifier">hipHostFree</phrase><phrase role="special">(</phrase> <phrase role="identifier">host_b</phrase><phrase role="special">);</phrase>
    <phrase role="identifier">hipHostFree</phrase><phrase role="special">(</phrase> <phrase role="identifier">host_c</phrase><phrase role="special">);</phrase>
    <phrase role="identifier">hipFree</phrase><phrase role="special">(</phrase> <phrase role="identifier">dev_a</phrase><phrase role="special">);</phrase>
    <phrase role="identifier">hipFree</phrase><phrase role="special">(</phrase> <phrase role="identifier">dev_b</phrase><phrase role="special">);</phrase>
    <phrase role="identifier">hipFree</phrase><phrase role="special">(</phrase> <phrase role="identifier">dev_c</phrase><phrase role="special">);</phrase>
    <phrase role="identifier">hipStreamDestroy</phrase><phrase role="special">(</phrase> <phrase role="identifier">stream</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>
      <bridgehead renderas="sect4" id="fiber.gpu_computing.hip.h1">
        <phrase id="fiber.gpu_computing.hip.synopsis"/><link linkend="fiber.gpu_computing.hip.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">hip</phrase><phrase role="special">/</phrase><phrase role="identifier">waitfor</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">namespace</phrase> <phrase role="identifier">hip</phrase> <phrase role="special">{</phrase>

<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">tuple</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">hipStream_t</phrase><phrase role="special">,</phrase> <phrase role="identifier">hipError_t</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">waitfor_all</phrase><phrase role="special">(</phrase> <phrase role="identifier">hipStream_t</phrase> <phrase role="identifier">st</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">tuple</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">hipStream_t</phrase><phrase role="special">,</phrase> <phrase role="identifier">hipError_t</phrase> <phrase role="special">&gt;</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">waitfor_all</phrase><phrase role="special">(</phrase> <phrase role="identifier">hipStream_t</phrase> <phrase role="special">...</phrase> <phrase role="identifier">st</phrase><phrase role="special">);</phrase>

<phrase role="special">}}}</phrase>
</programlisting>
      <para>
        <bridgehead renderas="sect4" id="hip_waitfor_bridgehead">
  <phrase id="hip_waitfor"/>
  <link linkend="hip_waitfor">Non-member function <code>hip::waitfor()</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">hip</phrase><phrase role="special">/</phrase><phrase role="identifier">waitfor</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">namespace</phrase> <phrase role="identifier">hip</phrase> <phrase role="special">{</phrase>

<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">tuple</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">hipStream_t</phrase><phrase role="special">,</phrase> <phrase role="identifier">hipError_t</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">waitfor_all</phrase><phrase role="special">(</phrase> <phrase role="identifier">hipStream_t</phrase> <phrase role="identifier">st</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">tuple</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">hipStream_t</phrase><phrase role="special">,</phrase> <phrase role="identifier">hipError_t</phrase> <phrase role="special">&gt;</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">waitfor_all</phrase><phrase role="special">(</phrase> <phrase role="identifier">hipStream_t</phrase> <phrase role="special">...</phrase> <phrase role="identifier">st</phrase><phrase role="special">);</phrase>

<phrase role="special">}}}</phrase>
</programlisting>
      <variablelist>
        <title></title>
        <varlistentry>
          <term>Effects:</term>
          <listitem>
            <para>
              Suspends active fiber till HIP stream has finished its operations.
            </para>
          </listitem>
        </varlistentry>
        <varlistentry>
          <term>Returns:</term>
          <listitem>
            <para>
              tuple of stream reference and the HIP stream status
            </para>
          </listitem>
        </varlistentry>
      </variablelist>
    </section>
  </section>
  <section id="fiber.worker">
    <title><anchor id="worker"/><link linkend="fiber.worker">Running with worker
    threads</link></title>
    <bridgehead renderas="sect3" id="fiber.worker.h0">
      <phrase id="fiber.worker.keep_workers_running"/><link linkend="fiber.worker.keep_workers_running">Keep
      workers running</link>
    </bridgehead>
    <para>
      If a worker thread is used but no fiber is created or parts of the framework
      (like <link linkend="this_fiber_yield"><code>this_fiber::yield()</code></link>) are touched, then no fiber scheduler
      is instantiated.
    </para>
<programlisting><phrase role="keyword">auto</phrase> <phrase role="identifier">worker</phrase> <phrase role="special">=</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">thread</phrase><phrase role="special">(</phrase>
        <phrase role="special">[]{</phrase>
            <phrase role="comment">// fiber scheduler not instantiated</phrase>
        <phrase role="special">});</phrase>
<phrase role="identifier">worker</phrase><phrase role="special">.</phrase><phrase role="identifier">join</phrase><phrase role="special">();</phrase>
</programlisting>
    <para>
      If <emphasis>use_scheduling_algorithm&lt;&gt;()</emphasis> is invoked, the
      fiber scheduler is created. If the worker thread simply returns, destroys the
      scheduler and terminates.
    </para>
<programlisting><phrase role="keyword">auto</phrase> <phrase role="identifier">worker</phrase> <phrase role="special">=</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">thread</phrase><phrase role="special">(</phrase>
        <phrase role="special">[]{</phrase>
            <phrase role="comment">// fiber scheduler created</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="identifier">worker</phrase><phrase role="special">.</phrase><phrase role="identifier">join</phrase><phrase role="special">();</phrase>
</programlisting>
    <para>
      In order to keep the worker thread running, the fiber associated with the thread
      stack (which is called <quote>main</quote> fiber) is blocked. For instance
      the <quote>main</quote> fiber might wait on a <link linkend="class_condition_variable"><code>condition_variable</code></link>.
      For a gracefully shutdown <link linkend="class_condition_variable"><code>condition_variable</code></link> is signalled
      and the <quote>main</quote> fiber returns. The scheduler gets destructed if
      all fibers of the worker thread have been terminated.
    </para>
<programlisting><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="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">condition_variable_any</phrase> <phrase role="identifier">cv</phrase><phrase role="special">;</phrase>
<phrase role="keyword">auto</phrase> <phrase role="identifier">worker</phrase> <phrase role="special">=</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">thread</phrase><phrase role="special">(</phrase>
        <phrase role="special">[&amp;</phrase><phrase role="identifier">mtx</phrase><phrase role="special">,&amp;</phrase><phrase role="identifier">cv</phrase><phrase role="special">]{</phrase>
            <phrase role="identifier">mtx</phrase><phrase role="special">.</phrase><phrase role="identifier">lock</phrase><phrase role="special">();</phrase>
            <phrase role="comment">// suspend till signalled</phrase>
            <phrase role="identifier">cv</phrase><phrase role="special">.</phrase><phrase role="identifier">wait</phrase><phrase role="special">(</phrase><phrase role="identifier">mtx</phrase><phrase role="special">);</phrase>
            <phrase role="identifier">mtx</phrase><phrase role="special">.</phrase><phrase role="identifier">unlock</phrase><phrase role="special">();</phrase>
        <phrase role="special">});</phrase>
<phrase role="comment">// signal termination</phrase>
<phrase role="identifier">cv</phrase><phrase role="special">.</phrase><phrase role="identifier">notify_all</phrase><phrase role="special">();</phrase>
<phrase role="identifier">worker</phrase><phrase role="special">.</phrase><phrase role="identifier">join</phrase><phrase role="special">();</phrase>
</programlisting>
    <bridgehead renderas="sect3" id="fiber.worker.h1">
      <phrase id="fiber.worker.processing_tasks"/><link linkend="fiber.worker.processing_tasks">Processing
      tasks</link>
    </bridgehead>
    <para>
      Tasks can be transferred via channels. The worker thread runs a pool of fibers
      that dequeue and executed tasks from the channel. The termination is signalled
      via closing the channel.
    </para>
<programlisting><phrase role="keyword">using</phrase> <phrase role="identifier">task</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">()&gt;;</phrase>
<phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">buffered_channel</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">task</phrase><phrase role="special">&gt;</phrase> <phrase role="identifier">ch</phrase><phrase role="special">{</phrase><phrase role="number">1024</phrase><phrase role="special">};</phrase>
<phrase role="keyword">auto</phrase> <phrase role="identifier">worker</phrase> <phrase role="special">=</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">thread</phrase><phrase role="special">(</phrase>
        <phrase role="special">[&amp;</phrase><phrase role="identifier">ch</phrase><phrase role="special">]{</phrase>
            <phrase role="comment">// create pool of fibers</phrase>
            <phrase role="keyword">for</phrase> <phrase role="special">(</phrase><phrase role="keyword">int</phrase> <phrase role="identifier">i</phrase><phrase role="special">=</phrase><phrase role="number">0</phrase><phrase role="special">;</phrase> <phrase role="identifier">i</phrase><phrase role="special">&lt;</phrase><phrase role="number">10</phrase><phrase role="special">;</phrase> <phrase role="special">++</phrase><phrase role="identifier">i</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
                <phrase role="identifier">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">[&amp;</phrase><phrase role="identifier">ch</phrase><phrase role="special">]{</phrase>
                        <phrase role="identifier">task</phrase> <phrase role="identifier">tsk</phrase><phrase role="special">;</phrase>
                        <phrase role="comment">// dequeue and process tasks</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">closed</phrase><phrase role="special">!=</phrase><phrase role="identifier">ch</phrase><phrase role="special">.</phrase><phrase role="identifier">pop</phrase><phrase role="special">(</phrase><phrase role="identifier">tsk</phrase><phrase role="special">)){</phrase>
                            <phrase role="identifier">tsk</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>
            <phrase role="identifier">task</phrase> <phrase role="identifier">tsk</phrase><phrase role="special">;</phrase>
            <phrase role="comment">// dequeue and process tasks</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">closed</phrase><phrase role="special">!=</phrase><phrase role="identifier">ch</phrase><phrase role="special">.</phrase><phrase role="identifier">pop</phrase><phrase role="special">(</phrase><phrase role="identifier">tsk</phrase><phrase role="special">)){</phrase>
                <phrase role="identifier">tsk</phrase><phrase role="special">();</phrase>
            <phrase role="special">}</phrase>
        <phrase role="special">});</phrase>
<phrase role="comment">// feed channel with tasks</phrase>
<phrase role="identifier">ch</phrase><phrase role="special">.</phrase><phrase role="identifier">push</phrase><phrase role="special">([]{</phrase> <phrase role="special">...</phrase> <phrase role="special">});</phrase>
<phrase role="special">...</phrase>
<phrase role="comment">// signal termination</phrase>
<phrase role="identifier">ch</phrase><phrase role="special">.</phrase><phrase role="identifier">close</phrase><phrase role="special">();</phrase>
<phrase role="identifier">worker</phrase><phrase role="special">.</phrase><phrase role="identifier">join</phrase><phrase role="special">();</phrase>
</programlisting>
    <para>
      An alternative is to use a work-stealing scheduler. This kind of scheduling
      algorithm a worker thread steals fibers from the ready-queue of other worker
      threads if its own ready-queue is empty.
    </para>
    <note>
      <para>
        Wait till all worker threads have registered the work-stealing scheduling
        algorithm.
      </para>
    </note>
<programlisting><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="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">condition_variable_any</phrase> <phrase role="identifier">cv</phrase><phrase role="special">;</phrase>
<phrase role="comment">// start wotrker-thread first</phrase>
<phrase role="keyword">auto</phrase> <phrase role="identifier">worker</phrase> <phrase role="special">=</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">thread</phrase><phrase role="special">(</phrase>
        <phrase role="special">[&amp;</phrase><phrase role="identifier">mtx</phrase><phrase role="special">,&amp;</phrase><phrase role="identifier">cv</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">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">algo</phrase><phrase role="special">::</phrase><phrase role="identifier">work_stealing</phrase><phrase role="special">&gt;(</phrase><phrase role="number">2</phrase><phrase role="special">);</phrase>
            <phrase role="identifier">mtx</phrase><phrase role="special">.</phrase><phrase role="identifier">lock</phrase><phrase role="special">();</phrase>
            <phrase role="comment">// suspend main-fiber from the worker thread</phrase>
            <phrase role="identifier">cv</phrase><phrase role="special">.</phrase><phrase role="identifier">wait</phrase><phrase role="special">(</phrase><phrase role="identifier">mtx</phrase><phrase role="special">);</phrase>
            <phrase role="identifier">mtx</phrase><phrase role="special">.</phrase><phrase role="identifier">unlock</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">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">algo</phrase><phrase role="special">::</phrase><phrase role="identifier">work_stealing</phrase><phrase role="special">&gt;(</phrase><phrase role="number">2</phrase><phrase role="special">);</phrase>
<phrase role="comment">// create fibers with tasks</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="special">...</phrase> <phrase role="special">}};</phrase>
<phrase role="special">...</phrase>
<phrase role="comment">// signal termination</phrase>
<phrase role="identifier">cv</phrase><phrase role="special">.</phrase><phrase role="identifier">notify_all</phrase><phrase role="special">();</phrase>
<phrase role="identifier">worker</phrase><phrase role="special">.</phrase><phrase role="identifier">join</phrase><phrase role="special">();</phrase>
</programlisting>
    <important>
      <para>
        Because the TIB (thread information block on Windows) is not fully described
        in the MSDN, it might be possible that not all required TIB-parts are swapped.
        Using WinFiber implementation might be an alternative (see documentation
        about <ulink url="http://www.boost.org/doc/libs/1_65_1/libs/context/doc/html/context/cc/implementations__fcontext_t__ucontext_t_and_winfiber.html"><emphasis>implementations
        fcontext_t, ucontext_t and WinFiber of boost.context</emphasis></ulink>).
      </para>
    </important>
  </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 with gcc-6.3.1, using build
      options: variant = release, optimization = speed. Tests were executed on dual
      Intel XEON E5 2620v4 2.2GHz, 16C/32T, 64GB RAM, running Linux (x86_64).
    </para>
    <para>
      Measurements headed 1C/1T were run in a single-threaded process.
    </para>
    <para>
      The <ulink url="https://github.com/atemerev/skynet">microbenchmark <emphasis>syknet</emphasis></ulink>
      from Alexander Temerev was ported and used for performance measurements. At
      the root the test spawns 10 threads-of-execution (ToE), e.g. actor/goroutine/fiber
      etc.. Each spawned ToE spawns additional 10 ToEs ... until <emphasis role="bold">1,000,000</emphasis>
      ToEs are created. ToEs return back their ordinal numbers (0 ... 999,999), which
      are summed on the previous level and sent back upstream, until reaching the
      root. The test was run 10-20 times, producing a range of values for each measurement.
    </para>
    <table frame="all" id="fiber.performance.time_per_actor_erlang_process_goroutine__other_languages___average_over_1_000_000_">
      <title>time per actor/erlang process/goroutine (other languages) (average over
      1,000,000)</title>
      <tgroup cols="3">
        <thead>
          <row>
            <entry>
              <para>
                Haskell | stack-1.4.0/ghc-8.0.1
              </para>
            </entry>
            <entry>
              <para>
                Go | go1.8.1
              </para>
            </entry>
            <entry>
              <para>
                Erlang | erts-8.3
              </para>
            </entry>
          </row>
        </thead>
        <tbody>
          <row>
            <entry>
              <para>
                0.05 &#xb5;s - 0.06 &#xb5;s
              </para>
            </entry>
            <entry>
              <para>
                0.42 &#xb5;s - 0.49 &#xb5;s
              </para>
            </entry>
            <entry>
              <para>
                0.63 &#xb5;s - 0.73 &#xb5;s
              </para>
            </entry>
          </row>
        </tbody>
      </tgroup>
    </table>
    <para>
      Pthreads are created with a stack size of 8kB while <code><phrase role="identifier">std</phrase><phrase
      role="special">::</phrase><phrase role="identifier">thread</phrase></code>'s
      use the system default (1MB - 2MB). The microbenchmark could <emphasis role="bold">not</emphasis>
      be <emphasis role="bold">run</emphasis> with 1,000,000 threads because of
      <emphasis role="bold">resource exhaustion</emphasis> (pthread and std::thread).
      Instead the test runs only at <emphasis role="bold">10,000</emphasis> threads.
    </para>
    <table frame="all" id="fiber.performance.time_per_thread__average_over_10_000___unable_to_spawn_1_000_000_threads_">
      <title>time per thread (average over 10,000 - unable to spawn 1,000,000 threads)</title>
      <tgroup cols="3">
        <thead>
          <row>
            <entry>
              <para>
                pthread
              </para>
            </entry>
            <entry>
              <para>
                <code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase
                role="identifier">thread</phrase></code>
              </para>
            </entry>
            <entry>
              <para>
                <code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase
                role="identifier">async</phrase></code>
              </para>
            </entry>
          </row>
        </thead>
        <tbody>
          <row>
            <entry>
              <para>
                54 &#xb5;s - 73 &#xb5;s
              </para>
            </entry>
            <entry>
              <para>
                52 &#xb5;s - 73 &#xb5;s
              </para>
            </entry>
            <entry>
              <para>
                106 &#xb5;s - 122 &#xb5;s
              </para>
            </entry>
          </row>
        </tbody>
      </tgroup>
    </table>
    <para>
      The test utilizes 16 cores with Symmetric MultiThreading enabled (32 logical
      CPUs). The fiber stacks are allocated by <link linkend="class_fixedsize_stack"><code>fixedsize_stack</code></link>.
    </para>
    <para>
      As the benchmark shows, the memory allocation algorithm is significant for
      performance in a multithreaded environment. The tests use glibc&#8217;s memory allocation
      algorithm (based on ptmalloc2) as well as Google&#8217;s <ulink url="http://goog-perftools.sourceforge.net/doc/tcmalloc.html">TCmalloc</ulink>
      (via linkflags=&quot;-ltcmalloc&quot;).<footnote id="fiber.performance.f0">
      <para>
        Tais B. Ferreira, Rivalino Matias, Autran Macedo, Lucio B. Araujo <quote>An
        Experimental Study on Memory Allocators in Multicore and Multithreaded Applications</quote>,
        PDCAT &#8217;11 Proceedings of the 2011 12th International Conference on Parallel
        and Distributed Computing, Applications and Technologies, pages 92-98
      </para>
      </footnote>
    </para>
    <para>
      In the <link linkend="class_work_stealing"><code>work_stealing</code></link> scheduling algorithm, each thread has
      its own local queue. Fibers that are ready to run are pushed to and popped
      from the local queue. If the queue runs out of ready fibers, fibers are stolen
      from the local queues of other participating threads.
    </para>
    <table frame="all" id="fiber.performance.time_per_fiber__average_over_1_000_000_">
      <title>time per fiber (average over 1.000.000)</title>
      <tgroup cols="2">
        <thead>
          <row>
            <entry>
              <para>
                fiber (16C/32T, work stealing, tcmalloc)
              </para>
            </entry>
            <entry>
              <para>
                fiber (1C/1T, round robin, tcmalloc)
              </para>
            </entry>
          </row>
        </thead>
        <tbody>
          <row>
            <entry>
              <para>
                0.05 &#xb5;s - 0.09 &#xb5;s
              </para>
            </entry>
            <entry>
              <para>
                1.69 &#xb5;s - 1.79 &#xb5;s
              </para>
            </entry>
          </row>
        </tbody>
      </tgroup>
    </table>
  </section>
  <section id="fiber.tuning">
    <title><anchor id="tuning"/><link linkend="fiber.tuning">Tuning</link></title>
    <bridgehead renderas="sect3" id="fiber.tuning.h0">
      <phrase id="fiber.tuning.disable_synchronization"/><link linkend="fiber.tuning.disable_synchronization">Disable
      synchronization</link>
    </bridgehead>
    <para>
      With <link linkend="cross_thread_sync"><code><phrase role="identifier">BOOST_FIBERS_NO_ATOMICS</phrase></code></link>
      defined at the compiler&#8217;s command line, synchronization between fibers (in different
      threads) is disabled. This is acceptable if the application is single threaded
      and/or fibers are not synchronized between threads.
    </para>
    <bridgehead renderas="sect3" id="fiber.tuning.h1">
      <phrase id="fiber.tuning.memory_allocation"/><link linkend="fiber.tuning.memory_allocation">Memory
      allocation</link>
    </bridgehead>
    <para>
      Memory allocation algorithm is significant for performance in a multithreaded
      environment, especially for <emphasis role="bold">Boost.Fiber</emphasis> where
      fiber stacks are allocated on the heap. The default user-level memory allocator
      (UMA) of glibc is ptmalloc2 but it can be replaced by another UMA that fit
      better for the concret work-load For instance Google&#8217;s <ulink url="http://goog-perftools.sourceforge.net/doc/tcmalloc.html">TCmalloc</ulink>
      enables a better performance at the <emphasis>skynet</emphasis> microbenchmark
      than glibc&#8217;s default memory allocator.
    </para>
    <bridgehead renderas="sect3" id="fiber.tuning.h2">
      <phrase id="fiber.tuning.scheduling_strategies"/><link linkend="fiber.tuning.scheduling_strategies">Scheduling
      strategies</link>
    </bridgehead>
    <para>
      The fibers in a thread are coordinated by a fiber manager. Fibers trade control
      cooperatively, rather than preemptively. Depending on the work-load several
      strategies of scheduling the fibers are possible <footnote id="fiber.tuning.f0">
      <para>
        1024cores.net: <ulink url="http://www.1024cores.net/home/scalable-architecture/task-scheduling-strategies">Task
        Scheduling Strategies</ulink>
      </para>
      </footnote> that can be implmented on behalf of <link linkend="class_algorithm"><code>algorithm</code></link>.
    </para>
    <itemizedlist>
      <listitem>
        <simpara>
          work-stealing: ready fibers are hold in a local queue, when the fiber-scheduler's
          local queue runs out of ready fibers, it randomly selects another fiber-scheduler
          and tries to steal a ready fiber from the victim (implemented in <link linkend="class_work_stealing"><code>work_stealing</code></link> and
          <link linkend="class_numa_work_stealing"><code>numa::work_stealing</code></link>)
        </simpara>
      </listitem>
      <listitem>
        <simpara>
          work-requesting: ready fibers are hold in a local queue, when the fiber-scheduler's
          local queue runs out of ready fibers, it randomly selects another fiber-scheduler
          and requests for a ready fibers, the victim fiber-scheduler sends a ready-fiber
          back
        </simpara>
      </listitem>
      <listitem>
        <simpara>
          work-sharing: ready fibers are hold in a global queue, fiber-scheduler
          concurrently push and pop ready fibers to/from the global queue (implemented
          in <link linkend="class_shared_work"><code>shared_work</code></link>)
        </simpara>
      </listitem>
      <listitem>
        <simpara>
          work-distribution: fibers that became ready are proactivly distributed
          to idle fiber-schedulers or fiber-schedulers with low load
        </simpara>
      </listitem>
      <listitem>
        <simpara>
          work-balancing: a dedicated (helper) fiber-scheduler periodically collects
          informations about all fiber-scheduler running in other threads and re-distributes
          ready fibers among them
        </simpara>
      </listitem>
    </itemizedlist>
    <bridgehead renderas="sect3" id="fiber.tuning.h3">
      <phrase id="fiber.tuning.ttas_locks"/><link linkend="fiber.tuning.ttas_locks">TTAS
      locks</link>
    </bridgehead>
    <para>
      Boost.Fiber uses internally spinlocks to protect critical regions if fibers
      running on different threads interact. Spinlocks are implemented as TTAS (test-test-and-set)
      locks, i.e. the spinlock tests the lock before calling an atomic exchange.
      This strategy helps to reduce the cache line invalidations triggered by acquiring/releasing
      the lock.
    </para>
    <bridgehead renderas="sect3" id="fiber.tuning.h4">
      <phrase id="fiber.tuning.spin_wait_loop"/><link linkend="fiber.tuning.spin_wait_loop">Spin-wait
      loop</link>
    </bridgehead>
    <para>
      A lock is considered under contention, if a thread repeatedly fails to acquire
      the lock because some other thread was faster. Waiting for a short time lets
      other threads finish before trying to enter the critical section again. While
      busy waiting on the lock, relaxing the CPU (via pause/yield mnemonic) gives
      the CPU a hint that the code is in a spin-wait loop.
    </para>
    <itemizedlist>
      <listitem>
        <simpara>
          prevents expensive pipeline flushes (speculatively executed load and compare
          instructions are not pushed to pipeline)
        </simpara>
      </listitem>
      <listitem>
        <simpara>
          another hardware thread (simultaneous multithreading) can get time slice
        </simpara>
      </listitem>
      <listitem>
        <simpara>
          it does delay a few CPU cycles, but this is necessary to prevent starvation
        </simpara>
      </listitem>
    </itemizedlist>
    <para>
      It is obvious that this strategy is useless on single core systems because
      the lock can only released if the thread gives up its time slice in order to
      let other threads run. The macro BOOST_FIBERS_SPIN_SINGLE_CORE replaces the
      CPU hints (pause/yield mnemonic) by informing the operating system (via <code><phrase
      role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">this_thread_yield</phrase><phrase
      role="special">()</phrase></code>) that the thread gives up its time slice
      and the operating system switches to another thread.
    </para>
    <bridgehead renderas="sect3" id="fiber.tuning.h5">
      <phrase id="fiber.tuning.exponential_back_off"/><link linkend="fiber.tuning.exponential_back_off">Exponential
      back-off</link>
    </bridgehead>
    <para>
      The macro BOOST_FIBERS_RETRY_THRESHOLD determines how many times the CPU iterates
      in the spin-wait loop before yielding the thread or blocking in futex-wait.
      The spinlock tracks how many times the thread failed to acquire the lock. The
      higher the contention, the longer the thread should back-off. A <quote>Binary
      Exponential Backoff</quote> algorithm together with a randomized contention
      window is utilized for this purpose. BOOST_FIBERS_CONTENTION_WINDOW_THRESHOLD
      determines the upper limit of the contention window (expressed as the exponent
      for basis of two).
    </para>
    <bridgehead renderas="sect3" id="fiber.tuning.h6">
      <phrase id="fiber.tuning.speculative_execution__hardware_transactional_memory_"/><link
      linkend="fiber.tuning.speculative_execution__hardware_transactional_memory_">Speculative
      execution (hardware transactional memory)</link>
    </bridgehead>
    <para>
      Boost.Fiber uses spinlocks to protect critical regions that can be used together
      with transactional memory (see section <link linkend="speculation">Speculative
      execution</link>).
    </para>
    <note>
      <para>
        TXS is enabled if property <code><phrase role="identifier">htm</phrase><phrase
        role="special">=</phrase><phrase role="identifier">tsx</phrase></code> is
        specified at b2 command-line and <code><phrase role="identifier">BOOST_USE_TSX</phrase></code>
        is applied to the compiler.
      </para>
    </note>
    <note>
      <para>
        A TSX-transaction will be aborted if the floating point state is modified
        inside a critical region. As a consequence floating point operations, e.g.
        tore/load of floating point related registers during a fiber (context) switch
        are disabled.
      </para>
    </note>
    <bridgehead renderas="sect3" id="fiber.tuning.h7">
      <phrase id="fiber.tuning.numa_systems"/><link linkend="fiber.tuning.numa_systems">NUMA
      systems</link>
    </bridgehead>
    <para>
      Modern multi-socket systems are usually designed as <link linkend="numa">NUMA
      systems</link>. A suitable fiber scheduler like <link linkend="class_numa_work_stealing"><code>numa::work_stealing</code></link> reduces
      remote memory access (latence).
    </para>
    <bridgehead renderas="sect3" id="fiber.tuning.h8">
      <phrase id="fiber.tuning.parameters"/><link linkend="fiber.tuning.parameters">Parameters</link>
    </bridgehead>
    <table frame="all" id="fiber.tuning.parameters_that_migh_be_defiend_at_compiler_s_command_line">
      <title>Parameters that migh be defiend at compiler's command line</title>
      <tgroup cols="3">
        <thead>
          <row>
            <entry>
              <para>
                Parameter
              </para>
            </entry>
            <entry>
              <para>
                Default value
              </para>
            </entry>
            <entry>
              <para>
                Effect on Boost.Fiber
              </para>
            </entry>
          </row>
        </thead>
        <tbody>
          <row>
            <entry>
              <para>
                BOOST_FIBERS_NO_ATOMICS
              </para>
            </entry>
            <entry>
              <para>
                -
              </para>
            </entry>
            <entry>
              <para>
                no multithreading support, all atomics removed, no synchronization
                between fibers running in different threads
              </para>
            </entry>
          </row>
          <row>
            <entry>
              <para>
                BOOST_FIBERS_SPINLOCK_STD_MUTEX
              </para>
            </entry>
            <entry>
              <para>
                -
              </para>
            </entry>
            <entry>
              <para>
                <code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase
                role="identifier">mutex</phrase></code> used inside spinlock
              </para>
            </entry>
          </row>
          <row>
            <entry>
              <para>
                BOOST_FIBERS_SPINLOCK_TTAS
              </para>
            </entry>
            <entry>
              <para>
                +
              </para>
            </entry>
            <entry>
              <para>
                spinlock with test-test-and-swap on shared variable
              </para>
            </entry>
          </row>
          <row>
            <entry>
              <para>
                BOOST_FIBERS_SPINLOCK_TTAS_ADAPTIVE
              </para>
            </entry>
            <entry>
              <para>
                -
              </para>
            </entry>
            <entry>
              <para>
                spinlock with test-test-and-swap on shared variable, adaptive retries
                while busy waiting
              </para>
            </entry>
          </row>
          <row>
            <entry>
              <para>
                BOOST_FIBERS_SPINLOCK_TTAS_FUTEX
              </para>
            </entry>
            <entry>
              <para>
                -
              </para>
            </entry>
            <entry>
              <para>
                spinlock with test-test-and-swap on shared variable, suspend on futex
                after certain number of retries
              </para>
            </entry>
          </row>
          <row>
            <entry>
              <para>
                BOOST_FIBERS_SPINLOCK_TTAS_ADAPTIVE_FUTEX
              </para>
            </entry>
            <entry>
              <para>
                -
              </para>
            </entry>
            <entry>
              <para>
                spinlock with test-test-and-swap on shared variable, while busy waiting
                adaptive retries, suspend on futex certain amount of retries
              </para>
            </entry>
          </row>
          <row>
            <entry>
              <para>
                BOOST_FIBERS_SPINLOCK_TTAS + BOOST_USE_TSX
              </para>
            </entry>
            <entry>
              <para>
                -
              </para>
            </entry>
            <entry>
              <para>
                spinlock with test-test-and-swap and speculative execution (Intel
                TSX required)
              </para>
            </entry>
          </row>
          <row>
            <entry>
              <para>
                BOOST_FIBERS_SPINLOCK_TTAS_ADAPTIVE + BOOST_USE_TSX
              </para>
            </entry>
            <entry>
              <para>
                -
              </para>
            </entry>
            <entry>
              <para>
                spinlock with test-test-and-swap on shared variable, adaptive retries
                while busy waiting and speculative execution (Intel TSX required)
              </para>
            </entry>
          </row>
          <row>
            <entry>
              <para>
                BOOST_FIBERS_SPINLOCK_TTAS_FUTEX + BOOST_USE_TSX
              </para>
            </entry>
            <entry>
              <para>
                -
              </para>
            </entry>
            <entry>
              <para>
                spinlock with test-test-and-swap on shared variable, suspend on futex
                after certain number of retries and speculative execution (Intel
                TSX required)
              </para>
            </entry>
          </row>
          <row>
            <entry>
              <para>
                BOOST_FIBERS_SPINLOCK_TTAS_ADAPTIVE_FUTEX + BOOST_USE_TSX
              </para>
            </entry>
            <entry>
              <para>
                -
              </para>
            </entry>
            <entry>
              <para>
                spinlock with test-test-and-swap on shared variable, while busy waiting
                adaptive retries, suspend on futex certain amount of retries and
                speculative execution (Intel TSX required)
              </para>
            </entry>
          </row>
          <row>
            <entry>
              <para>
                BOOST_FIBERS_SPIN_SINGLE_CORE
              </para>
            </entry>
            <entry>
              <para>
                -
              </para>
            </entry>
            <entry>
              <para>
                on single core machines with multiple threads, yield thread (<code><phrase
                role="identifier">std</phrase><phrase role="special">::</phrase><phrase
                role="identifier">this_thread</phrase><phrase role="special">::</phrase><phrase
                role="identifier">yield</phrase><phrase role="special">()</phrase></code>)
                after collisions
              </para>
            </entry>
          </row>
          <row>
            <entry>
              <para>
                BOOST_FIBERS_RETRY_THRESHOLD
              </para>
            </entry>
            <entry>
              <para>
                64
              </para>
            </entry>
            <entry>
              <para>
                max number of retries while busy spinning, the use fallback
              </para>
            </entry>
          </row>
          <row>
            <entry>
              <para>
                BOOST_FIBERS_CONTENTION_WINDOW_THRESHOLD
              </para>
            </entry>
            <entry>
              <para>
                16
              </para>
            </entry>
            <entry>
              <para>
                max size of collisions window, expressed as exponent for the basis
                of two
              </para>
            </entry>
          </row>
          <row>
            <entry>
              <para>
                BOOST_FIBERS_SPIN_BEFORE_SLEEP0
              </para>
            </entry>
            <entry>
              <para>
                32
              </para>
            </entry>
            <entry>
              <para>
                max number of retries that relax the processor before the thread
                sleeps for 0s
              </para>
            </entry>
          </row>
          <row>
            <entry>
              <para>
                BOOST_FIBERS_SPIN_BEFORE_YIELD
              </para>
            </entry>
            <entry>
              <para>
                64
              </para>
            </entry>
            <entry>
              <para>
                max number of retries where the thread sleeps for 0s before yield
                thread (<code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase
                role="identifier">this_thread</phrase><phrase role="special">::</phrase><phrase
                role="identifier">yield</phrase><phrase role="special">()</phrase></code>)
              </para>
            </entry>
          </row>
        </tbody>
      </tgroup>
    </table>
  </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>
      <listitem>
        <simpara>
          The <link linkend="class_fiber"><code>fiber</code></link> class is actually just a handle to internal <link linkend="class_context"><code>context</code></link> data.
          A subclass of <code><phrase role="identifier">fiber</phrase></code> would
          not add data to <code><phrase role="identifier">context</phrase></code>.
        </simpara>
      </listitem>
    </orderedlist>
    <para>
      The present mechanism allows you to <quote>drop in</quote> 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">ctx</phrase><phrase role="special">):</phrase>
        <phrase role="identifier">fiber_properties</phrase><phrase role="special">(</phrase> <phrase role="identifier">ctx</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 <code><phrase role="identifier">notify</phrase><phrase
          role="special">()</phrase></code> 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_algorithm_with_properties"><code>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>
<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">algo</phrase><phrase role="special">::</phrase><phrase role="identifier">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="keyword">typedef</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">scheduler</phrase><phrase role="special">::</phrase><phrase role="identifier">ready_queue_type</phrase><co id="fiber.custom.c8" linkends="fiber.custom.c9" />   <phrase role="identifier">rqueue_t</phrase><phrase role="special">;</phrase>

    <phrase role="identifier">rqueue_t</phrase>                                <phrase role="identifier">rqueue_</phrase><phrase role="special">;</phrase>
    <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">mutex</phrase>                  <phrase role="identifier">mtx_</phrase><phrase role="special">{};</phrase>
    <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">condition_variable</phrase>     <phrase role="identifier">cnd_</phrase><phrase role="special">{};</phrase>
    <phrase role="keyword">bool</phrase>                        <phrase role="identifier">flag_</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="identifier">priority_scheduler</phrase><phrase role="special">()</phrase> <phrase role="special">:</phrase>
        <phrase role="identifier">rqueue_</phrase><phrase role="special">()</phrase> <phrase role="special">{</phrase>
    <phrase role="special">}</phrase>

    <phrase role="comment">// For a subclass of algorithm_with_properties&lt;&gt;, it's important to</phrase>
    <phrase role="comment">// override the correct awakened() overload.</phrase>
    <co id="fiber.custom.c10" linkends="fiber.custom.c11" /><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">ctx</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="keyword">noexcept</phrase> <phrase role="special">{</phrase>
        <phrase role="keyword">int</phrase> <phrase role="identifier">ctx_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.c12" linkends="fiber.custom.c13" />
        <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">rqueue_t</phrase><phrase role="special">::</phrase><phrase role="identifier">iterator</phrase> <phrase role="identifier">i</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">find_if</phrase><phrase role="special">(</phrase> <phrase role="identifier">rqueue_</phrase><phrase role="special">.</phrase><phrase role="identifier">begin</phrase><phrase role="special">(),</phrase> <phrase role="identifier">rqueue_</phrase><phrase role="special">.</phrase><phrase role="identifier">end</phrase><phrase role="special">(),</phrase>
            <phrase role="special">[</phrase><phrase role="identifier">ctx_priority</phrase><phrase role="special">,</phrase><phrase role="keyword">this</phrase><phrase role="special">](</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">context</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">c</phrase><phrase role="special">)</phrase>
            <phrase role="special">{</phrase> <phrase role="keyword">return</phrase> <phrase role="identifier">properties</phrase><phrase role="special">(</phrase> <phrase role="special">&amp;</phrase><phrase role="identifier">c</phrase> <phrase role="special">).</phrase><phrase role="identifier">get_priority</phrase><phrase role="special">()</phrase> <phrase role="special">&lt;</phrase> <phrase role="identifier">ctx_priority</phrase><phrase role="special">;</phrase> <phrase role="special">}));</phrase>
        <phrase role="comment">// Now, whether or not we found a fiber with lower priority,</phrase>
        <phrase role="comment">// insert this new fiber here.</phrase>
        <phrase role="identifier">rqueue_</phrase><phrase role="special">.</phrase><phrase role="identifier">insert</phrase><phrase role="special">(</phrase> <phrase role="identifier">i</phrase><phrase role="special">,</phrase> <phrase role="special">*</phrase> <phrase role="identifier">ctx</phrase><phrase role="special">);</phrase>
    <phrase role="special">}</phrase>

    <co id="fiber.custom.c14" linkends="fiber.custom.c15" /><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="keyword">noexcept</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="identifier">rqueue_</phrase><phrase role="special">.</phrase><phrase role="identifier">empty</phrase><phrase role="special">()</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="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">ctx</phrase><phrase role="special">(</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">rqueue_</phrase><phrase role="special">.</phrase><phrase role="identifier">front</phrase><phrase role="special">()</phrase> <phrase role="special">);</phrase>
        <phrase role="identifier">rqueue_</phrase><phrase role="special">.</phrase><phrase role="identifier">pop_front</phrase><phrase role="special">();</phrase>
        <phrase role="keyword">return</phrase> <phrase role="identifier">ctx</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="keyword">bool</phrase> <phrase role="identifier">has_ready_fibers</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="special">!</phrase> <phrase role="identifier">rqueue_</phrase><phrase role="special">.</phrase><phrase role="identifier">empty</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="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">ctx</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="keyword">noexcept</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">// 'ctx' might not be in our queue at all, if caller is changing the</phrase>
        <phrase role="comment">// priority of (say) the running fiber. If it's not there, no need to</phrase>
        <phrase role="comment">// move it: 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">ctx</phrase><phrase role="special">-&gt;</phrase><phrase role="identifier">ready_is_linked</phrase><phrase role="special">())</phrase> <phrase role="special">{</phrase> <co id="fiber.custom.c20" linkends="fiber.custom.c21" />
            <phrase role="keyword">return</phrase><phrase role="special">;</phrase>
        <phrase role="special">}</phrase>

        <phrase role="comment">// Found ctx: unlink it</phrase>
        <phrase role="identifier">ctx</phrase><phrase role="special">-&gt;</phrase><phrase role="identifier">ready_unlink</phrase><phrase role="special">();</phrase>

        <phrase role="comment">// Here we know that ctx was in our ready queue, but we've unlinked</phrase>
        <phrase role="comment">// it. We happen to have a method that will (re-)add a context* to the</phrase>
        <phrase role="comment">// right place in the ready queue.</phrase>
        <phrase role="identifier">awakened</phrase><phrase role="special">(</phrase> <phrase role="identifier">ctx</phrase><phrase role="special">,</phrase> <phrase role="identifier">props</phrase><phrase role="special">);</phrase>
    <phrase role="special">}</phrase>

    <phrase role="keyword">void</phrase> <phrase role="identifier">suspend_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">steady_clock</phrase><phrase role="special">::</phrase><phrase role="identifier">time_point</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">time_point</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase> <phrase role="special">{</phrase>
        <phrase role="keyword">if</phrase> <phrase role="special">(</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">steady_clock</phrase><phrase role="special">::</phrase><phrase role="identifier">time_point</phrase><phrase role="special">::</phrase><phrase role="identifier">max</phrase><phrase role="special">)()</phrase> <phrase role="special">==</phrase> <phrase role="identifier">time_point</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">std</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">cnd_</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="keyword">this</phrase><phrase role="special">](){</phrase> <phrase role="keyword">return</phrase> <phrase role="identifier">flag_</phrase><phrase role="special">;</phrase> <phrase role="special">});</phrase>
            <phrase role="identifier">flag_</phrase> <phrase role="special">=</phrase> <phrase role="keyword">false</phrase><phrase role="special">;</phrase>
        <phrase role="special">}</phrase> <phrase role="keyword">else</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">std</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">cnd_</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">time_point</phrase><phrase role="special">,</phrase> <phrase role="special">[</phrase><phrase role="keyword">this</phrase><phrase role="special">](){</phrase> <phrase role="keyword">return</phrase> <phrase role="identifier">flag_</phrase><phrase role="special">;</phrase> <phrase role="special">});</phrase>
            <phrase role="identifier">flag_</phrase> <phrase role="special">=</phrase> <phrase role="keyword">false</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="keyword">noexcept</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">std</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">flag_</phrase> <phrase role="special">=</phrase> <phrase role="keyword">true</phrase><phrase role="special">;</phrase>
        <phrase role="identifier">lk</phrase><phrase role="special">.</phrase><phrase role="identifier">unlock</phrase><phrase role="special">();</phrase>
        <phrase role="identifier">cnd_</phrase><phrase role="special">.</phrase><phrase role="identifier">notify_all</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>
          See <link linkend="ready_queue_t">ready_queue_t</link>.
        </para>
      </callout>
      <callout arearefs="fiber.custom.c10" id="fiber.custom.c11">
        <para>
          You must override the <link linkend="algorithm_with_properties_awakened"><code>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.c12" id="fiber.custom.c13">
        <para>
          <code><phrase role="identifier">props</phrase></code> is the instance of
          priority_props associated with the passed fiber <code><phrase role="identifier">ctx</phrase></code>.
        </para>
      </callout>
      <callout arearefs="fiber.custom.c14" id="fiber.custom.c15">
        <para>
          You must override the <link linkend="algorithm_with_properties_pick_next"><code>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.c16" id="fiber.custom.c17">
        <para>
          You must override <link linkend="algorithm_with_properties_has_ready_fibers"><code>algorithm_with_properties::has_ready_fibers()</code></link>
      to
          inform the fiber manager of the state of your ready queue.
        </para>
      </callout>
      <callout arearefs="fiber.custom.c18" id="fiber.custom.c19">
        <para>
          Overriding <link linkend="algorithm_with_properties_property_change"><code>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.c20" id="fiber.custom.c21">
        <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">ctx</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="algorithm_with_properties_new_properties"><code>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">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;&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="algorithm_with_properties_pick_next"><code>algorithm_with_properties::pick_next()</code></link>.
    </para>
  </section>
  <section id="fiber.rationale">
    <title><link linkend="fiber.rationale">Rationale</link></title>
    <bridgehead renderas="sect3" id="fiber.rationale.h0">
      <phrase id="fiber.rationale.preprocessor_defines"/><link linkend="fiber.rationale.preprocessor_defines">preprocessor
      defines</link>
    </bridgehead>
    <table frame="all" id="fiber.rationale.preopcessor_defines">
      <title>preopcessor defines</title>
      <tgroup cols="2">
        <thead>
          <row>
            <entry>
            </entry>
            <entry>
            </entry>
          </row>
        </thead>
        <tbody>
          <row>
            <entry>
              <para>
                BOOST_FIBERS_NO_ATOMICS
              </para>
            </entry>
            <entry>
              <para>
                no <code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase
                role="identifier">atomic</phrase><phrase role="special">&lt;&gt;</phrase></code>
                used, inter-thread synchronization disabled
              </para>
            </entry>
          </row>
          <row>
            <entry>
              <para>
                BOOST_FIBERS_SPINLOCK_STD_MUTEX
              </para>
            </entry>
            <entry>
              <para>
                use <code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase
                role="identifier">mutex</phrase></code> as spinlock instead of default
                <code><phrase role="identifier">XCHG</phrase></code>-sinlock with
                backoff
              </para>
            </entry>
          </row>
          <row>
            <entry>
              <para>
                BOOST_FIBERS_SPIN_BACKOFF
              </para>
            </entry>
            <entry>
              <para>
                limit determines when to used <code><phrase role="identifier">std</phrase><phrase
                role="special">::</phrase><phrase role="identifier">this_thread</phrase><phrase
                role="special">::</phrase><phrase role="identifier">yield</phrase><phrase
                role="special">()</phrase></code> instead of mnemonic <code><phrase
                role="identifier">pause</phrase><phrase role="special">/</phrase><phrase
                role="identifier">yield</phrase></code> during busy wait (apllies
                on to <code><phrase role="identifier">XCHG</phrase></code>-spinlock)
              </para>
            </entry>
          </row>
          <row>
            <entry>
              <para>
                BOOST_FIBERS_SINGLE_CORE
              </para>
            </entry>
            <entry>
              <para>
                allways call <code><phrase role="identifier">std</phrase><phrase
                role="special">::</phrase><phrase role="identifier">this_thread</phrase><phrase
                role="special">::</phrase><phrase role="identifier">yield</phrase><phrase
                role="special">()</phrase></code> without backoff during busy wait
                (apllies on to <code><phrase role="identifier">XCHG</phrase></code>-spinlock)
              </para>
            </entry>
          </row>
        </tbody>
      </tgroup>
    </table>
    <bridgehead renderas="sect3" id="fiber.rationale.h1">
      <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.h2">
      <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.h3">
      <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>
    <anchor id="spurious_wakeup"/>
    <bridgehead renderas="sect3" id="fiber.rationale.h4">
      <phrase id="fiber.rationale.spurious_wakeup"/><link linkend="fiber.rationale.spurious_wakeup">spurious
      wakeup</link>
    </bridgehead>
    <para>
      Spurious wakeup can happen when using <ulink url="http://en.cppreference.com/w/cpp/thread/condition_variable"><code><phrase
      role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">condition_variable</phrase></code></ulink>:
      the condition variable appears to be have been signaled while the awaited condition
      may still be false. Spurious wakeup can happen repeatedly and is caused on
      some multiprocessor systems where making <code><phrase role="identifier">std</phrase><phrase
      role="special">::</phrase><phrase role="identifier">condition_variable</phrase></code>
      wakeup completely predictable would slow down all <code><phrase role="identifier">std</phrase><phrase
      role="special">::</phrase><phrase role="identifier">condition_variable</phrase></code>
      operations.<footnote id="fiber.rationale.f1">
      <para>
        David R. Butenhof <quote>Programming with POSIX Threads</quote>
      </para>
      </footnote>
    </para>
    <para>
      <link linkend="class_condition_variable"><code>condition_variable</code></link> is not subject to spurious wakeup.
      Nonetheless it is prudent to test the business-logic condition in a <code><phrase
      role="identifier">wait</phrase><phrase role="special">()</phrase></code> loop
      &mdash; or, equivalently, use one of the <code><phrase role="identifier">wait</phrase><phrase
      role="special">(</phrase> <phrase role="identifier">lock</phrase><phrase role="special">,</phrase>
      <phrase role="identifier">predicate</phrase> <phrase role="special">)</phrase></code>
      overloads.
    </para>
    <para>
      See also <link linkend="condition_variable_spurious_wakeups">No Spurious Wakeups</link>.
    </para>
    <bridgehead renderas="sect3" id="fiber.rationale.h5">
      <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 has been integrated. The user-defined
      scheduler must call <link linkend="context_detach"><code>context::detach()</code></link> on a fiber-context on the
      source thread and <link linkend="context_attach"><code>context::attach()</code></link> on the destination thread,
      passing the fiber-context to migrate. (For more information about custom schedulers,
      see <link linkend="custom">Customization</link>.) Examples <code><phrase role="identifier">work_sharing</phrase></code>
      and <code><phrase role="identifier">work_stealing</phrase></code> in directory
      <code><phrase role="identifier">examples</phrase></code> might be used as a
      blueprint.
    </para>
    <para>
      See also <link linkend="migration">Migrating fibers between threads</link>.
    </para>
    <bridgehead renderas="sect3" id="fiber.rationale.h6">
      <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>&#8217;s
      <emphasis>async-result</emphasis> is not part of the official API. However,
      to integrate with a <ulink url="http://www.boost.org/doc/libs/release/doc/html/boost_asio/reference/io_service.html"><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></ulink>,
      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&#8217;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.h7">
      <phrase id="fiber.rationale.tested_compilers"/><link linkend="fiber.rationale.tested_compilers">tested
      compilers</link>
    </bridgehead>
    <para>
      The library was tested with GCC-5.1.1, Clang-3.6.0 and MSVC-14.0 in c++11-mode.
    </para>
    <bridgehead renderas="sect3" id="fiber.rationale.h8">
      <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.acknowledgements">
    <title><link linkend="fiber.acknowledgements">Acknowledgments</link></title>
    <para>
      I'd like to thank Agustín Bergé, Eugene Yakubovich, Giovanni Piero Deretta
      and especially Nat Goodspeed.
    </para>
  </section>
</library>
