• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1<?xml version="1.0" encoding="UTF-8"?>
2<!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
3<library id="fiber" name="Fiber" dirname="fiber" last-revision="$Date: 2018/10/22 08:13:04 $"
4 xmlns:xi="http://www.w3.org/2001/XInclude">
5  <libraryinfo>
6    <authorgroup>
7    <author>
8      <firstname>Oliver</firstname> <surname>Kowalke</surname>
9    </author>
10    </authorgroup>
11    <copyright>
12      <year>2013</year> <holder>Oliver Kowalke</holder>
13    </copyright>
14    <legalnotice id="fiber.legal">
15      <para>
16        Distributed under the Boost Software License, Version 1.0. (See accompanying
17        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>)
18      </para>
19    </legalnotice>
20    <librarypurpose>
21      C++ Library to cooperatively schedule and synchronize micro-threads
22    </librarypurpose>
23    <librarycategory name="category:text"></librarycategory>
24  </libraryinfo>
25  <title>Fiber</title>
26  <section id="fiber.overview">
27    <title><link linkend="fiber.overview">Overview</link></title>
28    <para>
29      <emphasis role="bold">Boost.Fiber</emphasis> provides a framework for micro-/userland-threads
30      (fibers) scheduled cooperatively. The API contains classes and functions to
31      manage and synchronize fibers similiarly to <ulink url="http://en.cppreference.com/w/cpp/thread">standard
32      thread support library</ulink>.
33    </para>
34    <para>
35      Each fiber has its own stack.
36    </para>
37    <para>
38      A fiber can save the current execution state, including all registers and CPU
39      flags, the instruction pointer, and the stack pointer and later restore this
40      state. The idea is to have multiple execution paths running on a single thread
41      using cooperative scheduling (versus threads, which are preemptively scheduled).
42      The running fiber decides explicitly when it should yield to allow another
43      fiber to run (context switching). <emphasis role="bold">Boost.Fiber</emphasis>
44      internally uses <ulink url="http://www.boost.org/doc/libs/release/libs/context/doc/html/context/cc.html"><emphasis>call/cc</emphasis></ulink>
45      from <ulink url="http://www.boost.org/doc/libs/release/libs/context/index.html">Boost.Context</ulink>;
46      the classes in this library manage, schedule and, when needed, synchronize
47      those execution contexts. A context switch between threads usually costs thousands
48      of CPU cycles on x86, compared to a fiber switch with less than a hundred cycles.
49      A fiber runs on a single thread at any point in time.
50    </para>
51    <para>
52      In order to use the classes and functions described here, you can either include
53      the specific headers specified by the descriptions of each class or function,
54      or include the master library header:
55    </para>
56<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>
57</programlisting>
58    <para>
59      which includes all the other headers in turn.
60    </para>
61    <para>
62      The namespaces used are:
63    </para>
64<programlisting><phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase>
65<phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">this_fiber</phrase>
66</programlisting>
67    <bridgehead renderas="sect3" id="fiber.overview.h0">
68      <phrase id="fiber.overview.fibers_and_threads"/><link linkend="fiber.overview.fibers_and_threads">Fibers
69      and Threads</link>
70    </bridgehead>
71    <para>
72      Control is cooperatively passed between fibers launched on a given thread.
73      At a given moment, on a given thread, at most one fiber is running.
74    </para>
75    <para>
76      Spawning additional fibers on a given thread does not distribute your program
77      across more hardware cores, though it can make more effective use of the core
78      on which it's running.
79    </para>
80    <para>
81      On the other hand, a fiber may safely access any resource exclusively owned
82      by its parent thread without explicitly needing to defend that resource against
83      concurrent access by other fibers on the same thread. You are already guaranteed
84      that no other fiber on that thread is concurrently touching that resource.
85      This can be particularly important when introducing concurrency in legacy code.
86      You can safely spawn fibers running old code, using asynchronous I/O to interleave
87      execution.
88    </para>
89    <para>
90      In effect, fibers provide a natural way to organize concurrent code based on
91      asynchronous I/O. Instead of chaining together completion handlers, code running
92      on a fiber can make what looks like a normal blocking function call. That call
93      can cheaply suspend the calling fiber, allowing other fibers on the same thread
94      to run. When the operation has completed, the suspended fiber resumes, without
95      having to explicitly save or restore its state. Its local stack variables persist
96      across the call.
97    </para>
98    <para>
99      A fiber can be migrated from one thread to another, though the library does
100      not do this by default. It is possible for you to supply a custom scheduler
101      that migrates fibers between threads. You may specify custom fiber properties
102      to help your scheduler decide which fibers are permitted to migrate. Please
103      see <link linkend="migration">Migrating fibers between threads</link> and
104      <link linkend="custom">Customization</link> for more details.
105    </para>
106    <para>
107      <emphasis role="bold">Boost.Fiber</emphasis> allows to <emphasis role="bold"><code><phrase
108      role="identifier">multiplex</phrase> <phrase role="identifier">fibers</phrase>
109      <phrase role="identifier">across</phrase> <phrase role="identifier">multiple</phrase>
110      <phrase role="identifier">cores</phrase></code></emphasis> (see <link linkend="class_numa_work_stealing"><code>numa::work_stealing</code></link>).
111    </para>
112    <para>
113      A fiber launched on a particular thread continues running on that thread unless
114      migrated. It might be unblocked (see <link linkend="blocking">Blocking</link>
115      below) by some other thread, but that only transitions the fiber from <quote>blocked</quote>
116      to <quote>ready</quote> on its current thread &mdash; it does not cause the fiber to
117      resume on the thread that unblocked it.
118    </para>
119    <anchor id="thread_local_storage"/>
120    <bridgehead renderas="sect3" id="fiber.overview.h1">
121      <phrase id="fiber.overview.thread_local_storage"/><link linkend="fiber.overview.thread_local_storage">thread-local
122      storage</link>
123    </bridgehead>
124    <para>
125      Unless migrated, a fiber may access thread-local storage; however that storage
126      will be shared among all fibers running on the same thread. For fiber-local
127      storage, please see <link linkend="class_fiber_specific_ptr"><code>fiber_specific_ptr</code></link>.
128    </para>
129    <anchor id="cross_thread_sync"/>
130    <bridgehead renderas="sect3" id="fiber.overview.h2">
131      <phrase id="fiber.overview.boost_fibers_no_atomics"/><link linkend="fiber.overview.boost_fibers_no_atomics">BOOST_FIBERS_NO_ATOMICS</link>
132    </bridgehead>
133    <para>
134      The fiber synchronization objects provided by this library will, by default,
135      safely synchronize fibers running on different threads. However, this level
136      of synchronization can be removed (for performance) by building the library
137      with <emphasis role="bold"><code><phrase role="identifier">BOOST_FIBERS_NO_ATOMICS</phrase></code></emphasis>
138      defined. When the library is built with that macro, you must ensure that all
139      the fibers referencing a particular synchronization object are running in the
140      same thread. Please see <link linkend="synchronization">Synchronization</link>.
141    </para>
142    <anchor id="blocking"/>
143    <bridgehead renderas="sect3" id="fiber.overview.h3">
144      <phrase id="fiber.overview.blocking"/><link linkend="fiber.overview.blocking">Blocking</link>
145    </bridgehead>
146    <para>
147      Normally, when this documentation states that a particular fiber <emphasis>blocks</emphasis>
148      (or equivalently, <emphasis>suspends),</emphasis> it means that it yields control,
149      allowing other fibers on the same thread to run. The synchronization mechanisms
150      provided by <emphasis role="bold">Boost.Fiber</emphasis> have this behavior.
151    </para>
152    <para>
153      A fiber may, of course, use normal thread synchronization mechanisms; however
154      a fiber that invokes any of these mechanisms will block its entire thread,
155      preventing any other fiber from running on that thread in the meantime. For
156      instance, when a fiber wants to wait for a value from another fiber in the
157      same thread, using <code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase
158      role="identifier">future</phrase></code> would be unfortunate: <code><phrase
159      role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">future</phrase><phrase
160      role="special">::</phrase><phrase role="identifier">get</phrase><phrase role="special">()</phrase></code>
161      would block the whole thread, preventing the other fiber from delivering its
162      value. Use <link linkend="class_future"><code>future&lt;&gt;</code></link> instead.
163    </para>
164    <para>
165      Similarly, a fiber that invokes a normal blocking I/O operation will block
166      its entire thread. Fiber authors are encouraged to consistently use asynchronous
167      I/O. <ulink url="http://www.boost.org/doc/libs/release/libs/asio/index.html">Boost.Asio</ulink>
168      and other asynchronous I/O operations can straightforwardly be adapted for
169      <emphasis role="bold">Boost.Fiber</emphasis>: see <link linkend="callbacks">Integrating
170      Fibers with Asynchronous Callbacks</link>.
171    </para>
172    <para>
173      <emphasis role="bold">Boost.Fiber</emphasis> depends upon <ulink url="http://www.boost.org/doc/libs/release/libs/context/index.html">Boost.Context</ulink>.
174      Boost version 1.61.0 or greater is required.
175    </para>
176    <note>
177      <para>
178        This library requires C++11!
179      </para>
180    </note>
181    <section id="fiber.overview.implementations__fcontext_t__ucontext_t_and_winfiber">
182      <title><anchor id="implementation"/><link linkend="fiber.overview.implementations__fcontext_t__ucontext_t_and_winfiber">Implementations:
183      fcontext_t, ucontext_t and WinFiber</link></title>
184      <para>
185        <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>
186        from <ulink url="http://www.boost.org/doc/libs/release/libs/context/index.html">Boost.Context</ulink>
187        as building-block.
188      </para>
189      <bridgehead renderas="sect4" id="fiber.overview.implementations__fcontext_t__ucontext_t_and_winfiber.h0">
190        <phrase id="fiber.overview.implementations__fcontext_t__ucontext_t_and_winfiber.fcontext_t"/><link
191        linkend="fiber.overview.implementations__fcontext_t__ucontext_t_and_winfiber.fcontext_t">fcontext_t</link>
192      </bridgehead>
193      <para>
194        The implementation uses <code><phrase role="identifier">fcontext_t</phrase></code>
195        per default. fcontext_t is based on assembler and not available for all platforms.
196        It provides a much better performance than <code><phrase role="identifier">ucontext_t</phrase></code>
197        (the context switch takes two magnitudes of order less CPU cycles; see section
198        <ulink url="http://www.boost.org/doc/libs/release/libs/context/doc/html/context/performance.html"><emphasis>performance</emphasis></ulink>)
199        and <code><phrase role="identifier">WinFiber</phrase></code>.
200      </para>
201      <bridgehead renderas="sect4" id="fiber.overview.implementations__fcontext_t__ucontext_t_and_winfiber.h1">
202        <phrase id="fiber.overview.implementations__fcontext_t__ucontext_t_and_winfiber.ucontext_t"/><link
203        linkend="fiber.overview.implementations__fcontext_t__ucontext_t_and_winfiber.ucontext_t">ucontext_t</link>
204      </bridgehead>
205      <para>
206        As an alternative, <ulink url="https://en.wikipedia.org/wiki/Setcontext"><code><phrase
207        role="identifier">ucontext_t</phrase></code></ulink> can be used by compiling
208        with <code><phrase role="identifier">BOOST_USE_UCONTEXT</phrase></code> and
209        b2 property <code><phrase role="identifier">context</phrase><phrase role="special">-</phrase><phrase
210        role="identifier">impl</phrase><phrase role="special">=</phrase><phrase role="identifier">ucontext</phrase></code>.
211        <code><phrase role="identifier">ucontext_t</phrase></code> might be available
212        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>
213        (for instance deprecated since POSIX.1-2003, not C99 conform).
214      </para>
215      <note>
216        <para>
217          <ulink url="http://www.boost.org/doc/libs/release/libs/context/doc/html/context/cc.html"><emphasis>call/cc</emphasis></ulink>
218          supports <link linkend="segmented"><emphasis>Segmented stacks</emphasis></link>
219          only with <code><phrase role="identifier">ucontext_t</phrase></code> as
220          its implementation.
221        </para>
222      </note>
223      <bridgehead renderas="sect4" id="fiber.overview.implementations__fcontext_t__ucontext_t_and_winfiber.h2">
224        <phrase id="fiber.overview.implementations__fcontext_t__ucontext_t_and_winfiber.winfiber"/><link
225        linkend="fiber.overview.implementations__fcontext_t__ucontext_t_and_winfiber.winfiber">WinFiber</link>
226      </bridgehead>
227      <para>
228        With <code><phrase role="identifier">BOOST_USE_WINFIB</phrase></code> and
229        b2 property <code><phrase role="identifier">context</phrase><phrase role="special">-</phrase><phrase
230        role="identifier">impl</phrase><phrase role="special">=</phrase><phrase role="identifier">winfib</phrase></code>
231        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>.
232      </para>
233      <para>
234        Because the TIB (thread information block) is not fully described in the
235        MSDN, it might be possible that not all required TIB-parts are swapped.
236      </para>
237      <note>
238        <para>
239          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>
240          converts the thread into a Windows fiber by invoking <code><phrase role="identifier">ConvertThreadToFiber</phrase><phrase
241          role="special">()</phrase></code>. If desired, <code><phrase role="identifier">ConvertFiberToThread</phrase><phrase
242          role="special">()</phrase></code> has to be called by the user explicitly
243          in order to release resources allocated by <code><phrase role="identifier">ConvertThreadToFiber</phrase><phrase
244          role="special">()</phrase></code> (e.g. after using boost.context).
245        </para>
246      </note>
247    </section>
248    <important>
249      <para>
250        Windows using fcontext_t: turn off global program optimization (/GL) and
251        change /EHsc (compiler assumes that functions declared as extern &quot;C&quot;
252        never throw a C++ exception) to /EHs (tells compiler assumes that functions
253        declared as extern &quot;C&quot; may throw an exception).
254      </para>
255    </important>
256  </section>
257  <section id="fiber.fiber_mgmt">
258    <title><link linkend="fiber.fiber_mgmt">Fiber management</link></title>
259    <bridgehead renderas="sect3" id="fiber.fiber_mgmt.h0">
260      <phrase id="fiber.fiber_mgmt.synopsis"/><link linkend="fiber.fiber_mgmt.synopsis">Synopsis</link>
261    </bridgehead>
262<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>
263
264<phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase>
265<phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase>
266
267<phrase role="keyword">class</phrase> <phrase role="identifier">fiber</phrase><phrase role="special">;</phrase>
268<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>
269<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>
270
271<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>
272<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>
273<phrase role="keyword">bool</phrase> <phrase role="identifier">has_ready_fibers</phrase><phrase role="special">();</phrase>
274
275<phrase role="keyword">namespace</phrase> <phrase role="identifier">algo</phrase> <phrase role="special">{</phrase>
276
277<phrase role="keyword">struct</phrase> <phrase role="identifier">algorithm</phrase><phrase role="special">;</phrase>
278<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>
279<phrase role="keyword">struct</phrase> <phrase role="identifier">algorithm_with_properties</phrase><phrase role="special">;</phrase>
280<phrase role="keyword">class</phrase> <phrase role="identifier">round_robin</phrase><phrase role="special">;</phrase>
281<phrase role="keyword">class</phrase> <phrase role="identifier">shared_round_robin</phrase><phrase role="special">;</phrase>
282
283<phrase role="special">}}</phrase>
284
285<phrase role="keyword">namespace</phrase> <phrase role="identifier">this_fiber</phrase> <phrase role="special">{</phrase>
286
287<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>
288<phrase role="keyword">void</phrase> <phrase role="identifier">yield</phrase><phrase role="special">();</phrase>
289<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>
290<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>
291<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>
292<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>
293<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>
294<phrase role="identifier">PROPS</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">properties</phrase><phrase role="special">();</phrase>
295
296<phrase role="special">}</phrase>
297</programlisting>
298    <bridgehead renderas="sect3" id="fiber.fiber_mgmt.h1">
299      <phrase id="fiber.fiber_mgmt.tutorial"/><link linkend="fiber.fiber_mgmt.tutorial">Tutorial</link>
300    </bridgehead>
301    <para>
302      Each <link linkend="class_fiber"><code>fiber</code></link> represents a micro-thread which will be launched and managed
303      cooperatively by a scheduler. Objects of type <link linkend="class_fiber"><code>fiber</code></link> are move-only.
304    </para>
305<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>
306
307<phrase role="keyword">void</phrase> <phrase role="identifier">f</phrase><phrase role="special">()</phrase> <phrase role="special">{</phrase>
308    <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>
309
310    <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>
311<phrase role="special">}</phrase>
312</programlisting>
313    <bridgehead renderas="sect3" id="fiber.fiber_mgmt.h2">
314      <phrase id="fiber.fiber_mgmt.launching"/><link linkend="fiber.fiber_mgmt.launching">Launching</link>
315    </bridgehead>
316    <para>
317      A new fiber is launched by passing an object of a callable type that can be
318      invoked with no parameters. If the object must not be copied or moved, then
319      <emphasis>std::ref</emphasis> can be used to pass in a reference to the function
320      object. In this case, the user must ensure that the referenced object outlives
321      the newly-created fiber.
322    </para>
323<programlisting><phrase role="keyword">struct</phrase> <phrase role="identifier">callable</phrase> <phrase role="special">{</phrase>
324    <phrase role="keyword">void</phrase> <phrase role="keyword">operator</phrase><phrase role="special">()();</phrase>
325<phrase role="special">};</phrase>
326
327<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>
328    <phrase role="identifier">callable</phrase> <phrase role="identifier">x</phrase><phrase role="special">;</phrase>
329    <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>
330<phrase role="special">}</phrase> <phrase role="comment">// x is destroyed, but the newly-created fiber has a copy, so this is OK</phrase>
331
332<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>
333    <phrase role="identifier">callable</phrase> <phrase role="identifier">x</phrase><phrase role="special">;</phrase>
334    <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>
335<phrase role="special">}</phrase> <phrase role="comment">// x is destroyed, but the newly-created fiber still has a reference</phrase>
336  <phrase role="comment">// this leads to undefined behaviour</phrase>
337</programlisting>
338    <para>
339      The spawned <link linkend="class_fiber"><code>fiber</code></link> does not immediately start running. It is enqueued
340      in the list of ready-to-run fibers, and will run when the scheduler gets around
341      to it.
342    </para>
343    <anchor id="exceptions"/>
344    <bridgehead renderas="sect3" id="fiber.fiber_mgmt.h3">
345      <phrase id="fiber.fiber_mgmt.exceptions"/><link linkend="fiber.fiber_mgmt.exceptions">Exceptions</link>
346    </bridgehead>
347    <para>
348      An exception escaping from the function or callable object passed to the <link linkend="class_fiber"><code>fiber</code></link>
349constructor
350      calls <code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase
351      role="identifier">terminate</phrase><phrase role="special">()</phrase></code>.
352      If you need to know which exception was thrown, use <link linkend="class_future"><code>future&lt;&gt;</code></link> or
353      <link linkend="class_packaged_task"><code>packaged_task&lt;&gt;</code></link>.
354    </para>
355    <bridgehead renderas="sect3" id="fiber.fiber_mgmt.h4">
356      <phrase id="fiber.fiber_mgmt.detaching"/><link linkend="fiber.fiber_mgmt.detaching">Detaching</link>
357    </bridgehead>
358    <para>
359      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
360      function. After <link linkend="fiber_detach"><code>fiber::detach()</code></link> is called on a fiber object, that
361      object represents <emphasis>not-a-fiber</emphasis>. The fiber object may then
362      safely be destroyed.
363    </para>
364<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>
365</programlisting>
366    <para>
367      <emphasis role="bold">Boost.Fiber</emphasis> provides a number of ways to wait
368      for a running fiber to complete. You can coordinate even with a detached fiber
369      using a <link linkend="class_mutex"><code>mutex</code></link>, or <link linkend="class_condition_variable"><code>condition_variable</code></link>, or
370      any of the other <link linkend="synchronization">synchronization objects</link>
371      provided by the library.
372    </para>
373    <para>
374      If a detached fiber is still running when the thread&#8217;s main fiber terminates,
375      the thread will not shut down.
376    </para>
377    <bridgehead renderas="sect3" id="fiber.fiber_mgmt.h5">
378      <phrase id="fiber.fiber_mgmt.joining"/><link linkend="fiber.fiber_mgmt.joining">Joining</link>
379    </bridgehead>
380    <para>
381      In order to wait for a fiber to finish, the <link linkend="fiber_join"><code>fiber::join()</code></link> member function
382      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
383      until the <link linkend="class_fiber"><code>fiber</code></link> object has completed.
384    </para>
385<programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">some_fn</phrase><phrase role="special">()</phrase> <phrase role="special">{</phrase>
386    <phrase role="special">...</phrase>
387<phrase role="special">}</phrase>
388
389<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>
390<phrase role="special">...</phrase>
391<phrase role="identifier">f</phrase><phrase role="special">.</phrase><phrase role="identifier">join</phrase><phrase role="special">();</phrase>
392</programlisting>
393    <para>
394      If the fiber has already completed, then <link linkend="fiber_join"><code>fiber::join()</code></link> returns immediately
395      and the joined <link linkend="class_fiber"><code>fiber</code></link> object becomes <emphasis>not-a-fiber</emphasis>.
396    </para>
397    <bridgehead renderas="sect3" id="fiber.fiber_mgmt.h6">
398      <phrase id="fiber.fiber_mgmt.destruction"/><link linkend="fiber.fiber_mgmt.destruction">Destruction</link>
399    </bridgehead>
400    <para>
401      When a <link linkend="class_fiber"><code>fiber</code></link> object representing a valid execution context (the fiber
402      is <link linkend="fiber_joinable"><code>fiber::joinable()</code></link>) is destroyed, the program terminates. If
403      you intend the fiber to outlive the <link linkend="class_fiber"><code>fiber</code></link> object that launched it,
404      use the <link linkend="fiber_detach"><code>fiber::detach()</code></link> method.
405    </para>
406<programlisting><phrase role="special">{</phrase>
407    <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>
408<phrase role="special">}</phrase> <phrase role="comment">// std::terminate() will be called</phrase>
409
410<phrase role="special">{</phrase>
411    <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>
412    <phrase role="identifier">f</phrase><phrase role="special">.</phrase><phrase role="identifier">detach</phrase><phrase role="special">();</phrase>
413<phrase role="special">}</phrase> <phrase role="comment">// okay, program continues</phrase>
414</programlisting>
415    <anchor id="class_fiber_id"/>
416    <bridgehead renderas="sect3" id="fiber.fiber_mgmt.h7">
417      <phrase id="fiber.fiber_mgmt.fiber_ids"/><link linkend="fiber.fiber_mgmt.fiber_ids">Fiber
418      IDs</link>
419    </bridgehead>
420    <para>
421      Objects of class <link linkend="class_fiber_id"><code><phrase role="identifier">fiber</phrase><phrase
422      role="special">::</phrase><phrase role="identifier">id</phrase></code></link> can be
423      used to identify fibers. Each running <link linkend="class_fiber"><code>fiber</code></link> has a unique <link linkend="class_fiber_id"><code><phrase
424      role="identifier">fiber</phrase><phrase role="special">::</phrase><phrase role="identifier">id</phrase></code></link> obtainable
425      from the corresponding <link linkend="class_fiber"><code>fiber</code></link>
426by calling the <link linkend="fiber_get_id"><code>fiber::get_id()</code></link> member
427      function. Objects of class <link linkend="class_fiber_id"><code><phrase role="identifier">fiber</phrase><phrase
428      role="special">::</phrase><phrase role="identifier">id</phrase></code></link> can be
429      copied, and used as keys in associative containers: the full range of comparison
430      operators is provided. They can also be written to an output stream using the
431      stream insertion operator, though the output format is unspecified.
432    </para>
433    <para>
434      Each instance of <link linkend="class_fiber_id"><code><phrase role="identifier">fiber</phrase><phrase
435      role="special">::</phrase><phrase role="identifier">id</phrase></code></link> either
436      refers to some fiber, or <emphasis>not-a-fiber</emphasis>. Instances that refer
437      to <emphasis>not-a-fiber</emphasis> compare equal to each other, but not equal
438      to any instances that refer to an actual fiber. The comparison operators on
439      <link linkend="class_fiber_id"><code><phrase role="identifier">fiber</phrase><phrase role="special">::</phrase><phrase
440      role="identifier">id</phrase></code></link> yield a total order for every non-equal
441      <link linkend="class_fiber_id"><code><phrase role="identifier">fiber</phrase><phrase role="special">::</phrase><phrase
442      role="identifier">id</phrase></code></link>.
443    </para>
444    <anchor id="class_launch"/>
445    <bridgehead renderas="sect3" id="fiber.fiber_mgmt.h8">
446      <phrase id="fiber.fiber_mgmt.enumeration__code__phrase_role__identifier__launch__phrase___code_"/><link
447      linkend="fiber.fiber_mgmt.enumeration__code__phrase_role__identifier__launch__phrase___code_">Enumeration
448      <code><phrase role="identifier">launch</phrase></code></link>
449    </bridgehead>
450    <para>
451      <code><phrase role="identifier">launch</phrase></code> specifies whether control
452      passes immediately into a newly-launched fiber.
453    </para>
454<programlisting><phrase role="keyword">enum</phrase> <phrase role="keyword">class</phrase> <phrase role="identifier">launch</phrase> <phrase role="special">{</phrase>
455    <phrase role="identifier">dispatch</phrase><phrase role="special">,</phrase>
456    <phrase role="identifier">post</phrase>
457<phrase role="special">};</phrase>
458</programlisting>
459    <bridgehead renderas="sect3" id="fiber.fiber_mgmt.h9">
460      <phrase id="fiber.fiber_mgmt._code__phrase_role__identifier__dispatch__phrase___code_"/><link
461      linkend="fiber.fiber_mgmt._code__phrase_role__identifier__dispatch__phrase___code_"><code><phrase
462      role="identifier">dispatch</phrase></code></link>
463    </bridgehead>
464    <variablelist>
465      <title></title>
466      <varlistentry>
467        <term>Effects:</term>
468        <listitem>
469          <para>
470            A fiber launched with <code><phrase role="identifier">launch</phrase>
471            <phrase role="special">==</phrase> <phrase role="identifier">dispatch</phrase></code>
472            is entered immediately. In other words, launching a fiber with <code><phrase
473            role="identifier">dispatch</phrase></code> suspends the caller (the previously-running
474            fiber) until the fiber scheduler has a chance to resume it later.
475          </para>
476        </listitem>
477      </varlistentry>
478    </variablelist>
479    <bridgehead renderas="sect3" id="fiber.fiber_mgmt.h10">
480      <phrase id="fiber.fiber_mgmt._code__phrase_role__identifier__post__phrase___code_"/><link
481      linkend="fiber.fiber_mgmt._code__phrase_role__identifier__post__phrase___code_"><code><phrase
482      role="identifier">post</phrase></code></link>
483    </bridgehead>
484    <variablelist>
485      <title></title>
486      <varlistentry>
487        <term>Effects:</term>
488        <listitem>
489          <para>
490            A fiber launched with <code><phrase role="identifier">launch</phrase>
491            <phrase role="special">==</phrase> <phrase role="identifier">post</phrase></code>
492            is passed to the fiber scheduler as ready, but it is not yet entered.
493            The caller (the previously-running fiber) continues executing. The newly-launched
494            fiber will be entered when the fiber scheduler has a chance to resume
495            it later.
496          </para>
497        </listitem>
498      </varlistentry>
499      <varlistentry>
500        <term>Note:</term>
501        <listitem>
502          <para>
503            If <code><phrase role="identifier">launch</phrase></code> is not explicitly
504            specified, <code><phrase role="identifier">post</phrase></code> is the
505            default.
506          </para>
507        </listitem>
508      </varlistentry>
509    </variablelist>
510    <section id="fiber.fiber_mgmt.fiber">
511      <title><anchor id="class_fiber"/><link linkend="fiber.fiber_mgmt.fiber">Class
512      <code><phrase role="identifier">fiber</phrase></code></link></title>
513<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>
514
515<phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase>
516<phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase>
517
518<phrase role="keyword">class</phrase> <phrase role="identifier">fiber</phrase> <phrase role="special">{</phrase>
519<phrase role="keyword">public</phrase><phrase role="special">:</phrase>
520    <phrase role="keyword">class</phrase> <phrase role="identifier">id</phrase><phrase role="special">;</phrase>
521
522    <phrase role="keyword">constexpr</phrase> <phrase role="identifier">fiber</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
523
524    <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>
525    <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>
526
527    <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>
528    <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>
529
530    <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>
531    <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>
532
533    <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>
534    <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>
535
536    <phrase role="special">~</phrase><phrase role="identifier">fiber</phrase><phrase role="special">();</phrase>
537
538    <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>
539
540    <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>
541
542    <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>
543
544    <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>
545
546    <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>
547
548    <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>
549
550    <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>
551
552    <phrase role="keyword">void</phrase> <phrase role="identifier">detach</phrase><phrase role="special">();</phrase>
553
554    <phrase role="keyword">void</phrase> <phrase role="identifier">join</phrase><phrase role="special">();</phrase>
555
556    <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>
557    <phrase role="identifier">PROPS</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">properties</phrase><phrase role="special">();</phrase>
558<phrase role="special">};</phrase>
559
560<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>
561
562<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>
563
564<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>
565<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>
566
567<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>
568
569<phrase role="special">}}</phrase>
570</programlisting>
571      <bridgehead renderas="sect4" id="fiber.fiber_mgmt.fiber.h0">
572        <phrase id="fiber.fiber_mgmt.fiber.default_constructor"/><link linkend="fiber.fiber_mgmt.fiber.default_constructor">Default
573        constructor</link>
574      </bridgehead>
575<programlisting><phrase role="keyword">constexpr</phrase> <phrase role="identifier">fiber</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
576</programlisting>
577      <variablelist>
578        <title></title>
579        <varlistentry>
580          <term>Effects:</term>
581          <listitem>
582            <para>
583              Constructs a <link linkend="class_fiber"><code>fiber</code></link> instance that refers to <emphasis>not-a-fiber</emphasis>.
584            </para>
585          </listitem>
586        </varlistentry>
587        <varlistentry>
588          <term>Postconditions:</term>
589          <listitem>
590            <para>
591              <code><phrase role="keyword">this</phrase><phrase role="special">-&gt;</phrase><phrase
592              role="identifier">get_id</phrase><phrase role="special">()</phrase>
593              <phrase role="special">==</phrase> <phrase role="identifier">fiber</phrase><phrase
594              role="special">::</phrase><phrase role="identifier">id</phrase><phrase
595              role="special">()</phrase></code>
596            </para>
597          </listitem>
598        </varlistentry>
599        <varlistentry>
600          <term>Throws:</term>
601          <listitem>
602            <para>
603              Nothing
604            </para>
605          </listitem>
606        </varlistentry>
607      </variablelist>
608      <anchor id="fiber_fiber"/>
609      <bridgehead renderas="sect4" id="fiber.fiber_mgmt.fiber.h1">
610        <phrase id="fiber.fiber_mgmt.fiber.constructor"/><link linkend="fiber.fiber_mgmt.fiber.constructor">Constructor</link>
611      </bridgehead>
612<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>
613<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>
614
615<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>
616<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>
617
618<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>
619<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>
620
621<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>
622<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>
623       <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>
624</programlisting>
625      <variablelist>
626        <title></title>
627        <varlistentry>
628          <term>Preconditions:</term>
629          <listitem>
630            <para>
631              <code><phrase role="identifier">Fn</phrase></code> must be copyable
632              or movable.
633            </para>
634          </listitem>
635        </varlistentry>
636        <varlistentry>
637          <term>Effects:</term>
638          <listitem>
639            <para>
640              <code><phrase role="identifier">fn</phrase></code> is copied or moved
641              into internal storage for access by the new fiber. If <link linkend="class_launch"><code>launch</code></link> is
642              specified (or defaulted) to <code><phrase role="identifier">post</phrase></code>,
643              the new fiber is marked <quote>ready</quote> and will be entered at
644              the next opportunity. If <code><phrase role="identifier">launch</phrase></code>
645              is specified as <code><phrase role="identifier">dispatch</phrase></code>,
646              the calling fiber is suspended and the new fiber is entered immediately.
647            </para>
648          </listitem>
649        </varlistentry>
650        <varlistentry>
651          <term>Postconditions:</term>
652          <listitem>
653            <para>
654              <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>
655              refers to the newly created fiber of execution.
656            </para>
657          </listitem>
658        </varlistentry>
659        <varlistentry>
660          <term>Throws:</term>
661          <listitem>
662            <para>
663              <code><phrase role="identifier">fiber_error</phrase></code> if an error
664              occurs.
665            </para>
666          </listitem>
667        </varlistentry>
668        <varlistentry>
669          <term>Note:</term>
670          <listitem>
671            <para>
672              <link linkend="stack_allocator_concept"><code><phrase role="identifier">StackAllocator</phrase></code></link>
673              is required to allocate a stack for the internal __econtext__. If
674              <code><phrase role="identifier">StackAllocator</phrase></code> is not
675              explicitly passed, the default stack allocator depends on <code><phrase
676              role="identifier">BOOST_USE_SEGMENTED_STACKS</phrase></code>: if defined,
677              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>.
678            </para>
679          </listitem>
680        </varlistentry>
681        <varlistentry>
682          <term>See also:</term>
683          <listitem>
684            <para>
685              <ulink url="http://en.cppreference.com/w/cpp/memory/allocator_arg_t"><code><phrase
686              role="identifier">std</phrase><phrase role="special">::</phrase><phrase
687              role="identifier">allocator_arg_t</phrase></code></ulink>, <link linkend="stack">Stack
688              allocation</link>
689            </para>
690          </listitem>
691        </varlistentry>
692      </variablelist>
693      <bridgehead renderas="sect4" id="fiber.fiber_mgmt.fiber.h2">
694        <phrase id="fiber.fiber_mgmt.fiber.move_constructor"/><link linkend="fiber.fiber_mgmt.fiber.move_constructor">Move
695        constructor</link>
696      </bridgehead>
697<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>
698</programlisting>
699      <variablelist>
700        <title></title>
701        <varlistentry>
702          <term>Effects:</term>
703          <listitem>
704            <para>
705              Transfers ownership of the fiber managed by <code><phrase role="identifier">other</phrase></code>
706              to the newly constructed <link linkend="class_fiber"><code>fiber</code></link> instance.
707            </para>
708          </listitem>
709        </varlistentry>
710        <varlistentry>
711          <term>Postconditions:</term>
712          <listitem>
713            <para>
714              <code><phrase role="identifier">other</phrase><phrase role="special">.</phrase><phrase
715              role="identifier">get_id</phrase><phrase role="special">()</phrase>
716              <phrase role="special">==</phrase> <phrase role="identifier">fiber</phrase><phrase
717              role="special">::</phrase><phrase role="identifier">id</phrase><phrase
718              role="special">()</phrase></code> and <code><phrase role="identifier">get_id</phrase><phrase
719              role="special">()</phrase></code> returns the value of <code><phrase
720              role="identifier">other</phrase><phrase role="special">.</phrase><phrase
721              role="identifier">get_id</phrase><phrase role="special">()</phrase></code>
722              prior to the construction
723            </para>
724          </listitem>
725        </varlistentry>
726        <varlistentry>
727          <term>Throws:</term>
728          <listitem>
729            <para>
730              Nothing
731            </para>
732          </listitem>
733        </varlistentry>
734      </variablelist>
735      <bridgehead renderas="sect4" id="fiber.fiber_mgmt.fiber.h3">
736        <phrase id="fiber.fiber_mgmt.fiber.move_assignment_operator"/><link linkend="fiber.fiber_mgmt.fiber.move_assignment_operator">Move
737        assignment operator</link>
738      </bridgehead>
739<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>
740</programlisting>
741      <variablelist>
742        <title></title>
743        <varlistentry>
744          <term>Effects:</term>
745          <listitem>
746            <para>
747              Transfers ownership of the fiber managed by <code><phrase role="identifier">other</phrase></code>
748              (if any) to <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>.
749            </para>
750          </listitem>
751        </varlistentry>
752        <varlistentry>
753          <term>Postconditions:</term>
754          <listitem>
755            <para>
756              <code><phrase role="identifier">other</phrase><phrase role="special">-&gt;</phrase><phrase
757              role="identifier">get_id</phrase><phrase role="special">()</phrase>
758              <phrase role="special">==</phrase> <phrase role="identifier">fiber</phrase><phrase
759              role="special">::</phrase><phrase role="identifier">id</phrase><phrase
760              role="special">()</phrase></code> and <code><phrase role="identifier">get_id</phrase><phrase
761              role="special">()</phrase></code> returns the value of <code><phrase
762              role="identifier">other</phrase><phrase role="special">.</phrase><phrase
763              role="identifier">get_id</phrase><phrase role="special">()</phrase></code>
764              prior to the assignment.
765            </para>
766          </listitem>
767        </varlistentry>
768        <varlistentry>
769          <term>Throws:</term>
770          <listitem>
771            <para>
772              Nothing
773            </para>
774          </listitem>
775        </varlistentry>
776      </variablelist>
777      <bridgehead renderas="sect4" id="fiber.fiber_mgmt.fiber.h4">
778        <phrase id="fiber.fiber_mgmt.fiber.destructor"/><link linkend="fiber.fiber_mgmt.fiber.destructor">Destructor</link>
779      </bridgehead>
780<programlisting><phrase role="special">~</phrase><phrase role="identifier">fiber</phrase><phrase role="special">();</phrase>
781</programlisting>
782      <variablelist>
783        <title></title>
784        <varlistentry>
785          <term>Effects:</term>
786          <listitem>
787            <para>
788              If the fiber is <link linkend="fiber_joinable"><code>fiber::joinable()</code></link>, calls std::terminate.
789              Destroys <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>.
790            </para>
791          </listitem>
792        </varlistentry>
793        <varlistentry>
794          <term>Note:</term>
795          <listitem>
796            <para>
797              The programmer must ensure that the destructor is never executed while
798              the fiber is still <link linkend="fiber_joinable"><code>fiber::joinable()</code></link>. Even if you know
799              that the fiber has completed, you must still call either <link linkend="fiber_join"><code>fiber::join()</code></link> or
800              <link linkend="fiber_detach"><code>fiber::detach()</code></link> before destroying the <code><phrase role="identifier">fiber</phrase></code>
801              object.
802            </para>
803          </listitem>
804        </varlistentry>
805      </variablelist>
806      <para>
807        <bridgehead renderas="sect4" id="fiber_joinable_bridgehead">
808  <phrase id="fiber_joinable"/>
809  <link linkend="fiber_joinable">Member function <code>joinable</code>()</link>
810</bridgehead>
811      </para>
812<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>
813</programlisting>
814      <variablelist>
815        <title></title>
816        <varlistentry>
817          <term>Returns:</term>
818          <listitem>
819            <para>
820              <code><phrase role="keyword">true</phrase></code> if <code><phrase
821              role="special">*</phrase><phrase role="keyword">this</phrase></code>
822              refers to a fiber of execution, which may or may not have completed;
823              otherwise <code><phrase role="keyword">false</phrase></code>.
824            </para>
825          </listitem>
826        </varlistentry>
827        <varlistentry>
828          <term>Throws:</term>
829          <listitem>
830            <para>
831              Nothing
832            </para>
833          </listitem>
834        </varlistentry>
835      </variablelist>
836      <para>
837        <bridgehead renderas="sect4" id="fiber_join_bridgehead">
838  <phrase id="fiber_join"/>
839  <link linkend="fiber_join">Member function <code>join</code>()</link>
840</bridgehead>
841      </para>
842<programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">join</phrase><phrase role="special">();</phrase>
843</programlisting>
844      <variablelist>
845        <title></title>
846        <varlistentry>
847          <term>Preconditions:</term>
848          <listitem>
849            <para>
850              the fiber is <link linkend="fiber_joinable"><code>fiber::joinable()</code></link>.
851            </para>
852          </listitem>
853        </varlistentry>
854        <varlistentry>
855          <term>Effects:</term>
856          <listitem>
857            <para>
858              Waits for the referenced fiber of execution to complete.
859            </para>
860          </listitem>
861        </varlistentry>
862        <varlistentry>
863          <term>Postconditions:</term>
864          <listitem>
865            <para>
866              The fiber of execution referenced on entry has completed. <code><phrase
867              role="special">*</phrase><phrase role="keyword">this</phrase></code>
868              no longer refers to any fiber of execution.
869            </para>
870          </listitem>
871        </varlistentry>
872        <varlistentry>
873          <term>Throws:</term>
874          <listitem>
875            <para>
876              <code><phrase role="identifier">fiber_error</phrase></code>
877            </para>
878          </listitem>
879        </varlistentry>
880        <varlistentry>
881          <term>Error Conditions:</term>
882          <listitem>
883            <para>
884              <emphasis role="bold">resource_deadlock_would_occur</emphasis>: if
885              <code><phrase role="keyword">this</phrase><phrase role="special">-&gt;</phrase><phrase
886              role="identifier">get_id</phrase><phrase role="special">()</phrase>
887              <phrase role="special">==</phrase> <phrase role="identifier">boost</phrase><phrase
888              role="special">::</phrase><phrase role="identifier">this_fiber</phrase><phrase
889              role="special">::</phrase><phrase role="identifier">get_id</phrase><phrase
890              role="special">()</phrase></code>. <emphasis role="bold">invalid_argument</emphasis>:
891              if the fiber is not <link linkend="fiber_joinable"><code>fiber::joinable()</code></link>.
892            </para>
893          </listitem>
894        </varlistentry>
895      </variablelist>
896      <para>
897        <bridgehead renderas="sect4" id="fiber_detach_bridgehead">
898  <phrase id="fiber_detach"/>
899  <link linkend="fiber_detach">Member function <code>detach</code>()</link>
900</bridgehead>
901      </para>
902<programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">detach</phrase><phrase role="special">();</phrase>
903</programlisting>
904      <variablelist>
905        <title></title>
906        <varlistentry>
907          <term>Preconditions:</term>
908          <listitem>
909            <para>
910              the fiber is <link linkend="fiber_joinable"><code>fiber::joinable()</code></link>.
911            </para>
912          </listitem>
913        </varlistentry>
914        <varlistentry>
915          <term>Effects:</term>
916          <listitem>
917            <para>
918              The fiber of execution becomes detached, and no longer has an associated
919              <link linkend="class_fiber"><code>fiber</code></link> object.
920            </para>
921          </listitem>
922        </varlistentry>
923        <varlistentry>
924          <term>Postconditions:</term>
925          <listitem>
926            <para>
927              <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>
928              no longer refers to any fiber of execution.
929            </para>
930          </listitem>
931        </varlistentry>
932        <varlistentry>
933          <term>Throws:</term>
934          <listitem>
935            <para>
936              <code><phrase role="identifier">fiber_error</phrase></code>
937            </para>
938          </listitem>
939        </varlistentry>
940        <varlistentry>
941          <term>Error Conditions:</term>
942          <listitem>
943            <para>
944              <emphasis role="bold">invalid_argument</emphasis>: if the fiber is
945              not <link linkend="fiber_joinable"><code>fiber::joinable()</code></link>.
946            </para>
947          </listitem>
948        </varlistentry>
949      </variablelist>
950      <para>
951        <bridgehead renderas="sect4" id="fiber_get_id_bridgehead">
952  <phrase id="fiber_get_id"/>
953  <link linkend="fiber_get_id">Member function <code>get_id</code>()</link>
954</bridgehead>
955      </para>
956<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>
957</programlisting>
958      <variablelist>
959        <title></title>
960        <varlistentry>
961          <term>Returns:</term>
962          <listitem>
963            <para>
964              If <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>
965              refers to a fiber of execution, an instance of <link linkend="class_fiber_id"><code><phrase
966              role="identifier">fiber</phrase><phrase role="special">::</phrase><phrase
967              role="identifier">id</phrase></code></link> that represents that fiber. Otherwise
968              returns a default-constructed <link linkend="class_fiber_id"><code><phrase role="identifier">fiber</phrase><phrase
969              role="special">::</phrase><phrase role="identifier">id</phrase></code></link>.
970            </para>
971          </listitem>
972        </varlistentry>
973        <varlistentry>
974          <term>Throws:</term>
975          <listitem>
976            <para>
977              Nothing
978            </para>
979          </listitem>
980        </varlistentry>
981        <varlistentry>
982          <term>See also:</term>
983          <listitem>
984            <para>
985              <link linkend="this_fiber_get_id"><code>this_fiber::get_id()</code></link>
986            </para>
987          </listitem>
988        </varlistentry>
989      </variablelist>
990      <para>
991        <bridgehead renderas="sect4" id="fiber_properties_bridgehead">
992  <phrase id="fiber_properties"/>
993  <link linkend="fiber_properties">Templated member
994        function <code>properties</code>()</link>
995</bridgehead>
996      </para>
997<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>
998<phrase role="identifier">PROPS</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">properties</phrase><phrase role="special">();</phrase>
999</programlisting>
1000      <variablelist>
1001        <title></title>
1002        <varlistentry>
1003          <term>Preconditions:</term>
1004          <listitem>
1005            <para>
1006              <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>
1007              refers to a fiber of execution. <link linkend="use_scheduling_algorithm"><code>use_scheduling_algorithm()</code></link> has
1008              been called from this thread with a subclass of <link linkend="class_algorithm_with_properties"><code>algorithm_with_properties&lt;&gt;</code></link> with
1009              the same template argument <code><phrase role="identifier">PROPS</phrase></code>.
1010            </para>
1011          </listitem>
1012        </varlistentry>
1013        <varlistentry>
1014          <term>Returns:</term>
1015          <listitem>
1016            <para>
1017              a reference to the scheduler properties instance for <code><phrase
1018              role="special">*</phrase><phrase role="keyword">this</phrase></code>.
1019            </para>
1020          </listitem>
1021        </varlistentry>
1022        <varlistentry>
1023          <term>Throws:</term>
1024          <listitem>
1025            <para>
1026              <code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase
1027              role="identifier">bad_cast</phrase></code> if <code><phrase role="identifier">use_scheduling_algorithm</phrase><phrase
1028              role="special">()</phrase></code> was called with a <code><phrase role="identifier">algorithm_with_properties</phrase></code>
1029              subclass with some other template parameter than <code><phrase role="identifier">PROPS</phrase></code>.
1030            </para>
1031          </listitem>
1032        </varlistentry>
1033        <varlistentry>
1034          <term>Note:</term>
1035          <listitem>
1036            <para>
1037              <link linkend="class_algorithm_with_properties"><code>algorithm_with_properties&lt;&gt;</code></link> provides
1038              a way for a user-coded scheduler to associate extended properties,
1039              such as priority, with a fiber instance. This method allows access
1040              to those user-provided properties.
1041            </para>
1042          </listitem>
1043        </varlistentry>
1044        <varlistentry>
1045          <term>See also:</term>
1046          <listitem>
1047            <para>
1048              <link linkend="custom">Customization</link>
1049            </para>
1050          </listitem>
1051        </varlistentry>
1052      </variablelist>
1053      <para>
1054        <bridgehead renderas="sect4" id="fiber_swap_bridgehead">
1055  <phrase id="fiber_swap"/>
1056  <link linkend="fiber_swap">Member function <code>swap</code>()</link>
1057</bridgehead>
1058      </para>
1059<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>
1060</programlisting>
1061      <variablelist>
1062        <title></title>
1063        <varlistentry>
1064          <term>Effects:</term>
1065          <listitem>
1066            <para>
1067              Exchanges the fiber of execution associated with <code><phrase role="special">*</phrase><phrase
1068              role="keyword">this</phrase></code> and <code><phrase role="identifier">other</phrase></code>,
1069              so <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>
1070              becomes associated with the fiber formerly associated with <code><phrase
1071              role="identifier">other</phrase></code>, and vice-versa.
1072            </para>
1073          </listitem>
1074        </varlistentry>
1075        <varlistentry>
1076          <term>Postconditions:</term>
1077          <listitem>
1078            <para>
1079              <code><phrase role="keyword">this</phrase><phrase role="special">-&gt;</phrase><phrase
1080              role="identifier">get_id</phrase><phrase role="special">()</phrase></code>
1081              returns the same value as <code><phrase role="identifier">other</phrase><phrase
1082              role="special">.</phrase><phrase role="identifier">get_id</phrase><phrase
1083              role="special">()</phrase></code> prior to the call. <code><phrase
1084              role="identifier">other</phrase><phrase role="special">.</phrase><phrase
1085              role="identifier">get_id</phrase><phrase role="special">()</phrase></code>
1086              returns the same value as <code><phrase role="keyword">this</phrase><phrase
1087              role="special">-&gt;</phrase><phrase role="identifier">get_id</phrase><phrase
1088              role="special">()</phrase></code> prior to the call.
1089            </para>
1090          </listitem>
1091        </varlistentry>
1092        <varlistentry>
1093          <term>Throws:</term>
1094          <listitem>
1095            <para>
1096              Nothing
1097            </para>
1098          </listitem>
1099        </varlistentry>
1100      </variablelist>
1101      <para>
1102        <bridgehead renderas="sect4" id="swap_for_fiber_bridgehead">
1103  <phrase id="swap_for_fiber"/>
1104  <link linkend="swap_for_fiber">Non-member function
1105        <code>swap()</code></link>
1106</bridgehead>
1107      </para>
1108<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>
1109</programlisting>
1110      <variablelist>
1111        <title></title>
1112        <varlistentry>
1113          <term>Effects:</term>
1114          <listitem>
1115            <para>
1116              Same as <code><phrase role="identifier">l</phrase><phrase role="special">.</phrase><phrase
1117              role="identifier">swap</phrase><phrase role="special">(</phrase> <phrase
1118              role="identifier">r</phrase><phrase role="special">)</phrase></code>.
1119            </para>
1120          </listitem>
1121        </varlistentry>
1122        <varlistentry>
1123          <term>Throws:</term>
1124          <listitem>
1125            <para>
1126              Nothing
1127            </para>
1128          </listitem>
1129        </varlistentry>
1130      </variablelist>
1131      <para>
1132        <bridgehead renderas="sect4" id="operator&lt;_bridgehead">
1133  <phrase id="operator&lt;"/>
1134  <link linkend="operator&lt;">Non-member function <code>operator&lt;()</code></link>
1135</bridgehead>
1136      </para>
1137<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>
1138</programlisting>
1139      <variablelist>
1140        <title></title>
1141        <varlistentry>
1142          <term>Returns:</term>
1143          <listitem>
1144            <para>
1145              <code><phrase role="keyword">true</phrase></code> if <code><phrase
1146              role="identifier">l</phrase><phrase role="special">.</phrase><phrase
1147              role="identifier">get_id</phrase><phrase role="special">()</phrase>
1148              <phrase role="special">&lt;</phrase> <phrase role="identifier">r</phrase><phrase
1149              role="special">.</phrase><phrase role="identifier">get_id</phrase><phrase
1150              role="special">()</phrase></code> is <code><phrase role="keyword">true</phrase></code>,
1151              false otherwise.
1152            </para>
1153          </listitem>
1154        </varlistentry>
1155        <varlistentry>
1156          <term>Throws:</term>
1157          <listitem>
1158            <para>
1159              Nothing.
1160            </para>
1161          </listitem>
1162        </varlistentry>
1163      </variablelist>
1164      <para>
1165        <bridgehead renderas="sect4" id="use_scheduling_algorithm_bridgehead">
1166  <phrase id="use_scheduling_algorithm"/>
1167  <link linkend="use_scheduling_algorithm">Non-member
1168        function <code>use_scheduling_algorithm()</code></link>
1169</bridgehead>
1170      </para>
1171<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>
1172<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>
1173</programlisting>
1174      <variablelist>
1175        <title></title>
1176        <varlistentry>
1177          <term>Effects:</term>
1178          <listitem>
1179            <para>
1180              Directs <emphasis role="bold">Boost.Fiber</emphasis> to use <code><phrase
1181              role="identifier">SchedAlgo</phrase></code>, which must be a concrete
1182              subclass of <link linkend="class_algorithm"><code>algorithm</code></link>, as the scheduling algorithm for
1183              all fibers in the current thread. Pass any required <code><phrase role="identifier">SchedAlgo</phrase></code>
1184              constructor arguments as <code><phrase role="identifier">args</phrase></code>.
1185            </para>
1186          </listitem>
1187        </varlistentry>
1188        <varlistentry>
1189          <term>Note:</term>
1190          <listitem>
1191            <para>
1192              If you want a given thread to use a non-default scheduling algorithm,
1193              make that thread call <code><phrase role="identifier">use_scheduling_algorithm</phrase><phrase
1194              role="special">()</phrase></code> before any other <emphasis role="bold">Boost.Fiber</emphasis>
1195              entry point. If no scheduler has been set for the current thread by
1196              the time <emphasis role="bold">Boost.Fiber</emphasis> needs to use
1197              it, the library will create a default <link linkend="class_round_robin"><code>round_robin</code></link> instance
1198              for this thread.
1199            </para>
1200          </listitem>
1201        </varlistentry>
1202        <varlistentry>
1203          <term>Throws:</term>
1204          <listitem>
1205            <para>
1206              Nothing
1207            </para>
1208          </listitem>
1209        </varlistentry>
1210        <varlistentry>
1211          <term>See also:</term>
1212          <listitem>
1213            <para>
1214              <link linkend="scheduling">Scheduling</link>, <link linkend="custom">Customization</link>
1215            </para>
1216          </listitem>
1217        </varlistentry>
1218      </variablelist>
1219      <para>
1220        <bridgehead renderas="sect4" id="has_ready_fibers_bridgehead">
1221  <phrase id="has_ready_fibers"/>
1222  <link linkend="has_ready_fibers">Non-member function
1223        <code>has_ready_fibers()</code></link>
1224</bridgehead>
1225      </para>
1226<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>
1227</programlisting>
1228      <variablelist>
1229        <title></title>
1230        <varlistentry>
1231          <term>Returns:</term>
1232          <listitem>
1233            <para>
1234              <code><phrase role="keyword">true</phrase></code> if scheduler has
1235              fibers ready to run.
1236            </para>
1237          </listitem>
1238        </varlistentry>
1239        <varlistentry>
1240          <term>Throws:</term>
1241          <listitem>
1242            <para>
1243              Nothing
1244            </para>
1245          </listitem>
1246        </varlistentry>
1247        <varlistentry>
1248          <term>Note:</term>
1249          <listitem>
1250            <para>
1251              Can be used for work-stealing to find an idle scheduler.
1252            </para>
1253          </listitem>
1254        </varlistentry>
1255      </variablelist>
1256    </section>
1257    <section id="fiber.fiber_mgmt.id">
1258      <title><anchor id="class_id"/><link linkend="fiber.fiber_mgmt.id">Class fiber::id</link></title>
1259<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>
1260
1261<phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase>
1262<phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase>
1263
1264<phrase role="keyword">class</phrase> <phrase role="identifier">id</phrase> <phrase role="special">{</phrase>
1265<phrase role="keyword">public</phrase><phrase role="special">:</phrase>
1266    <phrase role="keyword">constexpr</phrase> <phrase role="identifier">id</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
1267
1268    <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>
1269
1270    <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>
1271
1272    <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>
1273
1274    <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>
1275
1276    <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>
1277
1278    <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>
1279
1280    <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>
1281    <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>
1282    <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>
1283<phrase role="special">};</phrase>
1284
1285<phrase role="special">}}</phrase>
1286</programlisting>
1287      <bridgehead renderas="sect4" id="fiber.fiber_mgmt.id.h0">
1288        <phrase id="fiber.fiber_mgmt.id.constructor"/><link linkend="fiber.fiber_mgmt.id.constructor">Constructor</link>
1289      </bridgehead>
1290<programlisting><phrase role="keyword">constexpr</phrase> <phrase role="identifier">id</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
1291</programlisting>
1292      <variablelist>
1293        <title></title>
1294        <varlistentry>
1295          <term>Effects:</term>
1296          <listitem>
1297            <para>
1298              Represents an instance of <emphasis>not-a-fiber</emphasis>.
1299            </para>
1300          </listitem>
1301        </varlistentry>
1302        <varlistentry>
1303          <term>Throws:</term>
1304          <listitem>
1305            <para>
1306              Nothing.
1307            </para>
1308          </listitem>
1309        </varlistentry>
1310      </variablelist>
1311      <para>
1312        <bridgehead renderas="sect4" id="id_operator_equal_bridgehead">
1313  <phrase id="id_operator_equal"/>
1314  <link linkend="id_operator_equal">Member function
1315        <code>operator==</code>()</link>
1316</bridgehead>
1317      </para>
1318<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>
1319</programlisting>
1320      <variablelist>
1321        <title></title>
1322        <varlistentry>
1323          <term>Returns:</term>
1324          <listitem>
1325            <para>
1326              <code><phrase role="keyword">true</phrase></code> if <code><phrase
1327              role="special">*</phrase><phrase role="keyword">this</phrase></code>
1328              and <code><phrase role="identifier">other</phrase></code> represent
1329              the same fiber, or both represent <emphasis>not-a-fiber</emphasis>,
1330              <code><phrase role="keyword">false</phrase></code> otherwise.
1331            </para>
1332          </listitem>
1333        </varlistentry>
1334        <varlistentry>
1335          <term>Throws:</term>
1336          <listitem>
1337            <para>
1338              Nothing.
1339            </para>
1340          </listitem>
1341        </varlistentry>
1342      </variablelist>
1343      <para>
1344        <bridgehead renderas="sect4" id="id_operator_not_equal_bridgehead">
1345  <phrase id="id_operator_not_equal"/>
1346  <link linkend="id_operator_not_equal">Member
1347        function <code>operator!=</code>()</link>
1348</bridgehead>
1349      </para>
1350<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>
1351</programlisting>
1352      <variablelist>
1353        <title></title>
1354        <varlistentry>
1355          <term>Returns:</term>
1356          <listitem>
1357            <para>
1358              <code>! (other == * this)</code>
1359            </para>
1360          </listitem>
1361        </varlistentry>
1362        <varlistentry>
1363          <term>Throws:</term>
1364          <listitem>
1365            <para>
1366              Nothing.
1367            </para>
1368          </listitem>
1369        </varlistentry>
1370      </variablelist>
1371      <para>
1372        <bridgehead renderas="sect4" id="id_operator_less_bridgehead">
1373  <phrase id="id_operator_less"/>
1374  <link linkend="id_operator_less">Member function
1375        <code>operator&lt;</code>()</link>
1376</bridgehead>
1377      </para>
1378<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>
1379</programlisting>
1380      <variablelist>
1381        <title></title>
1382        <varlistentry>
1383          <term>Returns:</term>
1384          <listitem>
1385            <para>
1386              <code><phrase role="keyword">true</phrase></code> if <code><phrase
1387              role="special">*</phrase><phrase role="keyword">this</phrase> <phrase
1388              role="special">!=</phrase> <phrase role="identifier">other</phrase></code>
1389              is true and the implementation-defined total order of <code><phrase
1390              role="identifier">fiber</phrase><phrase role="special">::</phrase><phrase
1391              role="identifier">id</phrase></code> values places <code><phrase role="special">*</phrase><phrase
1392              role="keyword">this</phrase></code> before <code><phrase role="identifier">other</phrase></code>,
1393              false otherwise.
1394            </para>
1395          </listitem>
1396        </varlistentry>
1397        <varlistentry>
1398          <term>Throws:</term>
1399          <listitem>
1400            <para>
1401              Nothing.
1402            </para>
1403          </listitem>
1404        </varlistentry>
1405      </variablelist>
1406      <para>
1407        <bridgehead renderas="sect4" id="id_operator_greater_bridgehead">
1408  <phrase id="id_operator_greater"/>
1409  <link linkend="id_operator_greater">Member
1410        function <code>operator&gt;</code>()</link>
1411</bridgehead>
1412      </para>
1413<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>
1414</programlisting>
1415      <variablelist>
1416        <title></title>
1417        <varlistentry>
1418          <term>Returns:</term>
1419          <listitem>
1420            <para>
1421              <code><phrase role="identifier">other</phrase> <phrase role="special">&lt;</phrase>
1422              <phrase role="special">*</phrase> <phrase role="keyword">this</phrase></code>
1423            </para>
1424          </listitem>
1425        </varlistentry>
1426        <varlistentry>
1427          <term>Throws:</term>
1428          <listitem>
1429            <para>
1430              Nothing.
1431            </para>
1432          </listitem>
1433        </varlistentry>
1434      </variablelist>
1435      <para>
1436        <bridgehead renderas="sect4" id="id_operator_less_equal_bridgehead">
1437  <phrase id="id_operator_less_equal"/>
1438  <link linkend="id_operator_less_equal">Member
1439        function <code>operator&lt;=</code>()</link>
1440</bridgehead>
1441      </para>
1442<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>
1443</programlisting>
1444      <variablelist>
1445        <title></title>
1446        <varlistentry>
1447          <term>Returns:</term>
1448          <listitem>
1449            <para>
1450              <code><phrase role="special">!</phrase> <phrase role="special">(</phrase><phrase
1451              role="identifier">other</phrase> <phrase role="special">&lt;</phrase>
1452              <phrase role="special">*</phrase> <phrase role="keyword">this</phrase><phrase
1453              role="special">)</phrase></code>
1454            </para>
1455          </listitem>
1456        </varlistentry>
1457        <varlistentry>
1458          <term>Throws:</term>
1459          <listitem>
1460            <para>
1461              Nothing.
1462            </para>
1463          </listitem>
1464        </varlistentry>
1465      </variablelist>
1466      <para>
1467        <bridgehead renderas="sect4" id="id_operator_greater_equal_bridgehead">
1468  <phrase id="id_operator_greater_equal"/>
1469  <link linkend="id_operator_greater_equal">Member
1470        function <code>operator&gt;=</code>()</link>
1471</bridgehead>
1472      </para>
1473<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>
1474</programlisting>
1475      <variablelist>
1476        <title></title>
1477        <varlistentry>
1478          <term>Returns:</term>
1479          <listitem>
1480            <para>
1481              <code><phrase role="special">!</phrase> <phrase role="special">(*</phrase>
1482              <phrase role="keyword">this</phrase> <phrase role="special">&lt;</phrase>
1483              <phrase role="identifier">other</phrase><phrase role="special">)</phrase></code>
1484            </para>
1485          </listitem>
1486        </varlistentry>
1487        <varlistentry>
1488          <term>Throws:</term>
1489          <listitem>
1490            <para>
1491              Nothing.
1492            </para>
1493          </listitem>
1494        </varlistentry>
1495      </variablelist>
1496      <bridgehead renderas="sect4" id="fiber.fiber_mgmt.id.h1">
1497        <phrase id="fiber.fiber_mgmt.id.operator_lt__lt_"/><link linkend="fiber.fiber_mgmt.id.operator_lt__lt_">operator&lt;&lt;</link>
1498      </bridgehead>
1499<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>
1500<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>
1501<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>
1502</programlisting>
1503      <variablelist>
1504        <title></title>
1505        <varlistentry>
1506          <term>Efects:</term>
1507          <listitem>
1508            <para>
1509              Writes the representation of <code><phrase role="identifier">other</phrase></code>
1510              to stream <code><phrase role="identifier">os</phrase></code>. The representation
1511              is unspecified.
1512            </para>
1513          </listitem>
1514        </varlistentry>
1515        <varlistentry>
1516          <term>Returns:</term>
1517          <listitem>
1518            <para>
1519              <code><phrase role="identifier">os</phrase></code>
1520            </para>
1521          </listitem>
1522        </varlistentry>
1523      </variablelist>
1524    </section>
1525    <section id="fiber.fiber_mgmt.this_fiber">
1526      <title><link linkend="fiber.fiber_mgmt.this_fiber">Namespace this_fiber</link></title>
1527      <para>
1528        In general, <code><phrase role="identifier">this_fiber</phrase></code> operations
1529        may be called from the <quote>main</quote> fiber &mdash; the fiber on which function
1530        <code><phrase role="identifier">main</phrase><phrase role="special">()</phrase></code>
1531        is entered &mdash; as well as from an explicitly-launched thread&#8217;s thread-function.
1532        That is, in many respects the main fiber on each thread can be treated like
1533        an explicitly-launched fiber.
1534      </para>
1535<programlisting><phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase>
1536<phrase role="keyword">namespace</phrase> <phrase role="identifier">this_fiber</phrase> <phrase role="special">{</phrase>
1537
1538<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>
1539<phrase role="keyword">void</phrase> <phrase role="identifier">yield</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
1540<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>
1541<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>
1542<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>
1543<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>
1544<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>
1545<phrase role="identifier">PROPS</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">properties</phrase><phrase role="special">();</phrase>
1546
1547<phrase role="special">}}</phrase>
1548</programlisting>
1549      <para>
1550        <bridgehead renderas="sect4" id="this_fiber_get_id_bridgehead">
1551  <phrase id="this_fiber_get_id"/>
1552  <link linkend="this_fiber_get_id">Non-member
1553        function <code>this_fiber::get_id()</code></link>
1554</bridgehead>
1555      </para>
1556<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>
1557
1558<phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase>
1559<phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase>
1560
1561<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>
1562
1563<phrase role="special">}}</phrase>
1564</programlisting>
1565      <variablelist>
1566        <title></title>
1567        <varlistentry>
1568          <term>Returns:</term>
1569          <listitem>
1570            <para>
1571              An instance of <link linkend="class_fiber_id"><code><phrase role="identifier">fiber</phrase><phrase
1572              role="special">::</phrase><phrase role="identifier">id</phrase></code></link> that
1573              represents the currently executing fiber.
1574            </para>
1575          </listitem>
1576        </varlistentry>
1577        <varlistentry>
1578          <term>Throws:</term>
1579          <listitem>
1580            <para>
1581              Nothing.
1582            </para>
1583          </listitem>
1584        </varlistentry>
1585      </variablelist>
1586      <para>
1587        <bridgehead renderas="sect4" id="this_fiber_sleep_until_bridgehead">
1588  <phrase id="this_fiber_sleep_until"/>
1589  <link linkend="this_fiber_sleep_until">Non-member
1590        function <code>this_fiber::sleep_until()</code></link>
1591</bridgehead>
1592      </para>
1593<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>
1594
1595<phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase>
1596<phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase>
1597
1598<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>
1599<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>
1600
1601<phrase role="special">}}</phrase>
1602</programlisting>
1603      <variablelist>
1604        <title></title>
1605        <varlistentry>
1606          <term>Effects:</term>
1607          <listitem>
1608            <para>
1609              Suspends the current fiber until the time point specified by <code><phrase
1610              role="identifier">abs_time</phrase></code> has been reached.
1611            </para>
1612          </listitem>
1613        </varlistentry>
1614        <varlistentry>
1615          <term>Throws:</term>
1616          <listitem>
1617            <para>
1618              timeout-related exceptions.
1619            </para>
1620          </listitem>
1621        </varlistentry>
1622        <varlistentry>
1623          <term>Note:</term>
1624          <listitem>
1625            <para>
1626              The current fiber will not resume before <code><phrase role="identifier">abs_time</phrase></code>,
1627              but there are no guarantees about how soon after <code><phrase role="identifier">abs_time</phrase></code>
1628              it might resume.
1629            </para>
1630          </listitem>
1631        </varlistentry>
1632        <varlistentry>
1633          <term>Note:</term>
1634          <listitem>
1635            <para>
1636              <quote>timeout-related exceptions</quote> are as defined in the C++
1637              Standard, section <emphasis role="bold">30.2.4 Timing specifications
1638              [thread.req.timing]</emphasis>: <quote>A function that takes an argument
1639              which specifies a timeout will throw if, during its execution, a clock,
1640              time point, or time duration throws an exception. Such exceptions are
1641              referred to as <emphasis>timeout-related exceptions.</emphasis></quote>
1642            </para>
1643          </listitem>
1644        </varlistentry>
1645      </variablelist>
1646      <para>
1647        <bridgehead renderas="sect4" id="this_fiber_sleep_for_bridgehead">
1648  <phrase id="this_fiber_sleep_for"/>
1649  <link linkend="this_fiber_sleep_for">Non-member
1650        function <code>this_fiber::sleep_for()</code></link>
1651</bridgehead>
1652      </para>
1653<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>
1654
1655<phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase>
1656<phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase>
1657
1658<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>
1659<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>
1660
1661<phrase role="special">}}</phrase>
1662</programlisting>
1663      <variablelist>
1664        <title></title>
1665        <varlistentry>
1666          <term>Effects:</term>
1667          <listitem>
1668            <para>
1669              Suspends the current fiber until the time duration specified by <code><phrase
1670              role="identifier">rel_time</phrase></code> has elapsed.
1671            </para>
1672          </listitem>
1673        </varlistentry>
1674        <varlistentry>
1675          <term>Throws:</term>
1676          <listitem>
1677            <para>
1678              timeout-related exceptions.
1679            </para>
1680          </listitem>
1681        </varlistentry>
1682        <varlistentry>
1683          <term>Note:</term>
1684          <listitem>
1685            <para>
1686              The current fiber will not resume before <code><phrase role="identifier">rel_time</phrase></code>
1687              has elapsed, but there are no guarantees about how soon after that
1688              it might resume.
1689            </para>
1690          </listitem>
1691        </varlistentry>
1692      </variablelist>
1693      <para>
1694        <bridgehead renderas="sect4" id="this_fiber_yield_bridgehead">
1695  <phrase id="this_fiber_yield"/>
1696  <link linkend="this_fiber_yield">Non-member function
1697        <code>this_fiber::yield()</code></link>
1698</bridgehead>
1699      </para>
1700<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>
1701
1702<phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase>
1703<phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase>
1704
1705<phrase role="keyword">void</phrase> <phrase role="identifier">yield</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
1706
1707<phrase role="special">}}</phrase>
1708</programlisting>
1709      <variablelist>
1710        <title></title>
1711        <varlistentry>
1712          <term>Effects:</term>
1713          <listitem>
1714            <para>
1715              Relinquishes execution control, allowing other fibers to run.
1716            </para>
1717          </listitem>
1718        </varlistentry>
1719        <varlistentry>
1720          <term>Throws:</term>
1721          <listitem>
1722            <para>
1723              Nothing.
1724            </para>
1725          </listitem>
1726        </varlistentry>
1727        <varlistentry>
1728          <term>Note:</term>
1729          <listitem>
1730            <para>
1731              A fiber that calls <code><phrase role="identifier">yield</phrase><phrase
1732              role="special">()</phrase></code> is not suspended: it is immediately
1733              passed to the scheduler as ready to run.
1734            </para>
1735          </listitem>
1736        </varlistentry>
1737      </variablelist>
1738      <para>
1739        <bridgehead renderas="sect4" id="this_fiber_properties_bridgehead">
1740  <phrase id="this_fiber_properties"/>
1741  <link linkend="this_fiber_properties">Non-member
1742        function <code>this_fiber::properties()</code></link>
1743</bridgehead>
1744      </para>
1745<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>
1746
1747<phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase>
1748<phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase>
1749
1750<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>
1751<phrase role="identifier">PROPS</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">properties</phrase><phrase role="special">();</phrase>
1752
1753<phrase role="special">}}</phrase>
1754</programlisting>
1755      <variablelist>
1756        <title></title>
1757        <varlistentry>
1758          <term>Preconditions:</term>
1759          <listitem>
1760            <para>
1761              <link linkend="use_scheduling_algorithm"><code>use_scheduling_algorithm()</code></link> has been called from
1762              this thread with a subclass of <link linkend="class_algorithm_with_properties"><code>algorithm_with_properties&lt;&gt;</code></link> with
1763              the same template argument <code><phrase role="identifier">PROPS</phrase></code>.
1764            </para>
1765          </listitem>
1766        </varlistentry>
1767        <varlistentry>
1768          <term>Returns:</term>
1769          <listitem>
1770            <para>
1771              a reference to the scheduler properties instance for the currently
1772              running fiber.
1773            </para>
1774          </listitem>
1775        </varlistentry>
1776        <varlistentry>
1777          <term>Throws:</term>
1778          <listitem>
1779            <para>
1780              <code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase
1781              role="identifier">bad_cast</phrase></code> if <code><phrase role="identifier">use_scheduling_algorithm</phrase><phrase
1782              role="special">()</phrase></code> was called with an <code><phrase
1783              role="identifier">algorithm_with_properties</phrase></code> subclass
1784              with some other template parameter than <code><phrase role="identifier">PROPS</phrase></code>.
1785            </para>
1786          </listitem>
1787        </varlistentry>
1788        <varlistentry>
1789          <term>Note:</term>
1790          <listitem>
1791            <para>
1792              <link linkend="class_algorithm_with_properties"><code>algorithm_with_properties&lt;&gt;</code></link> provides
1793              a way for a user-coded scheduler to associate extended properties,
1794              such as priority, with a fiber instance. This function allows access
1795              to those user-provided properties.
1796            </para>
1797          </listitem>
1798        </varlistentry>
1799        <varlistentry>
1800          <term>Note:</term>
1801          <listitem>
1802            <para>
1803              The first time this function is called from the main fiber of a thread,
1804              it may internally yield, permitting other fibers to run.
1805            </para>
1806          </listitem>
1807        </varlistentry>
1808        <varlistentry>
1809          <term>See also:</term>
1810          <listitem>
1811            <para>
1812              <link linkend="custom">Customization</link>
1813            </para>
1814          </listitem>
1815        </varlistentry>
1816      </variablelist>
1817    </section>
1818  </section>
1819  <section id="fiber.scheduling">
1820    <title><anchor id="scheduling"/><link linkend="fiber.scheduling">Scheduling</link></title>
1821    <para>
1822      The fibers in a thread are coordinated by a fiber manager. Fibers trade control
1823      cooperatively, rather than preemptively: the currently-running fiber retains
1824      control until it invokes some operation that passes control to the manager.
1825      Each time a fiber suspends (or yields), the fiber manager consults a scheduler
1826      to determine which fiber will run next.
1827    </para>
1828    <para>
1829      <emphasis role="bold">Boost.Fiber</emphasis> provides the fiber manager, but
1830      the scheduler is a customization point. (See <link linkend="custom">Customization</link>.)
1831    </para>
1832    <para>
1833      Each thread has its own scheduler. Different threads in a process may use different
1834      schedulers. By default, <emphasis role="bold">Boost.Fiber</emphasis> implicitly
1835      instantiates <link linkend="class_round_robin"><code>round_robin</code></link> as the scheduler for each thread.
1836    </para>
1837    <para>
1838      You are explicitly permitted to code your own <link linkend="class_algorithm"><code>algorithm</code></link> subclass.
1839      For the most part, your <code><phrase role="identifier">algorithm</phrase></code>
1840      subclass need not defend against cross-thread calls: the fiber manager intercepts
1841      and defers such calls. Most <code><phrase role="identifier">algorithm</phrase></code>
1842      methods are only ever directly called from the thread whose fibers it is managing
1843      &mdash; with exceptions as documented below.
1844    </para>
1845    <para>
1846      Your <code><phrase role="identifier">algorithm</phrase></code> subclass is
1847      engaged on a particular thread by calling <link linkend="use_scheduling_algorithm"><code>use_scheduling_algorithm()</code></link>:
1848    </para>
1849<programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">thread_fn</phrase><phrase role="special">()</phrase> <phrase role="special">{</phrase>
1850    <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>
1851    <phrase role="special">...</phrase>
1852<phrase role="special">}</phrase>
1853</programlisting>
1854    <para>
1855      A scheduler class must implement interface <link linkend="class_algorithm"><code>algorithm</code></link>. <emphasis
1856      role="bold">Boost.Fiber</emphasis> provides schedulers: <link linkend="class_round_robin"><code>round_robin</code></link>,
1857      <link linkend="class_work_stealing"><code>work_stealing</code></link>, <link linkend="class_numa_work_stealing"><code>numa::work_stealing</code></link> and
1858      <link linkend="class_shared_work"><code>shared_work</code></link>.
1859    </para>
1860<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>
1861    <phrase role="comment">// thread registers itself at work-stealing scheduler</phrase>
1862    <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>
1863    <phrase role="special">...</phrase>
1864<phrase role="special">}</phrase>
1865
1866<phrase role="comment">// count of logical cpus</phrase>
1867<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>
1868<phrase role="comment">// start worker-threads first</phrase>
1869<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>
1870<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>
1871    <phrase role="comment">// spawn thread</phrase>
1872    <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>
1873<phrase role="special">}</phrase>
1874<phrase role="comment">// start-thread registers itself at work-stealing scheduler</phrase>
1875<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>
1876<phrase role="special">...</phrase>
1877</programlisting>
1878    <para>
1879      The example spawns as many threads as <code><phrase role="identifier">std</phrase><phrase
1880      role="special">::</phrase><phrase role="identifier">thread</phrase><phrase
1881      role="special">::</phrase><phrase role="identifier">hardware_concurrency</phrase><phrase
1882      role="special">()</phrase></code> returns. Each thread runs a <link linkend="class_work_stealing"><code>work_stealing</code></link> scheduler.
1883      Each instance of this scheduler needs to know how many threads run the work-stealing
1884      scheduler in the program. If the local queue of one thread runs out of ready
1885      fibers, the thread tries to steal a ready fiber from another thread running
1886      this scheduler.
1887    </para>
1888    <para>
1889      <bridgehead renderas="sect4" id="class_algorithm_bridgehead">
1890  <phrase id="class_algorithm"/>
1891  <link linkend="class_algorithm">Class <code>algorithm</code></link>
1892</bridgehead>
1893    </para>
1894    <para>
1895      <code><phrase role="identifier">algorithm</phrase></code> is the abstract base
1896      class defining the interface that a fiber scheduler must implement.
1897    </para>
1898<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>
1899
1900<phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase>
1901<phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase>
1902<phrase role="keyword">namespace</phrase> <phrase role="identifier">algo</phrase> <phrase role="special">{</phrase>
1903
1904<phrase role="keyword">struct</phrase> <phrase role="identifier">algorithm</phrase> <phrase role="special">{</phrase>
1905    <phrase role="keyword">virtual</phrase> <phrase role="special">~</phrase><phrase role="identifier">algorithm</phrase><phrase role="special">();</phrase>
1906
1907    <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>
1908
1909    <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>
1910
1911    <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>
1912
1913    <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>
1914
1915    <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>
1916<phrase role="special">};</phrase>
1917
1918<phrase role="special">}}}</phrase>
1919</programlisting>
1920    <para>
1921      <bridgehead renderas="sect4" id="algorithm_awakened_bridgehead">
1922  <phrase id="algorithm_awakened"/>
1923  <link linkend="algorithm_awakened">Member function
1924      <code>awakened</code>()</link>
1925</bridgehead>
1926    </para>
1927<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>
1928</programlisting>
1929    <variablelist>
1930      <title></title>
1931      <varlistentry>
1932        <term>Effects:</term>
1933        <listitem>
1934          <para>
1935            Informs the scheduler that fiber <code><phrase role="identifier">f</phrase></code>
1936            is ready to run. Fiber <code><phrase role="identifier">f</phrase></code>
1937            might be newly launched, or it might have been blocked but has just been
1938            awakened, or it might have called <link linkend="this_fiber_yield"><code>this_fiber::yield()</code></link>.
1939          </para>
1940        </listitem>
1941      </varlistentry>
1942      <varlistentry>
1943        <term>Note:</term>
1944        <listitem>
1945          <para>
1946            This method advises the scheduler to add fiber <code><phrase role="identifier">f</phrase></code>
1947            to its collection of fibers ready to run. A typical scheduler implementation
1948            places <code><phrase role="identifier">f</phrase></code> into a queue.
1949          </para>
1950        </listitem>
1951      </varlistentry>
1952      <varlistentry>
1953        <term>See also:</term>
1954        <listitem>
1955          <para>
1956            <link linkend="class_round_robin"><code>round_robin</code></link>
1957          </para>
1958        </listitem>
1959      </varlistentry>
1960    </variablelist>
1961    <para>
1962      <bridgehead renderas="sect4" id="algorithm_pick_next_bridgehead">
1963  <phrase id="algorithm_pick_next"/>
1964  <link linkend="algorithm_pick_next">Member
1965      function <code>pick_next</code>()</link>
1966</bridgehead>
1967    </para>
1968<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>
1969</programlisting>
1970    <variablelist>
1971      <title></title>
1972      <varlistentry>
1973        <term>Returns:</term>
1974        <listitem>
1975          <para>
1976            the fiber which is to be resumed next, or <code><phrase role="keyword">nullptr</phrase></code>
1977            if there is no ready fiber.
1978          </para>
1979        </listitem>
1980      </varlistentry>
1981      <varlistentry>
1982        <term>Note:</term>
1983        <listitem>
1984          <para>
1985            This is where the scheduler actually specifies the fiber which is to
1986            run next. A typical scheduler implementation chooses the head of the
1987            ready queue.
1988          </para>
1989        </listitem>
1990      </varlistentry>
1991      <varlistentry>
1992        <term>See also:</term>
1993        <listitem>
1994          <para>
1995            <link linkend="class_round_robin"><code>round_robin</code></link>
1996          </para>
1997        </listitem>
1998      </varlistentry>
1999    </variablelist>
2000    <para>
2001      <bridgehead renderas="sect4" id="algorithm_has_ready_fibers_bridgehead">
2002  <phrase id="algorithm_has_ready_fibers"/>
2003  <link linkend="algorithm_has_ready_fibers">Member
2004      function <code>has_ready_fibers</code>()</link>
2005</bridgehead>
2006    </para>
2007<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>
2008</programlisting>
2009    <variablelist>
2010      <title></title>
2011      <varlistentry>
2012        <term>Returns:</term>
2013        <listitem>
2014          <para>
2015            <code><phrase role="keyword">true</phrase></code> if scheduler has fibers
2016            ready to run.
2017          </para>
2018        </listitem>
2019      </varlistentry>
2020    </variablelist>
2021    <para>
2022      <bridgehead renderas="sect4" id="algorithm_suspend_until_bridgehead">
2023  <phrase id="algorithm_suspend_until"/>
2024  <link linkend="algorithm_suspend_until">Member
2025      function <code>suspend_until</code>()</link>
2026</bridgehead>
2027    </para>
2028<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>
2029</programlisting>
2030    <variablelist>
2031      <title></title>
2032      <varlistentry>
2033        <term>Effects:</term>
2034        <listitem>
2035          <para>
2036            Informs the scheduler that no fiber will be ready until time-point <code><phrase
2037            role="identifier">abs_time</phrase></code>.
2038          </para>
2039        </listitem>
2040      </varlistentry>
2041      <varlistentry>
2042        <term>Note:</term>
2043        <listitem>
2044          <para>
2045            This method allows a custom scheduler to yield control to the containing
2046            environment in whatever way makes sense. The fiber manager is stating
2047            that <code><phrase role="identifier">suspend_until</phrase><phrase role="special">()</phrase></code>
2048            need not return until <code><phrase role="identifier">abs_time</phrase></code>
2049            &mdash; or <link linkend="algorithm_notify"><code>algorithm::notify()</code></link> is called &mdash; whichever comes first.
2050            The interaction with <code><phrase role="identifier">notify</phrase><phrase
2051            role="special">()</phrase></code> means that, for instance, calling
2052            <ulink url="http://en.cppreference.com/w/cpp/thread/sleep_until"><code><phrase
2053            role="identifier">std</phrase><phrase role="special">::</phrase><phrase
2054            role="identifier">this_thread</phrase><phrase role="special">::</phrase><phrase
2055            role="identifier">sleep_until</phrase><phrase role="special">(</phrase><phrase
2056            role="identifier">abs_time</phrase><phrase role="special">)</phrase></code></ulink>
2057            would be too simplistic. <link linkend="round_robin_suspend_until"><code>round_robin::suspend_until()</code></link> uses
2058            a <ulink url="http://en.cppreference.com/w/cpp/thread/condition_variable"><code><phrase
2059            role="identifier">std</phrase><phrase role="special">::</phrase><phrase
2060            role="identifier">condition_variable</phrase></code></ulink> to coordinate
2061            with <link linkend="round_robin_notify"><code>round_robin::notify()</code></link>.
2062          </para>
2063        </listitem>
2064      </varlistentry>
2065      <varlistentry>
2066        <term>Note:</term>
2067        <listitem>
2068          <para>
2069            Given that <code><phrase role="identifier">notify</phrase><phrase role="special">()</phrase></code>
2070            might be called from another thread, your <code><phrase role="identifier">suspend_until</phrase><phrase
2071            role="special">()</phrase></code> implementation &mdash; like the rest of your
2072            <code><phrase role="identifier">algorithm</phrase></code> implementation
2073            &mdash; must guard any data it shares with your <code><phrase role="identifier">notify</phrase><phrase
2074            role="special">()</phrase></code> implementation.
2075          </para>
2076        </listitem>
2077      </varlistentry>
2078    </variablelist>
2079    <para>
2080      <bridgehead renderas="sect4" id="algorithm_notify_bridgehead">
2081  <phrase id="algorithm_notify"/>
2082  <link linkend="algorithm_notify">Member function
2083      <code>notify</code>()</link>
2084</bridgehead>
2085    </para>
2086<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>
2087</programlisting>
2088    <variablelist>
2089      <title></title>
2090      <varlistentry>
2091        <term>Effects:</term>
2092        <listitem>
2093          <para>
2094            Requests the scheduler to return from a pending call to <link linkend="algorithm_suspend_until"><code>algorithm::suspend_until()</code></link>.
2095          </para>
2096        </listitem>
2097      </varlistentry>
2098      <varlistentry>
2099        <term>Note:</term>
2100        <listitem>
2101          <para>
2102            Alone among the <code><phrase role="identifier">algorithm</phrase></code>
2103            methods, <code><phrase role="identifier">notify</phrase><phrase role="special">()</phrase></code>
2104            may be called from another thread. Your <code><phrase role="identifier">notify</phrase><phrase
2105            role="special">()</phrase></code> implementation must guard any data
2106            it shares with the rest of your <code><phrase role="identifier">algorithm</phrase></code>
2107            implementation.
2108          </para>
2109        </listitem>
2110      </varlistentry>
2111    </variablelist>
2112    <para>
2113      <bridgehead renderas="sect4" id="class_round_robin_bridgehead">
2114  <phrase id="class_round_robin"/>
2115  <link linkend="class_round_robin">Class <code>round_robin</code></link>
2116</bridgehead>
2117    </para>
2118    <para>
2119      This class implements <link linkend="class_algorithm"><code>algorithm</code></link>, scheduling fibers in round-robin
2120      fashion.
2121    </para>
2122<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>
2123
2124<phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase>
2125<phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase>
2126<phrase role="keyword">namespace</phrase> <phrase role="identifier">algo</phrase> <phrase role="special">{</phrase>
2127
2128<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>
2129    <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>
2130
2131    <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>
2132
2133    <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>
2134
2135    <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>
2136
2137    <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>
2138<phrase role="special">};</phrase>
2139
2140<phrase role="special">}}}</phrase>
2141</programlisting>
2142    <para>
2143      <bridgehead renderas="sect4" id="round_robin_awakened_bridgehead">
2144  <phrase id="round_robin_awakened"/>
2145  <link linkend="round_robin_awakened">Member
2146      function <code>awakened</code>()</link>
2147</bridgehead>
2148    </para>
2149<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>
2150</programlisting>
2151    <variablelist>
2152      <title></title>
2153      <varlistentry>
2154        <term>Effects:</term>
2155        <listitem>
2156          <para>
2157            Enqueues fiber <code><phrase role="identifier">f</phrase></code> onto
2158            a ready queue.
2159          </para>
2160        </listitem>
2161      </varlistentry>
2162      <varlistentry>
2163        <term>Throws:</term>
2164        <listitem>
2165          <para>
2166            Nothing.
2167          </para>
2168        </listitem>
2169      </varlistentry>
2170    </variablelist>
2171    <para>
2172      <bridgehead renderas="sect4" id="round_robin_pick_next_bridgehead">
2173  <phrase id="round_robin_pick_next"/>
2174  <link linkend="round_robin_pick_next">Member
2175      function <code>pick_next</code>()</link>
2176</bridgehead>
2177    </para>
2178<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>
2179</programlisting>
2180    <variablelist>
2181      <title></title>
2182      <varlistentry>
2183        <term>Returns:</term>
2184        <listitem>
2185          <para>
2186            the fiber at the head of the ready queue, or <code><phrase role="keyword">nullptr</phrase></code>
2187            if the queue is empty.
2188          </para>
2189        </listitem>
2190      </varlistentry>
2191      <varlistentry>
2192        <term>Throws:</term>
2193        <listitem>
2194          <para>
2195            Nothing.
2196          </para>
2197        </listitem>
2198      </varlistentry>
2199      <varlistentry>
2200        <term>Note:</term>
2201        <listitem>
2202          <para>
2203            Placing ready fibers onto the tail of a queue, and returning them from
2204            the head of that queue, shares the thread between ready fibers in round-robin
2205            fashion.
2206          </para>
2207        </listitem>
2208      </varlistentry>
2209    </variablelist>
2210    <para>
2211      <bridgehead renderas="sect4" id="round_robin_has_ready_fibers_bridgehead">
2212  <phrase id="round_robin_has_ready_fibers"/>
2213  <link linkend="round_robin_has_ready_fibers">Member
2214      function <code>has_ready_fibers</code>()</link>
2215</bridgehead>
2216    </para>
2217<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>
2218</programlisting>
2219    <variablelist>
2220      <title></title>
2221      <varlistentry>
2222        <term>Returns:</term>
2223        <listitem>
2224          <para>
2225            <code><phrase role="keyword">true</phrase></code> if scheduler has fibers
2226            ready to run.
2227          </para>
2228        </listitem>
2229      </varlistentry>
2230      <varlistentry>
2231        <term>Throws:</term>
2232        <listitem>
2233          <para>
2234            Nothing.
2235          </para>
2236        </listitem>
2237      </varlistentry>
2238    </variablelist>
2239    <para>
2240      <bridgehead renderas="sect4" id="round_robin_suspend_until_bridgehead">
2241  <phrase id="round_robin_suspend_until"/>
2242  <link linkend="round_robin_suspend_until">Member
2243      function <code>suspend_until</code>()</link>
2244</bridgehead>
2245    </para>
2246<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>
2247</programlisting>
2248    <variablelist>
2249      <title></title>
2250      <varlistentry>
2251        <term>Effects:</term>
2252        <listitem>
2253          <para>
2254            Informs <code><phrase role="identifier">round_robin</phrase></code> that
2255            no ready fiber will be available until time-point <code><phrase role="identifier">abs_time</phrase></code>.
2256            This implementation blocks in <ulink url="http://en.cppreference.com/w/cpp/thread/condition_variable/wait_until"><code><phrase
2257            role="identifier">std</phrase><phrase role="special">::</phrase><phrase
2258            role="identifier">condition_variable</phrase><phrase role="special">::</phrase><phrase
2259            role="identifier">wait_until</phrase><phrase role="special">()</phrase></code></ulink>.
2260          </para>
2261        </listitem>
2262      </varlistentry>
2263      <varlistentry>
2264        <term>Throws:</term>
2265        <listitem>
2266          <para>
2267            Nothing.
2268          </para>
2269        </listitem>
2270      </varlistentry>
2271    </variablelist>
2272    <para>
2273      <bridgehead renderas="sect4" id="round_robin_notify_bridgehead">
2274  <phrase id="round_robin_notify"/>
2275  <link linkend="round_robin_notify">Member function
2276      <code>notify</code>()</link>
2277</bridgehead>
2278    </para>
2279<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>
2280</programlisting>
2281    <variablelist>
2282      <title></title>
2283      <varlistentry>
2284        <term>Effects:</term>
2285        <listitem>
2286          <para>
2287            Wake up a pending call to <link linkend="round_robin_suspend_until"><code>round_robin::suspend_until()</code></link>,
2288            some fibers might be ready. This implementation wakes <code><phrase role="identifier">suspend_until</phrase><phrase
2289            role="special">()</phrase></code> via <ulink url="http://en.cppreference.com/w/cpp/thread/condition_variable/notify_all"><code><phrase
2290            role="identifier">std</phrase><phrase role="special">::</phrase><phrase
2291            role="identifier">condition_variable</phrase><phrase role="special">::</phrase><phrase
2292            role="identifier">notify_all</phrase><phrase role="special">()</phrase></code></ulink>.
2293          </para>
2294        </listitem>
2295      </varlistentry>
2296      <varlistentry>
2297        <term>Throws:</term>
2298        <listitem>
2299          <para>
2300            Nothing.
2301          </para>
2302        </listitem>
2303      </varlistentry>
2304    </variablelist>
2305    <para>
2306      <bridgehead renderas="sect4" id="class_work_stealing_bridgehead">
2307  <phrase id="class_work_stealing"/>
2308  <link linkend="class_work_stealing">Class <code>work_stealing</code></link>
2309</bridgehead>
2310    </para>
2311    <para>
2312      This class implements <link linkend="class_algorithm"><code>algorithm</code></link>; if the local ready-queue runs
2313      out of ready fibers, ready fibers are stolen from other schedulers.<sbr/> The
2314      victim scheduler (from which a ready fiber is stolen) is selected at random.
2315    </para>
2316    <note>
2317      <para>
2318        Worker-threads are stored in a static variable, dynamically adding/removing
2319        worker threads is not supported.
2320      </para>
2321    </note>
2322<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>
2323
2324<phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase>
2325<phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase>
2326<phrase role="keyword">namespace</phrase> <phrase role="identifier">algo</phrase> <phrase role="special">{</phrase>
2327
2328<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>
2329<phrase role="keyword">public</phrase><phrase role="special">:</phrase>
2330    <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>
2331
2332    <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>
2333    <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>
2334
2335    <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>
2336    <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>
2337
2338    <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>
2339
2340    <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>
2341
2342    <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>
2343
2344    <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>
2345
2346    <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>
2347<phrase role="special">};</phrase>
2348
2349<phrase role="special">}}}</phrase>
2350</programlisting>
2351    <bridgehead renderas="sect3" id="fiber.scheduling.h0">
2352      <phrase id="fiber.scheduling.constructor"/><link linkend="fiber.scheduling.constructor">Constructor</link>
2353    </bridgehead>
2354<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>
2355</programlisting>
2356    <variablelist>
2357      <title></title>
2358      <varlistentry>
2359        <term>Effects:</term>
2360        <listitem>
2361          <para>
2362            Constructs work-stealing scheduling algorithm. <code><phrase role="identifier">thread_count</phrase></code>
2363            represents the number of threads running this algorithm.
2364          </para>
2365        </listitem>
2366      </varlistentry>
2367      <varlistentry>
2368        <term>Throws:</term>
2369        <listitem>
2370          <para>
2371            <code><phrase role="identifier">system_error</phrase></code>
2372          </para>
2373        </listitem>
2374      </varlistentry>
2375      <varlistentry>
2376        <term>Note:</term>
2377        <listitem>
2378          <para>
2379            If <code><phrase role="identifier">suspend</phrase></code> is set to
2380            <code><phrase role="keyword">true</phrase></code>, then the scheduler
2381            suspends if no ready fiber could be stolen. The scheduler will by woken
2382            up if a sleeping fiber times out or it was notified from remote (other
2383            thread or fiber scheduler).
2384          </para>
2385        </listitem>
2386      </varlistentry>
2387    </variablelist>
2388    <para>
2389      <bridgehead renderas="sect4" id="work_stealing_awakened_bridgehead">
2390  <phrase id="work_stealing_awakened"/>
2391  <link linkend="work_stealing_awakened">Member
2392      function <code>awakened</code>()</link>
2393</bridgehead>
2394    </para>
2395<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>
2396</programlisting>
2397    <variablelist>
2398      <title></title>
2399      <varlistentry>
2400        <term>Effects:</term>
2401        <listitem>
2402          <para>
2403            Enqueues fiber <code><phrase role="identifier">f</phrase></code> onto
2404            the shared ready queue.
2405          </para>
2406        </listitem>
2407      </varlistentry>
2408      <varlistentry>
2409        <term>Throws:</term>
2410        <listitem>
2411          <para>
2412            Nothing.
2413          </para>
2414        </listitem>
2415      </varlistentry>
2416    </variablelist>
2417    <para>
2418      <bridgehead renderas="sect4" id="work_stealing_pick_next_bridgehead">
2419  <phrase id="work_stealing_pick_next"/>
2420  <link linkend="work_stealing_pick_next">Member
2421      function <code>pick_next</code>()</link>
2422</bridgehead>
2423    </para>
2424<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>
2425</programlisting>
2426    <variablelist>
2427      <title></title>
2428      <varlistentry>
2429        <term>Returns:</term>
2430        <listitem>
2431          <para>
2432            the fiber at the head of the ready queue, or <code><phrase role="keyword">nullptr</phrase></code>
2433            if the queue is empty.
2434          </para>
2435        </listitem>
2436      </varlistentry>
2437      <varlistentry>
2438        <term>Throws:</term>
2439        <listitem>
2440          <para>
2441            Nothing.
2442          </para>
2443        </listitem>
2444      </varlistentry>
2445      <varlistentry>
2446        <term>Note:</term>
2447        <listitem>
2448          <para>
2449            Placing ready fibers onto the tail of the sahred queue, and returning
2450            them from the head of that queue, shares the thread between ready fibers
2451            in round-robin fashion.
2452          </para>
2453        </listitem>
2454      </varlistentry>
2455    </variablelist>
2456    <para>
2457      <bridgehead renderas="sect4" id="work_stealing_has_ready_fibers_bridgehead">
2458  <phrase id="work_stealing_has_ready_fibers"/>
2459  <link linkend="work_stealing_has_ready_fibers">Member
2460      function <code>has_ready_fibers</code>()</link>
2461</bridgehead>
2462    </para>
2463<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>
2464</programlisting>
2465    <variablelist>
2466      <title></title>
2467      <varlistentry>
2468        <term>Returns:</term>
2469        <listitem>
2470          <para>
2471            <code><phrase role="keyword">true</phrase></code> if scheduler has fibers
2472            ready to run.
2473          </para>
2474        </listitem>
2475      </varlistentry>
2476      <varlistentry>
2477        <term>Throws:</term>
2478        <listitem>
2479          <para>
2480            Nothing.
2481          </para>
2482        </listitem>
2483      </varlistentry>
2484    </variablelist>
2485    <para>
2486      <bridgehead renderas="sect4" id="work_stealing_suspend_until_bridgehead">
2487  <phrase id="work_stealing_suspend_until"/>
2488  <link linkend="work_stealing_suspend_until">Member
2489      function <code>suspend_until</code>()</link>
2490</bridgehead>
2491    </para>
2492<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>
2493</programlisting>
2494    <variablelist>
2495      <title></title>
2496      <varlistentry>
2497        <term>Effects:</term>
2498        <listitem>
2499          <para>
2500            Informs <code><phrase role="identifier">work_stealing</phrase></code>
2501            that no ready fiber will be available until time-point <code><phrase
2502            role="identifier">abs_time</phrase></code>. This implementation blocks
2503            in <ulink url="http://en.cppreference.com/w/cpp/thread/condition_variable/wait_until"><code><phrase
2504            role="identifier">std</phrase><phrase role="special">::</phrase><phrase
2505            role="identifier">condition_variable</phrase><phrase role="special">::</phrase><phrase
2506            role="identifier">wait_until</phrase><phrase role="special">()</phrase></code></ulink>.
2507          </para>
2508        </listitem>
2509      </varlistentry>
2510      <varlistentry>
2511        <term>Throws:</term>
2512        <listitem>
2513          <para>
2514            Nothing.
2515          </para>
2516        </listitem>
2517      </varlistentry>
2518    </variablelist>
2519    <para>
2520      <bridgehead renderas="sect4" id="work_stealing_notify_bridgehead">
2521  <phrase id="work_stealing_notify"/>
2522  <link linkend="work_stealing_notify">Member
2523      function <code>notify</code>()</link>
2524</bridgehead>
2525    </para>
2526<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>
2527</programlisting>
2528    <variablelist>
2529      <title></title>
2530      <varlistentry>
2531        <term>Effects:</term>
2532        <listitem>
2533          <para>
2534            Wake up a pending call to <link linkend="work_stealing_suspend_until"><code>work_stealing::suspend_until()</code></link>,
2535            some fibers might be ready. This implementation wakes <code><phrase role="identifier">suspend_until</phrase><phrase
2536            role="special">()</phrase></code> via <ulink url="http://en.cppreference.com/w/cpp/thread/condition_variable/notify_all"><code><phrase
2537            role="identifier">std</phrase><phrase role="special">::</phrase><phrase
2538            role="identifier">condition_variable</phrase><phrase role="special">::</phrase><phrase
2539            role="identifier">notify_all</phrase><phrase role="special">()</phrase></code></ulink>.
2540          </para>
2541        </listitem>
2542      </varlistentry>
2543      <varlistentry>
2544        <term>Throws:</term>
2545        <listitem>
2546          <para>
2547            Nothing.
2548          </para>
2549        </listitem>
2550      </varlistentry>
2551    </variablelist>
2552    <para>
2553      <bridgehead renderas="sect4" id="class_shared_work_bridgehead">
2554  <phrase id="class_shared_work"/>
2555  <link linkend="class_shared_work">Class <code>shared_work</code></link>
2556</bridgehead>
2557    </para>
2558    <note>
2559      <para>
2560        Because of the non-locality of data, <emphasis>shared_work</emphasis> is
2561        less performant than <link linkend="class_work_stealing"><code>work_stealing</code></link>.
2562      </para>
2563    </note>
2564    <para>
2565      This class implements <link linkend="class_algorithm"><code>algorithm</code></link>, scheduling fibers in round-robin
2566      fashion. Ready fibers are shared between all instances (running on different
2567      threads) of shared_work, thus the work is distributed equally over all threads.
2568    </para>
2569    <note>
2570      <para>
2571        Worker-threads are stored in a static variable, dynamically adding/removing
2572        worker threads is not supported.
2573      </para>
2574    </note>
2575<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>
2576
2577<phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase>
2578<phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase>
2579<phrase role="keyword">namespace</phrase> <phrase role="identifier">algo</phrase> <phrase role="special">{</phrase>
2580
2581<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>
2582    <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>
2583
2584    <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>
2585
2586    <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>
2587
2588    <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>
2589
2590    <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>
2591<phrase role="special">};</phrase>
2592
2593<phrase role="special">}}}</phrase>
2594</programlisting>
2595    <para>
2596      <bridgehead renderas="sect4" id="shared_work_awakened_bridgehead">
2597  <phrase id="shared_work_awakened"/>
2598  <link linkend="shared_work_awakened">Member
2599      function <code>awakened</code>()</link>
2600</bridgehead>
2601    </para>
2602<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>
2603</programlisting>
2604    <variablelist>
2605      <title></title>
2606      <varlistentry>
2607        <term>Effects:</term>
2608        <listitem>
2609          <para>
2610            Enqueues fiber <code><phrase role="identifier">f</phrase></code> onto
2611            the shared ready queue.
2612          </para>
2613        </listitem>
2614      </varlistentry>
2615      <varlistentry>
2616        <term>Throws:</term>
2617        <listitem>
2618          <para>
2619            Nothing.
2620          </para>
2621        </listitem>
2622      </varlistentry>
2623    </variablelist>
2624    <para>
2625      <bridgehead renderas="sect4" id="shared_work_pick_next_bridgehead">
2626  <phrase id="shared_work_pick_next"/>
2627  <link linkend="shared_work_pick_next">Member
2628      function <code>pick_next</code>()</link>
2629</bridgehead>
2630    </para>
2631<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>
2632</programlisting>
2633    <variablelist>
2634      <title></title>
2635      <varlistentry>
2636        <term>Returns:</term>
2637        <listitem>
2638          <para>
2639            the fiber at the head of the ready queue, or <code><phrase role="keyword">nullptr</phrase></code>
2640            if the queue is empty.
2641          </para>
2642        </listitem>
2643      </varlistentry>
2644      <varlistentry>
2645        <term>Throws:</term>
2646        <listitem>
2647          <para>
2648            Nothing.
2649          </para>
2650        </listitem>
2651      </varlistentry>
2652      <varlistentry>
2653        <term>Note:</term>
2654        <listitem>
2655          <para>
2656            Placing ready fibers onto the tail of the shared queue, and returning
2657            them from the head of that queue, shares the thread between ready fibers
2658            in round-robin fashion.
2659          </para>
2660        </listitem>
2661      </varlistentry>
2662    </variablelist>
2663    <para>
2664      <bridgehead renderas="sect4" id="shared_work_has_ready_fibers_bridgehead">
2665  <phrase id="shared_work_has_ready_fibers"/>
2666  <link linkend="shared_work_has_ready_fibers">Member
2667      function <code>has_ready_fibers</code>()</link>
2668</bridgehead>
2669    </para>
2670<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>
2671</programlisting>
2672    <variablelist>
2673      <title></title>
2674      <varlistentry>
2675        <term>Returns:</term>
2676        <listitem>
2677          <para>
2678            <code><phrase role="keyword">true</phrase></code> if scheduler has fibers
2679            ready to run.
2680          </para>
2681        </listitem>
2682      </varlistentry>
2683      <varlistentry>
2684        <term>Throws:</term>
2685        <listitem>
2686          <para>
2687            Nothing.
2688          </para>
2689        </listitem>
2690      </varlistentry>
2691    </variablelist>
2692    <para>
2693      <bridgehead renderas="sect4" id="shared_work_suspend_until_bridgehead">
2694  <phrase id="shared_work_suspend_until"/>
2695  <link linkend="shared_work_suspend_until">Member
2696      function <code>suspend_until</code>()</link>
2697</bridgehead>
2698    </para>
2699<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>
2700</programlisting>
2701    <variablelist>
2702      <title></title>
2703      <varlistentry>
2704        <term>Effects:</term>
2705        <listitem>
2706          <para>
2707            Informs <code><phrase role="identifier">shared_work</phrase></code> that
2708            no ready fiber will be available until time-point <code><phrase role="identifier">abs_time</phrase></code>.
2709            This implementation blocks in <ulink url="http://en.cppreference.com/w/cpp/thread/condition_variable/wait_until"><code><phrase
2710            role="identifier">std</phrase><phrase role="special">::</phrase><phrase
2711            role="identifier">condition_variable</phrase><phrase role="special">::</phrase><phrase
2712            role="identifier">wait_until</phrase><phrase role="special">()</phrase></code></ulink>.
2713          </para>
2714        </listitem>
2715      </varlistentry>
2716      <varlistentry>
2717        <term>Throws:</term>
2718        <listitem>
2719          <para>
2720            Nothing.
2721          </para>
2722        </listitem>
2723      </varlistentry>
2724    </variablelist>
2725    <para>
2726      <bridgehead renderas="sect4" id="shared_work_notify_bridgehead">
2727  <phrase id="shared_work_notify"/>
2728  <link linkend="shared_work_notify">Member function
2729      <code>notify</code>()</link>
2730</bridgehead>
2731    </para>
2732<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>
2733</programlisting>
2734    <variablelist>
2735      <title></title>
2736      <varlistentry>
2737        <term>Effects:</term>
2738        <listitem>
2739          <para>
2740            Wake up a pending call to <link linkend="shared_work_suspend_until"><code>shared_work::suspend_until()</code></link>,
2741            some fibers might be ready. This implementation wakes <code><phrase role="identifier">suspend_until</phrase><phrase
2742            role="special">()</phrase></code> via <ulink url="http://en.cppreference.com/w/cpp/thread/condition_variable/notify_all"><code><phrase
2743            role="identifier">std</phrase><phrase role="special">::</phrase><phrase
2744            role="identifier">condition_variable</phrase><phrase role="special">::</phrase><phrase
2745            role="identifier">notify_all</phrase><phrase role="special">()</phrase></code></ulink>.
2746          </para>
2747        </listitem>
2748      </varlistentry>
2749      <varlistentry>
2750        <term>Throws:</term>
2751        <listitem>
2752          <para>
2753            Nothing.
2754          </para>
2755        </listitem>
2756      </varlistentry>
2757    </variablelist>
2758    <bridgehead renderas="sect3" id="fiber.scheduling.h1">
2759      <phrase id="fiber.scheduling.custom_scheduler_fiber_properties"/><link linkend="fiber.scheduling.custom_scheduler_fiber_properties">Custom
2760      Scheduler Fiber Properties</link>
2761    </bridgehead>
2762    <para>
2763      A scheduler class directly derived from <link linkend="class_algorithm"><code>algorithm</code></link> can use any
2764      information available from <link linkend="class_context"><code>context</code></link> to implement the <code><phrase
2765      role="identifier">algorithm</phrase></code> interface. But a custom scheduler
2766      might need to track additional properties for a fiber. For instance, a priority-based
2767      scheduler would need to track a fiber&#8217;s priority.
2768    </para>
2769    <para>
2770      <emphasis role="bold">Boost.Fiber</emphasis> provides a mechanism by which
2771      your custom scheduler can associate custom properties with each fiber.
2772    </para>
2773    <para>
2774      <bridgehead renderas="sect4" id="class_fiber_properties_bridgehead">
2775  <phrase id="class_fiber_properties"/>
2776  <link linkend="class_fiber_properties">Class
2777      <code>fiber_properties</code></link>
2778</bridgehead>
2779    </para>
2780    <para>
2781      A custom fiber properties class must be derived from <code><phrase role="identifier">fiber_properties</phrase></code>.
2782    </para>
2783<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>
2784
2785<phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase>
2786<phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase>
2787
2788<phrase role="keyword">class</phrase> <phrase role="identifier">fiber_properties</phrase> <phrase role="special">{</phrase>
2789<phrase role="keyword">public</phrase><phrase role="special">:</phrase>
2790    <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>
2791
2792    <phrase role="keyword">virtual</phrase> <phrase role="special">~</phrase><phrase role="identifier">fiber_properties</phrase><phrase role="special">();</phrase>
2793
2794<phrase role="keyword">protected</phrase><phrase role="special">:</phrase>
2795    <phrase role="keyword">void</phrase> <phrase role="identifier">notify</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
2796<phrase role="special">};</phrase>
2797
2798<phrase role="special">}}</phrase>
2799</programlisting>
2800    <bridgehead renderas="sect3" id="fiber.scheduling.h2">
2801      <phrase id="fiber.scheduling.constructor0"/><link linkend="fiber.scheduling.constructor0">Constructor</link>
2802    </bridgehead>
2803<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>
2804</programlisting>
2805    <variablelist>
2806      <title></title>
2807      <varlistentry>
2808        <term>Effects:</term>
2809        <listitem>
2810          <para>
2811            Constructs base-class component of custom subclass.
2812          </para>
2813        </listitem>
2814      </varlistentry>
2815      <varlistentry>
2816        <term>Throws:</term>
2817        <listitem>
2818          <para>
2819            Nothing.
2820          </para>
2821        </listitem>
2822      </varlistentry>
2823      <varlistentry>
2824        <term>Note:</term>
2825        <listitem>
2826          <para>
2827            Your subclass constructor must accept a <code><phrase role="identifier">context</phrase><phrase
2828            role="special">*</phrase></code> and pass it to the base-class <code><phrase
2829            role="identifier">fiber_properties</phrase></code> constructor.
2830          </para>
2831        </listitem>
2832      </varlistentry>
2833    </variablelist>
2834    <para>
2835      <bridgehead renderas="sect4" id="fiber_properties_notify_bridgehead">
2836  <phrase id="fiber_properties_notify"/>
2837  <link linkend="fiber_properties_notify">Member
2838      function <code>notify</code>()</link>
2839</bridgehead>
2840    </para>
2841<programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">notify</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
2842</programlisting>
2843    <variablelist>
2844      <title></title>
2845      <varlistentry>
2846        <term>Effects:</term>
2847        <listitem>
2848          <para>
2849            Pass control to the custom <link linkend="class_algorithm_with_properties"><code>algorithm_with_properties&lt;&gt;</code></link> subclass&#8217;s
2850            <link linkend="algorithm_with_properties_property_change"><code>algorithm_with_properties::property_change()</code></link> method.
2851          </para>
2852        </listitem>
2853      </varlistentry>
2854      <varlistentry>
2855        <term>Throws:</term>
2856        <listitem>
2857          <para>
2858            Nothing.
2859          </para>
2860        </listitem>
2861      </varlistentry>
2862      <varlistentry>
2863        <term>Note:</term>
2864        <listitem>
2865          <para>
2866            A custom scheduler&#8217;s <link linkend="algorithm_with_properties_pick_next"><code>algorithm_with_properties::pick_next()</code></link> method
2867            might dynamically select from the ready fibers, or <link linkend="algorithm_with_properties_awakened"><code>algorithm_with_properties::awakened()</code></link> might
2868            instead insert each ready fiber into some form of ready queue for <code><phrase
2869            role="identifier">pick_next</phrase><phrase role="special">()</phrase></code>.
2870            In the latter case, if application code modifies a fiber property (e.g.
2871            priority) that should affect that fiber&#8217;s relationship to other ready
2872            fibers, the custom scheduler must be given the opportunity to reorder
2873            its ready queue. The custom property subclass should implement an access
2874            method to modify such a property; that access method should call <code><phrase
2875            role="identifier">notify</phrase><phrase role="special">()</phrase></code>
2876            once the new property value has been stored. This passes control to the
2877            custom scheduler&#8217;s <code><phrase role="identifier">property_change</phrase><phrase
2878            role="special">()</phrase></code> method, allowing the custom scheduler
2879            to reorder its ready queue appropriately. Use at your discretion. Of
2880            course, if you define a property which does not affect the behavior of
2881            the <code><phrase role="identifier">pick_next</phrase><phrase role="special">()</phrase></code>
2882            method, you need not call <code><phrase role="identifier">notify</phrase><phrase
2883            role="special">()</phrase></code> when that property is modified.
2884          </para>
2885        </listitem>
2886      </varlistentry>
2887    </variablelist>
2888    <para>
2889      <bridgehead renderas="sect4" id="class_algorithm_with_properties_bridgehead">
2890  <phrase id="class_algorithm_with_properties"/>
2891  <link linkend="class_algorithm_with_properties">Template
2892      <code>algorithm_with_properties&lt;&gt;</code></link>
2893</bridgehead>
2894    </para>
2895    <para>
2896      A custom scheduler that depends on a custom properties class <code><phrase
2897      role="identifier">PROPS</phrase></code> should be derived from <code><phrase
2898      role="identifier">algorithm_with_properties</phrase><phrase role="special">&lt;</phrase><phrase
2899      role="identifier">PROPS</phrase><phrase role="special">&gt;</phrase></code>.
2900      <code><phrase role="identifier">PROPS</phrase></code> should be derived from
2901      <link linkend="class_fiber_properties"><code>fiber_properties</code></link>.
2902    </para>
2903<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>
2904
2905<phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase>
2906<phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase>
2907<phrase role="keyword">namespace</phrase> <phrase role="identifier">algo</phrase> <phrase role="special">{</phrase>
2908
2909<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>
2910<phrase role="keyword">struct</phrase> <phrase role="identifier">algorithm_with_properties</phrase> <phrase role="special">{</phrase>
2911    <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>
2912
2913    <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>
2914
2915    <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>
2916
2917    <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>
2918
2919    <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>
2920
2921    <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>
2922
2923    <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>
2924
2925    <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>
2926<phrase role="special">};</phrase>
2927
2928<phrase role="special">}}}</phrase>
2929</programlisting>
2930    <para>
2931      <bridgehead renderas="sect4" id="algorithm_with_properties_awakened_bridgehead">
2932  <phrase id="algorithm_with_properties_awakened"/>
2933  <link linkend="algorithm_with_properties_awakened">Member
2934      function <code>awakened</code>()</link>
2935</bridgehead>
2936    </para>
2937<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>
2938</programlisting>
2939    <variablelist>
2940      <title></title>
2941      <varlistentry>
2942        <term>Effects:</term>
2943        <listitem>
2944          <para>
2945            Informs the scheduler that fiber <code><phrase role="identifier">f</phrase></code>
2946            is ready to run, like <link linkend="algorithm_awakened"><code>algorithm::awakened()</code></link>. Passes
2947            the fiber&#8217;s associated <code><phrase role="identifier">PROPS</phrase></code>
2948            instance.
2949          </para>
2950        </listitem>
2951      </varlistentry>
2952      <varlistentry>
2953        <term>Throws:</term>
2954        <listitem>
2955          <para>
2956            Nothing.
2957          </para>
2958        </listitem>
2959      </varlistentry>
2960      <varlistentry>
2961        <term>Note:</term>
2962        <listitem>
2963          <para>
2964            An <code><phrase role="identifier">algorithm_with_properties</phrase><phrase
2965            role="special">&lt;&gt;</phrase></code> subclass must override this method
2966            instead of <code><phrase role="identifier">algorithm</phrase><phrase
2967            role="special">::</phrase><phrase role="identifier">awakened</phrase><phrase
2968            role="special">()</phrase></code>.
2969          </para>
2970        </listitem>
2971      </varlistentry>
2972    </variablelist>
2973    <para>
2974      <bridgehead renderas="sect4" id="algorithm_with_properties_pick_next_bridgehead">
2975  <phrase id="algorithm_with_properties_pick_next"/>
2976  <link linkend="algorithm_with_properties_pick_next">Member
2977      function <code>pick_next</code>()</link>
2978</bridgehead>
2979    </para>
2980<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>
2981</programlisting>
2982    <variablelist>
2983      <title></title>
2984      <varlistentry>
2985        <term>Returns:</term>
2986        <listitem>
2987          <para>
2988            the fiber which is to be resumed next, or <code><phrase role="keyword">nullptr</phrase></code>
2989            if there is no ready fiber.
2990          </para>
2991        </listitem>
2992      </varlistentry>
2993      <varlistentry>
2994        <term>Throws:</term>
2995        <listitem>
2996          <para>
2997            Nothing.
2998          </para>
2999        </listitem>
3000      </varlistentry>
3001      <varlistentry>
3002        <term>Note:</term>
3003        <listitem>
3004          <para>
3005            same as <link linkend="algorithm_pick_next"><code>algorithm::pick_next()</code></link>
3006          </para>
3007        </listitem>
3008      </varlistentry>
3009    </variablelist>
3010    <para>
3011      <bridgehead renderas="sect4" id="algorithm_with_properties_has_ready_fibers_bridgehead">
3012  <phrase id="algorithm_with_properties_has_ready_fibers"/>
3013  <link linkend="algorithm_with_properties_has_ready_fibers">Member
3014      function <code>has_ready_fibers</code>()</link>
3015</bridgehead>
3016    </para>
3017<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>
3018</programlisting>
3019    <variablelist>
3020      <title></title>
3021      <varlistentry>
3022        <term>Returns:</term>
3023        <listitem>
3024          <para>
3025            <code><phrase role="keyword">true</phrase></code> if scheduler has fibers
3026            ready to run.
3027          </para>
3028        </listitem>
3029      </varlistentry>
3030      <varlistentry>
3031        <term>Throws:</term>
3032        <listitem>
3033          <para>
3034            Nothing.
3035          </para>
3036        </listitem>
3037      </varlistentry>
3038      <varlistentry>
3039        <term>Note:</term>
3040        <listitem>
3041          <para>
3042            same as <link linkend="algorithm_has_ready_fibers"><code>algorithm::has_ready_fibers()</code></link>
3043          </para>
3044        </listitem>
3045      </varlistentry>
3046    </variablelist>
3047    <para>
3048      <bridgehead renderas="sect4" id="algorithm_with_properties_suspend_until_bridgehead">
3049  <phrase id="algorithm_with_properties_suspend_until"/>
3050  <link linkend="algorithm_with_properties_suspend_until">Member
3051      function <code>suspend_until</code>()</link>
3052</bridgehead>
3053    </para>
3054<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>
3055</programlisting>
3056    <variablelist>
3057      <title></title>
3058      <varlistentry>
3059        <term>Effects:</term>
3060        <listitem>
3061          <para>
3062            Informs the scheduler that no fiber will be ready until time-point <code><phrase
3063            role="identifier">abs_time</phrase></code>.
3064          </para>
3065        </listitem>
3066      </varlistentry>
3067      <varlistentry>
3068        <term>Note:</term>
3069        <listitem>
3070          <para>
3071            same as <link linkend="algorithm_suspend_until"><code>algorithm::suspend_until()</code></link>
3072          </para>
3073        </listitem>
3074      </varlistentry>
3075    </variablelist>
3076    <para>
3077      <bridgehead renderas="sect4" id="algorithm_with_properties_notify_bridgehead">
3078  <phrase id="algorithm_with_properties_notify"/>
3079  <link linkend="algorithm_with_properties_notify">Member
3080      function <code>notify</code>()</link>
3081</bridgehead>
3082    </para>
3083<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>
3084</programlisting>
3085    <variablelist>
3086      <title></title>
3087      <varlistentry>
3088        <term>Effects:</term>
3089        <listitem>
3090          <para>
3091            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>.
3092          </para>
3093        </listitem>
3094      </varlistentry>
3095      <varlistentry>
3096        <term>Note:</term>
3097        <listitem>
3098          <para>
3099            same as <link linkend="algorithm_notify"><code>algorithm::notify()</code></link>
3100          </para>
3101        </listitem>
3102      </varlistentry>
3103    </variablelist>
3104    <para>
3105      <bridgehead renderas="sect4" id="algorithm_with_properties_properties_bridgehead">
3106  <phrase id="algorithm_with_properties_properties"/>
3107  <link linkend="algorithm_with_properties_properties">Member
3108      function <code>properties</code>()</link>
3109</bridgehead>
3110    </para>
3111<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>
3112</programlisting>
3113    <variablelist>
3114      <title></title>
3115      <varlistentry>
3116        <term>Returns:</term>
3117        <listitem>
3118          <para>
3119            the <code><phrase role="identifier">PROPS</phrase></code> instance associated
3120            with fiber <code><phrase role="identifier">f</phrase></code>.
3121          </para>
3122        </listitem>
3123      </varlistentry>
3124      <varlistentry>
3125        <term>Throws:</term>
3126        <listitem>
3127          <para>
3128            Nothing.
3129          </para>
3130        </listitem>
3131      </varlistentry>
3132      <varlistentry>
3133        <term>Note:</term>
3134        <listitem>
3135          <para>
3136            The fiber&#8217;s associated <code><phrase role="identifier">PROPS</phrase></code>
3137            instance is already passed to <link linkend="algorithm_with_properties_awakened"><code>algorithm_with_properties::awakened()</code></link> and
3138            <link linkend="algorithm_with_properties_property_change"><code>algorithm_with_properties::property_change()</code></link>.
3139            However, every <link linkend="class_algorithm"><code>algorithm</code></link> subclass is expected to track
3140            a collection of ready <link linkend="class_context"><code>context</code></link> instances. This method allows
3141            your custom scheduler to retrieve the <link linkend="class_fiber_properties"><code>fiber_properties</code></link> subclass
3142            instance for any <code><phrase role="identifier">context</phrase></code>
3143            in its collection.
3144          </para>
3145        </listitem>
3146      </varlistentry>
3147    </variablelist>
3148    <para>
3149      <bridgehead renderas="sect4" id="algorithm_with_properties_property_change_bridgehead">
3150  <phrase id="algorithm_with_properties_property_change"/>
3151  <link linkend="algorithm_with_properties_property_change">Member
3152      function <code>property_change</code>()</link>
3153</bridgehead>
3154    </para>
3155<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>
3156</programlisting>
3157    <variablelist>
3158      <title></title>
3159      <varlistentry>
3160        <term>Effects:</term>
3161        <listitem>
3162          <para>
3163            Notify the custom scheduler of a possibly-relevant change to a property
3164            belonging to fiber <code><phrase role="identifier">f</phrase></code>.
3165            <code><phrase role="identifier">properties</phrase></code> contains the
3166            new values of all relevant properties.
3167          </para>
3168        </listitem>
3169      </varlistentry>
3170      <varlistentry>
3171        <term>Throws:</term>
3172        <listitem>
3173          <para>
3174            Nothing.
3175          </para>
3176        </listitem>
3177      </varlistentry>
3178      <varlistentry>
3179        <term>Note:</term>
3180        <listitem>
3181          <para>
3182            This method is only called when a custom <link linkend="class_fiber_properties"><code>fiber_properties</code></link> subclass
3183            explicitly calls <link linkend="fiber_properties_notify"><code>fiber_properties::notify()</code></link>.
3184          </para>
3185        </listitem>
3186      </varlistentry>
3187    </variablelist>
3188    <para>
3189      <bridgehead renderas="sect4" id="algorithm_with_properties_new_properties_bridgehead">
3190  <phrase id="algorithm_with_properties_new_properties"/>
3191  <link linkend="algorithm_with_properties_new_properties">Member
3192      function <code>new_properties</code>()</link>
3193</bridgehead>
3194    </para>
3195<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>
3196</programlisting>
3197    <variablelist>
3198      <title></title>
3199      <varlistentry>
3200        <term>Returns:</term>
3201        <listitem>
3202          <para>
3203            A new instance of <link linkend="class_fiber_properties"><code>fiber_properties</code></link> subclass <code><phrase
3204            role="identifier">PROPS</phrase></code>.
3205          </para>
3206        </listitem>
3207      </varlistentry>
3208      <varlistentry>
3209        <term>Note:</term>
3210        <listitem>
3211          <para>
3212            By default, <code><phrase role="identifier">algorithm_with_properties</phrase><phrase
3213            role="special">&lt;&gt;::</phrase><phrase role="identifier">new_properties</phrase><phrase
3214            role="special">()</phrase></code> simply returns <code><phrase role="keyword">new</phrase>
3215            <phrase role="identifier">PROPS</phrase><phrase role="special">(</phrase><phrase
3216            role="identifier">f</phrase><phrase role="special">)</phrase></code>,
3217            placing the <code><phrase role="identifier">PROPS</phrase></code> instance
3218            on the heap. Override this method to allocate <code><phrase role="identifier">PROPS</phrase></code>
3219            some other way. The returned <code><phrase role="identifier">fiber_properties</phrase></code>
3220            pointer must point to the <code><phrase role="identifier">PROPS</phrase></code>
3221            instance to be associated with fiber <code><phrase role="identifier">f</phrase></code>.
3222          </para>
3223        </listitem>
3224      </varlistentry>
3225    </variablelist>
3226    <para>
3227      <anchor id="context"/><bridgehead renderas="sect4" id="class_context_bridgehead">
3228  <phrase id="class_context"/>
3229  <link linkend="class_context">Class
3230      <code>context</code></link>
3231</bridgehead>
3232    </para>
3233    <para>
3234      While you are free to treat <code><phrase role="identifier">context</phrase><phrase
3235      role="special">*</phrase></code> as an opaque token, certain <code><phrase
3236      role="identifier">context</phrase></code> members may be useful to a custom
3237      scheduler implementation.
3238    </para>
3239    <para>
3240      <anchor id="ready_queue_t"/>Of particular note is the fact that <code><phrase
3241      role="identifier">context</phrase></code> contains a hook to participate in
3242      a <ulink url="http://www.boost.org/doc/libs/release/doc/html/intrusive/list.html"><code><phrase
3243      role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">intrusive</phrase><phrase
3244      role="special">::</phrase><phrase role="identifier">list</phrase></code></ulink>
3245      <literal>typedef</literal>&#8217;ed as <code><phrase role="identifier">boost</phrase><phrase
3246      role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase
3247      role="special">::</phrase><phrase role="identifier">scheduler</phrase><phrase
3248      role="special">::</phrase><phrase role="identifier">ready_queue_t</phrase></code>.
3249      This hook is reserved for use by <link linkend="class_algorithm"><code>algorithm</code></link> implementations. (For
3250      instance, <link linkend="class_round_robin"><code>round_robin</code></link> contains a <code><phrase role="identifier">ready_queue_t</phrase></code>
3251      instance to manage its ready fibers.) See <link linkend="context_ready_is_linked"><code>context::ready_is_linked()</code></link>,
3252      <link linkend="context_ready_link"><code>context::ready_link()</code></link>, <link linkend="context_ready_unlink"><code>context::ready_unlink()</code></link>.
3253    </para>
3254    <para>
3255      Your <code><phrase role="identifier">algorithm</phrase></code> implementation
3256      may use any container you desire to manage passed <code><phrase role="identifier">context</phrase></code>
3257      instances. <code><phrase role="identifier">ready_queue_t</phrase></code> avoids
3258      some of the overhead of typical STL containers.
3259    </para>
3260<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>
3261
3262<phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase>
3263<phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase>
3264
3265<phrase role="keyword">enum</phrase> <phrase role="keyword">class</phrase> <phrase role="identifier">type</phrase> <phrase role="special">{</phrase>
3266  <phrase role="identifier">none</phrase>               <phrase role="special">=</phrase> <emphasis>unspecified</emphasis><phrase role="special">,</phrase>
3267  <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>
3268  <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>
3269  <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>
3270  <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>
3271<phrase role="special">};</phrase>
3272
3273<phrase role="keyword">class</phrase> <phrase role="identifier">context</phrase> <phrase role="special">{</phrase>
3274<phrase role="keyword">public</phrase><phrase role="special">:</phrase>
3275    <phrase role="keyword">class</phrase> <phrase role="identifier">id</phrase><phrase role="special">;</phrase>
3276
3277    <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>
3278
3279    <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>
3280    <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>
3281
3282    <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>
3283
3284    <phrase role="keyword">void</phrase> <phrase role="identifier">detach</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
3285    <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>
3286
3287    <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>
3288
3289    <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>
3290
3291    <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>
3292    <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>
3293    <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>
3294
3295    <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>
3296    <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>
3297    <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>
3298    <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>
3299    <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>
3300    <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>
3301
3302    <phrase role="keyword">void</phrase> <phrase role="identifier">ready_unlink</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
3303    <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>
3304    <phrase role="keyword">void</phrase> <phrase role="identifier">wait_unlink</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
3305
3306    <phrase role="keyword">void</phrase> <phrase role="identifier">suspend</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
3307    <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>
3308<phrase role="special">};</phrase>
3309
3310<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>
3311
3312<phrase role="special">}}</phrase>
3313</programlisting>
3314    <para>
3315      <bridgehead renderas="sect4" id="context_active_bridgehead">
3316  <phrase id="context_active"/>
3317  <link linkend="context_active">Static member function
3318      <code>active</code>()</link>
3319</bridgehead>
3320    </para>
3321<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>
3322</programlisting>
3323    <variablelist>
3324      <title></title>
3325      <varlistentry>
3326        <term>Returns:</term>
3327        <listitem>
3328          <para>
3329            Pointer to instance of current fiber.
3330          </para>
3331        </listitem>
3332      </varlistentry>
3333      <varlistentry>
3334        <term>Throws:</term>
3335        <listitem>
3336          <para>
3337            Nothing
3338          </para>
3339        </listitem>
3340      </varlistentry>
3341    </variablelist>
3342    <para>
3343      <bridgehead renderas="sect4" id="context_get_id_bridgehead">
3344  <phrase id="context_get_id"/>
3345  <link linkend="context_get_id">Member function <code>get_id</code>()</link>
3346</bridgehead>
3347    </para>
3348<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>
3349</programlisting>
3350    <variablelist>
3351      <title></title>
3352      <varlistentry>
3353        <term>Returns:</term>
3354        <listitem>
3355          <para>
3356            If <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>
3357            refers to a fiber of execution, an instance of <link linkend="class_fiber_id"><code><phrase
3358            role="identifier">fiber</phrase><phrase role="special">::</phrase><phrase
3359            role="identifier">id</phrase></code></link> that represents that fiber. Otherwise
3360            returns a default-constructed <link linkend="class_fiber_id"><code><phrase role="identifier">fiber</phrase><phrase
3361            role="special">::</phrase><phrase role="identifier">id</phrase></code></link>.
3362          </para>
3363        </listitem>
3364      </varlistentry>
3365      <varlistentry>
3366        <term>Throws:</term>
3367        <listitem>
3368          <para>
3369            Nothing
3370          </para>
3371        </listitem>
3372      </varlistentry>
3373      <varlistentry>
3374        <term>See also:</term>
3375        <listitem>
3376          <para>
3377            <link linkend="fiber_get_id"><code>fiber::get_id()</code></link>
3378          </para>
3379        </listitem>
3380      </varlistentry>
3381    </variablelist>
3382    <para>
3383      <bridgehead renderas="sect4" id="context_attach_bridgehead">
3384  <phrase id="context_attach"/>
3385  <link linkend="context_attach">Member function <code>attach</code>()</link>
3386</bridgehead>
3387    </para>
3388<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>
3389</programlisting>
3390    <variablelist>
3391      <title></title>
3392      <varlistentry>
3393        <term>Precondition:</term>
3394        <listitem>
3395          <para>
3396            <code><phrase role="keyword">this</phrase><phrase role="special">-&gt;</phrase><phrase
3397            role="identifier">get_scheduler</phrase><phrase role="special">()</phrase>
3398            <phrase role="special">==</phrase> <phrase role="keyword">nullptr</phrase></code>
3399          </para>
3400        </listitem>
3401      </varlistentry>
3402      <varlistentry>
3403        <term>Effects:</term>
3404        <listitem>
3405          <para>
3406            Attach fiber <code><phrase role="identifier">f</phrase></code> to scheduler
3407            running <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>.
3408          </para>
3409        </listitem>
3410      </varlistentry>
3411      <varlistentry>
3412        <term>Postcondition:</term>
3413        <listitem>
3414          <para>
3415            <code><phrase role="keyword">this</phrase><phrase role="special">-&gt;</phrase><phrase
3416            role="identifier">get_scheduler</phrase><phrase role="special">()</phrase>
3417            <phrase role="special">!=</phrase> <phrase role="keyword">nullptr</phrase></code>
3418          </para>
3419        </listitem>
3420      </varlistentry>
3421      <varlistentry>
3422        <term>Throws:</term>
3423        <listitem>
3424          <para>
3425            Nothing
3426          </para>
3427        </listitem>
3428      </varlistentry>
3429      <varlistentry>
3430        <term>Note:</term>
3431        <listitem>
3432          <para>
3433            A typical call: <code><phrase role="identifier">boost</phrase><phrase
3434            role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase
3435            role="special">::</phrase><phrase role="identifier">context</phrase><phrase
3436            role="special">::</phrase><phrase role="identifier">active</phrase><phrase
3437            role="special">()-&gt;</phrase><phrase role="identifier">attach</phrase><phrase
3438            role="special">(</phrase><phrase role="identifier">f</phrase><phrase
3439            role="special">);</phrase></code>
3440          </para>
3441        </listitem>
3442      </varlistentry>
3443      <varlistentry>
3444        <term>Note:</term>
3445        <listitem>
3446          <para>
3447            <code><phrase role="identifier">f</phrase></code> must not be the running
3448            fiber&#8217;s context. It must not be <link linkend="blocking"><emphasis>blocked</emphasis></link>
3449            or terminated. It must not be a <code><phrase role="identifier">pinned_context</phrase></code>.
3450            It must be currently detached. It must not currently be linked into an
3451            <link linkend="class_algorithm"><code>algorithm</code></link> implementation&#8217;s ready queue. Most of these conditions
3452            are implied by <code><phrase role="identifier">f</phrase></code> being
3453            owned by an <code><phrase role="identifier">algorithm</phrase></code>
3454            implementation: that is, it has been passed to <link linkend="algorithm_awakened"><code>algorithm::awakened()</code></link> but
3455            has not yet been returned by <link linkend="algorithm_pick_next"><code>algorithm::pick_next()</code></link>.
3456            Typically a <code><phrase role="identifier">pick_next</phrase><phrase
3457            role="special">()</phrase></code> implementation would call <code><phrase
3458            role="identifier">attach</phrase><phrase role="special">()</phrase></code>
3459            with the <code><phrase role="identifier">context</phrase><phrase role="special">*</phrase></code>
3460            it is about to return. It must first remove <code><phrase role="identifier">f</phrase></code>
3461            from its ready queue. You should never pass a <code><phrase role="identifier">pinned_context</phrase></code>
3462            to <code><phrase role="identifier">attach</phrase><phrase role="special">()</phrase></code>
3463            because you should never have called its <code><phrase role="identifier">detach</phrase><phrase
3464            role="special">()</phrase></code> method in the first place.
3465          </para>
3466        </listitem>
3467      </varlistentry>
3468    </variablelist>
3469    <para>
3470      <bridgehead renderas="sect4" id="context_detach_bridgehead">
3471  <phrase id="context_detach"/>
3472  <link linkend="context_detach">Member function <code>detach</code>()</link>
3473</bridgehead>
3474    </para>
3475<programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">detach</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
3476</programlisting>
3477    <variablelist>
3478      <title></title>
3479      <varlistentry>
3480        <term>Precondition:</term>
3481        <listitem>
3482          <para>
3483            <code><phrase role="special">(</phrase><phrase role="keyword">this</phrase><phrase
3484            role="special">-&gt;</phrase><phrase role="identifier">get_scheduler</phrase><phrase
3485            role="special">()</phrase> <phrase role="special">!=</phrase> <phrase
3486            role="keyword">nullptr</phrase><phrase role="special">)</phrase> <phrase
3487            role="special">&amp;&amp;</phrase> <phrase role="special">!</phrase>
3488            <phrase role="keyword">this</phrase><phrase role="special">-&gt;</phrase><phrase
3489            role="identifier">is_context</phrase><phrase role="special">(</phrase><phrase
3490            role="identifier">pinned_context</phrase><phrase role="special">)</phrase></code>
3491          </para>
3492        </listitem>
3493      </varlistentry>
3494      <varlistentry>
3495        <term>Effects:</term>
3496        <listitem>
3497          <para>
3498            Detach fiber <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>
3499            from its scheduler running <code><phrase role="special">*</phrase><phrase
3500            role="keyword">this</phrase></code>.
3501          </para>
3502        </listitem>
3503      </varlistentry>
3504      <varlistentry>
3505        <term>Throws:</term>
3506        <listitem>
3507          <para>
3508            Nothing
3509          </para>
3510        </listitem>
3511      </varlistentry>
3512      <varlistentry>
3513        <term>Postcondition:</term>
3514        <listitem>
3515          <para>
3516            <code><phrase role="keyword">this</phrase><phrase role="special">-&gt;</phrase><phrase
3517            role="identifier">get_scheduler</phrase><phrase role="special">()</phrase>
3518            <phrase role="special">==</phrase> <phrase role="keyword">nullptr</phrase></code>
3519          </para>
3520        </listitem>
3521      </varlistentry>
3522      <varlistentry>
3523        <term>Note:</term>
3524        <listitem>
3525          <para>
3526            This method must be called on the thread with which the fiber is currently
3527            associated. <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>
3528            must not be the running fiber&#8217;s context. It must not be <link linkend="blocking"><emphasis>blocked</emphasis></link>
3529            or terminated. It must not be a <code><phrase role="identifier">pinned_context</phrase></code>.
3530            It must not be detached already. It must not already be linked into an
3531            <link linkend="class_algorithm"><code>algorithm</code></link> implementation&#8217;s ready queue. Most of these conditions
3532            are implied by <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>
3533            being passed to <link linkend="algorithm_awakened"><code>algorithm::awakened()</code></link>; an <code><phrase
3534            role="identifier">awakened</phrase><phrase role="special">()</phrase></code>
3535            implementation must, however, test for <code><phrase role="identifier">pinned_context</phrase></code>.
3536            It must call <code><phrase role="identifier">detach</phrase><phrase role="special">()</phrase></code>
3537            <emphasis>before</emphasis> linking <code><phrase role="special">*</phrase><phrase
3538            role="keyword">this</phrase></code> into its ready queue.
3539          </para>
3540        </listitem>
3541      </varlistentry>
3542      <varlistentry>
3543        <term>Note:</term>
3544        <listitem>
3545          <para>
3546            In particular, it is erroneous to attempt to migrate a fiber from one
3547            thread to another by calling both <code><phrase role="identifier">detach</phrase><phrase
3548            role="special">()</phrase></code> and <code><phrase role="identifier">attach</phrase><phrase
3549            role="special">()</phrase></code> in the <link linkend="algorithm_pick_next"><code>algorithm::pick_next()</code></link> method.
3550            <code><phrase role="identifier">pick_next</phrase><phrase role="special">()</phrase></code>
3551            is called on the intended destination thread. <code><phrase role="identifier">detach</phrase><phrase
3552            role="special">()</phrase></code> must be called on the fiber&#8217;s original
3553            thread. You must call <code><phrase role="identifier">detach</phrase><phrase
3554            role="special">()</phrase></code> in the corresponding <code><phrase
3555            role="identifier">awakened</phrase><phrase role="special">()</phrase></code>
3556            method.
3557          </para>
3558        </listitem>
3559      </varlistentry>
3560      <varlistentry>
3561        <term>Note:</term>
3562        <listitem>
3563          <para>
3564            Unless you intend make a fiber available for potential migration to a
3565            different thread, you should call neither <code><phrase role="identifier">detach</phrase><phrase
3566            role="special">()</phrase></code> nor <code><phrase role="identifier">attach</phrase><phrase
3567            role="special">()</phrase></code> with its <code><phrase role="identifier">context</phrase></code>.
3568          </para>
3569        </listitem>
3570      </varlistentry>
3571    </variablelist>
3572    <para>
3573      <bridgehead renderas="sect4" id="context_is_context_bridgehead">
3574  <phrase id="context_is_context"/>
3575  <link linkend="context_is_context">Member function
3576      <code>is_context</code>()</link>
3577</bridgehead>
3578    </para>
3579<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>
3580</programlisting>
3581    <variablelist>
3582      <title></title>
3583      <varlistentry>
3584        <term>Returns:</term>
3585        <listitem>
3586          <para>
3587            <code><phrase role="keyword">true</phrase></code> if <code><phrase role="special">*</phrase><phrase
3588            role="keyword">this</phrase></code> is of the specified type.
3589          </para>
3590        </listitem>
3591      </varlistentry>
3592      <varlistentry>
3593        <term>Throws:</term>
3594        <listitem>
3595          <para>
3596            Nothing
3597          </para>
3598        </listitem>
3599      </varlistentry>
3600      <varlistentry>
3601        <term>Note:</term>
3602        <listitem>
3603          <para>
3604            <code><phrase role="identifier">type</phrase><phrase role="special">::</phrase><phrase
3605            role="identifier">worker_context</phrase></code> here means any fiber
3606            not special to the library. For <code><phrase role="identifier">type</phrase><phrase
3607            role="special">::</phrase><phrase role="identifier">main_context</phrase></code>
3608            the <code><phrase role="identifier">context</phrase></code> is associated
3609            with the <quote>main</quote> fiber of the thread: the one implicitly
3610            created by the thread itself, rather than one explicitly created by
3611            <emphasis role="bold">Boost.Fiber</emphasis>. For <code><phrase role="identifier">type</phrase><phrase
3612            role="special">::</phrase><phrase role="identifier">dispatcher_context</phrase></code>
3613            the <code><phrase role="identifier">context</phrase></code> is associated
3614            with a <quote>dispatching</quote> fiber, responsible for dispatching
3615            awakened fibers to a scheduler&#8217;s ready-queue. The <quote>dispatching</quote>
3616            fiber is an implementation detail of the fiber manager. The context of
3617            the <quote>main</quote> or <quote>dispatching</quote> fiber &mdash; any fiber
3618            for which <code><phrase role="identifier">is_context</phrase><phrase
3619            role="special">(</phrase><phrase role="identifier">pinned_context</phrase><phrase
3620            role="special">)</phrase></code> is <code><phrase role="keyword">true</phrase></code>
3621            &mdash; must never be passed to <link linkend="context_detach"><code>context::detach()</code></link>.
3622          </para>
3623        </listitem>
3624      </varlistentry>
3625    </variablelist>
3626    <para>
3627      <bridgehead renderas="sect4" id="context_is_terminated_bridgehead">
3628  <phrase id="context_is_terminated"/>
3629  <link linkend="context_is_terminated">Member
3630      function <code>is_terminated</code>()</link>
3631</bridgehead>
3632    </para>
3633<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>
3634</programlisting>
3635    <variablelist>
3636      <title></title>
3637      <varlistentry>
3638        <term>Returns:</term>
3639        <listitem>
3640          <para>
3641            <code><phrase role="keyword">true</phrase></code> if <code><phrase role="special">*</phrase><phrase
3642            role="keyword">this</phrase></code> is no longer a valid context.
3643          </para>
3644        </listitem>
3645      </varlistentry>
3646      <varlistentry>
3647        <term>Throws:</term>
3648        <listitem>
3649          <para>
3650            Nothing
3651          </para>
3652        </listitem>
3653      </varlistentry>
3654      <varlistentry>
3655        <term>Note:</term>
3656        <listitem>
3657          <para>
3658            The <code><phrase role="identifier">context</phrase></code> has returned
3659            from its fiber-function and is no longer considered a valid context.
3660          </para>
3661        </listitem>
3662      </varlistentry>
3663    </variablelist>
3664    <para>
3665      <bridgehead renderas="sect4" id="context_ready_is_linked_bridgehead">
3666  <phrase id="context_ready_is_linked"/>
3667  <link linkend="context_ready_is_linked">Member
3668      function <code>ready_is_linked</code>()</link>
3669</bridgehead>
3670    </para>
3671<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>
3672</programlisting>
3673    <variablelist>
3674      <title></title>
3675      <varlistentry>
3676        <term>Returns:</term>
3677        <listitem>
3678          <para>
3679            <code><phrase role="keyword">true</phrase></code> if <code><phrase role="special">*</phrase><phrase
3680            role="keyword">this</phrase></code> is stored in an <link linkend="class_algorithm"><code>algorithm</code></link>
3681implementation&#8217;s
3682            ready-queue.
3683          </para>
3684        </listitem>
3685      </varlistentry>
3686      <varlistentry>
3687        <term>Throws:</term>
3688        <listitem>
3689          <para>
3690            Nothing
3691          </para>
3692        </listitem>
3693      </varlistentry>
3694      <varlistentry>
3695        <term>Note:</term>
3696        <listitem>
3697          <para>
3698            Specifically, this method indicates whether <link linkend="context_ready_link"><code>context::ready_link()</code></link> has
3699            been called on <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>.
3700            <code><phrase role="identifier">ready_is_linked</phrase><phrase role="special">()</phrase></code>
3701            has no information about participation in any other containers.
3702          </para>
3703        </listitem>
3704      </varlistentry>
3705    </variablelist>
3706    <para>
3707      <bridgehead renderas="sect4" id="context_remote_ready_is_linked_bridgehead">
3708  <phrase id="context_remote_ready_is_linked"/>
3709  <link linkend="context_remote_ready_is_linked">Member
3710      function <code>remote_ready_is_linked</code>()</link>
3711</bridgehead>
3712    </para>
3713<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>
3714</programlisting>
3715    <variablelist>
3716      <title></title>
3717      <varlistentry>
3718        <term>Returns:</term>
3719        <listitem>
3720          <para>
3721            <code><phrase role="keyword">true</phrase></code> if <code><phrase role="special">*</phrase><phrase
3722            role="keyword">this</phrase></code> is stored in the fiber manager&#8217;s remote-ready-queue.
3723          </para>
3724        </listitem>
3725      </varlistentry>
3726      <varlistentry>
3727        <term>Throws:</term>
3728        <listitem>
3729          <para>
3730            Nothing
3731          </para>
3732        </listitem>
3733      </varlistentry>
3734      <varlistentry>
3735        <term>Note:</term>
3736        <listitem>
3737          <para>
3738            A <code><phrase role="identifier">context</phrase></code> signaled as
3739            ready by another thread is first stored in the fiber manager&#8217;s remote-ready-queue.
3740            This is the mechanism by which the fiber manager protects an <link linkend="class_algorithm"><code>algorithm</code></link> implementation
3741            from cross-thread <link linkend="algorithm_awakened"><code>algorithm::awakened()</code></link> calls.
3742          </para>
3743        </listitem>
3744      </varlistentry>
3745    </variablelist>
3746    <para>
3747      <bridgehead renderas="sect4" id="context_wait_is_linked_bridgehead">
3748  <phrase id="context_wait_is_linked"/>
3749  <link linkend="context_wait_is_linked">Member
3750      function <code>wait_is_linked</code>()</link>
3751</bridgehead>
3752    </para>
3753<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>
3754</programlisting>
3755    <variablelist>
3756      <title></title>
3757      <varlistentry>
3758        <term>Returns:</term>
3759        <listitem>
3760          <para>
3761            <code><phrase role="keyword">true</phrase></code> if <code><phrase role="special">*</phrase><phrase
3762            role="keyword">this</phrase></code> is stored in the wait-queue of some
3763            synchronization object.
3764          </para>
3765        </listitem>
3766      </varlistentry>
3767      <varlistentry>
3768        <term>Throws:</term>
3769        <listitem>
3770          <para>
3771            Nothing
3772          </para>
3773        </listitem>
3774      </varlistentry>
3775      <varlistentry>
3776        <term>Note:</term>
3777        <listitem>
3778          <para>
3779            The <code><phrase role="identifier">context</phrase></code> of a fiber
3780            waiting on a synchronization object (e.g. <code><phrase role="identifier">mutex</phrase></code>,
3781            <code><phrase role="identifier">condition_variable</phrase></code> etc.)
3782            is stored in the wait-queue of that synchronization object.
3783          </para>
3784        </listitem>
3785      </varlistentry>
3786    </variablelist>
3787    <para>
3788      <bridgehead renderas="sect4" id="context_ready_link_bridgehead">
3789  <phrase id="context_ready_link"/>
3790  <link linkend="context_ready_link">Member function
3791      <code>ready_link</code>()</link>
3792</bridgehead>
3793    </para>
3794<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>
3795<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>
3796</programlisting>
3797    <variablelist>
3798      <title></title>
3799      <varlistentry>
3800        <term>Effects:</term>
3801        <listitem>
3802          <para>
3803            Stores <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>
3804            in ready-queue <code><phrase role="identifier">lst</phrase></code>.
3805          </para>
3806        </listitem>
3807      </varlistentry>
3808      <varlistentry>
3809        <term>Throws:</term>
3810        <listitem>
3811          <para>
3812            Nothing
3813          </para>
3814        </listitem>
3815      </varlistentry>
3816      <varlistentry>
3817        <term>Note:</term>
3818        <listitem>
3819          <para>
3820            Argument <code><phrase role="identifier">lst</phrase></code> must be
3821            a doubly-linked list from <ulink url="http://www.boost.org/doc/libs/release/libs/intrusive/index.html">Boost.Intrusive</ulink>,
3822            e.g. an instance of <code><phrase role="identifier">boost</phrase><phrase
3823            role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase
3824            role="special">::</phrase><phrase role="identifier">scheduler</phrase><phrase
3825            role="special">::</phrase><phrase role="identifier">ready_queue_t</phrase></code>.
3826            Specifically, it must be a <ulink url="http://www.boost.org/doc/libs/release/doc/html/intrusive/list.html"><code><phrase
3827            role="identifier">boost</phrase><phrase role="special">::</phrase><phrase
3828            role="identifier">intrusive</phrase><phrase role="special">::</phrase><phrase
3829            role="identifier">list</phrase></code></ulink> compatible with the <code><phrase
3830            role="identifier">list_member_hook</phrase></code> stored in the <code><phrase
3831            role="identifier">context</phrase></code> object.
3832          </para>
3833        </listitem>
3834      </varlistentry>
3835    </variablelist>
3836    <para>
3837      <bridgehead renderas="sect4" id="context_remote_ready_link_bridgehead">
3838  <phrase id="context_remote_ready_link"/>
3839  <link linkend="context_remote_ready_link">Member
3840      function <code>remote_ready_link</code>()</link>
3841</bridgehead>
3842    </para>
3843<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>
3844<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>
3845</programlisting>
3846    <variablelist>
3847      <title></title>
3848      <varlistentry>
3849        <term>Effects:</term>
3850        <listitem>
3851          <para>
3852            Stores <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>
3853            in remote-ready-queue <code><phrase role="identifier">lst</phrase></code>.
3854          </para>
3855        </listitem>
3856      </varlistentry>
3857      <varlistentry>
3858        <term>Throws:</term>
3859        <listitem>
3860          <para>
3861            Nothing
3862          </para>
3863        </listitem>
3864      </varlistentry>
3865      <varlistentry>
3866        <term>Note:</term>
3867        <listitem>
3868          <para>
3869            Argument <code><phrase role="identifier">lst</phrase></code> must be
3870            a doubly-linked list from <ulink url="http://www.boost.org/doc/libs/release/libs/intrusive/index.html">Boost.Intrusive</ulink>.
3871          </para>
3872        </listitem>
3873      </varlistentry>
3874    </variablelist>
3875    <para>
3876      <bridgehead renderas="sect4" id="context_wait_link_bridgehead">
3877  <phrase id="context_wait_link"/>
3878  <link linkend="context_wait_link">Member function
3879      <code>wait_link</code>()</link>
3880</bridgehead>
3881    </para>
3882<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>
3883<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>
3884</programlisting>
3885    <variablelist>
3886      <title></title>
3887      <varlistentry>
3888        <term>Effects:</term>
3889        <listitem>
3890          <para>
3891            Stores <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>
3892            in wait-queue <code><phrase role="identifier">lst</phrase></code>.
3893          </para>
3894        </listitem>
3895      </varlistentry>
3896      <varlistentry>
3897        <term>Throws:</term>
3898        <listitem>
3899          <para>
3900            Nothing
3901          </para>
3902        </listitem>
3903      </varlistentry>
3904      <varlistentry>
3905        <term>Note:</term>
3906        <listitem>
3907          <para>
3908            Argument <code><phrase role="identifier">lst</phrase></code> must be
3909            a doubly-linked list from <ulink url="http://www.boost.org/doc/libs/release/libs/intrusive/index.html">Boost.Intrusive</ulink>.
3910          </para>
3911        </listitem>
3912      </varlistentry>
3913    </variablelist>
3914    <para>
3915      <bridgehead renderas="sect4" id="context_ready_unlink_bridgehead">
3916  <phrase id="context_ready_unlink"/>
3917  <link linkend="context_ready_unlink">Member
3918      function <code>ready_unlink</code>()</link>
3919</bridgehead>
3920    </para>
3921<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>
3922</programlisting>
3923    <variablelist>
3924      <title></title>
3925      <varlistentry>
3926        <term>Effects:</term>
3927        <listitem>
3928          <para>
3929            Removes <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>
3930            from ready-queue: undoes the effect of <link linkend="context_ready_link"><code>context::ready_link()</code></link>.
3931          </para>
3932        </listitem>
3933      </varlistentry>
3934      <varlistentry>
3935        <term>Throws:</term>
3936        <listitem>
3937          <para>
3938            Nothing
3939          </para>
3940        </listitem>
3941      </varlistentry>
3942    </variablelist>
3943    <para>
3944      <bridgehead renderas="sect4" id="context_remote_ready_unlink_bridgehead">
3945  <phrase id="context_remote_ready_unlink"/>
3946  <link linkend="context_remote_ready_unlink">Member
3947      function <code>remote_ready_unlink</code>()</link>
3948</bridgehead>
3949    </para>
3950<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>
3951</programlisting>
3952    <variablelist>
3953      <title></title>
3954      <varlistentry>
3955        <term>Effects:</term>
3956        <listitem>
3957          <para>
3958            Removes <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>
3959            from remote-ready-queue.
3960          </para>
3961        </listitem>
3962      </varlistentry>
3963      <varlistentry>
3964        <term>Throws:</term>
3965        <listitem>
3966          <para>
3967            Nothing
3968          </para>
3969        </listitem>
3970      </varlistentry>
3971    </variablelist>
3972    <para>
3973      <bridgehead renderas="sect4" id="context_wait_unlink_bridgehead">
3974  <phrase id="context_wait_unlink"/>
3975  <link linkend="context_wait_unlink">Member
3976      function <code>wait_unlink</code>()</link>
3977</bridgehead>
3978    </para>
3979<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>
3980</programlisting>
3981    <variablelist>
3982      <title></title>
3983      <varlistentry>
3984        <term>Effects:</term>
3985        <listitem>
3986          <para>
3987            Removes <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>
3988            from wait-queue.
3989          </para>
3990        </listitem>
3991      </varlistentry>
3992      <varlistentry>
3993        <term>Throws:</term>
3994        <listitem>
3995          <para>
3996            Nothing
3997          </para>
3998        </listitem>
3999      </varlistentry>
4000    </variablelist>
4001    <para>
4002      <bridgehead renderas="sect4" id="context_suspend_bridgehead">
4003  <phrase id="context_suspend"/>
4004  <link linkend="context_suspend">Member function <code>suspend</code>()</link>
4005</bridgehead>
4006    </para>
4007<programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">suspend</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
4008</programlisting>
4009    <variablelist>
4010      <title></title>
4011      <varlistentry>
4012        <term>Effects:</term>
4013        <listitem>
4014          <para>
4015            Suspends the running fiber (the fiber associated with <code><phrase role="special">*</phrase><phrase
4016            role="keyword">this</phrase></code>) until some other fiber passes <code><phrase
4017            role="keyword">this</phrase></code> to <link linkend="context_schedule"><code>context::schedule()</code></link>.
4018            <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>
4019            is marked as not-ready, and control passes to the scheduler to select
4020            another fiber to run.
4021          </para>
4022        </listitem>
4023      </varlistentry>
4024      <varlistentry>
4025        <term>Throws:</term>
4026        <listitem>
4027          <para>
4028            Nothing
4029          </para>
4030        </listitem>
4031      </varlistentry>
4032      <varlistentry>
4033        <term>Note:</term>
4034        <listitem>
4035          <para>
4036            This is a low-level API potentially useful for integration with other
4037            frameworks. It is not intended to be directly invoked by a typical application
4038            program.
4039          </para>
4040        </listitem>
4041      </varlistentry>
4042      <varlistentry>
4043        <term>Note:</term>
4044        <listitem>
4045          <para>
4046            The burden is on the caller to arrange for a call to <code><phrase role="identifier">schedule</phrase><phrase
4047            role="special">()</phrase></code> with a pointer to <code><phrase role="keyword">this</phrase></code>
4048            at some future time.
4049          </para>
4050        </listitem>
4051      </varlistentry>
4052    </variablelist>
4053    <para>
4054      <bridgehead renderas="sect4" id="context_schedule_bridgehead">
4055  <phrase id="context_schedule"/>
4056  <link linkend="context_schedule">Member function
4057      <code>schedule</code>()</link>
4058</bridgehead>
4059    </para>
4060<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>
4061</programlisting>
4062    <variablelist>
4063      <title></title>
4064      <varlistentry>
4065        <term>Effects:</term>
4066        <listitem>
4067          <para>
4068            Mark the fiber associated with context <code><phrase role="special">*</phrase><phrase
4069            role="identifier">ctx</phrase></code> as being ready to run. This does
4070            not immediately resume that fiber; rather it passes the fiber to the
4071            scheduler for subsequent resumption. If the scheduler is idle (has not
4072            returned from a call to <link linkend="algorithm_suspend_until"><code>algorithm::suspend_until()</code></link>),
4073            <link linkend="algorithm_notify"><code>algorithm::notify()</code></link> is called to wake it up.
4074          </para>
4075        </listitem>
4076      </varlistentry>
4077      <varlistentry>
4078        <term>Throws:</term>
4079        <listitem>
4080          <para>
4081            Nothing
4082          </para>
4083        </listitem>
4084      </varlistentry>
4085      <varlistentry>
4086        <term>Note:</term>
4087        <listitem>
4088          <para>
4089            This is a low-level API potentially useful for integration with other
4090            frameworks. It is not intended to be directly invoked by a typical application
4091            program.
4092          </para>
4093        </listitem>
4094      </varlistentry>
4095      <varlistentry>
4096        <term>Note:</term>
4097        <listitem>
4098          <para>
4099            It is explicitly supported to call <code><phrase role="identifier">schedule</phrase><phrase
4100            role="special">(</phrase><phrase role="identifier">ctx</phrase><phrase
4101            role="special">)</phrase></code> from a thread other than the one on
4102            which <code><phrase role="special">*</phrase><phrase role="identifier">ctx</phrase></code>
4103            is currently suspended. The corresponding fiber will be resumed on its
4104            original thread in due course.
4105          </para>
4106        </listitem>
4107      </varlistentry>
4108    </variablelist>
4109    <para>
4110      <bridgehead renderas="sect4" id="context_less_bridgehead">
4111  <phrase id="context_less"/>
4112  <link linkend="context_less">Non-member function <code>operator&lt;()</code></link>
4113</bridgehead>
4114    </para>
4115<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>
4116</programlisting>
4117    <variablelist>
4118      <title></title>
4119      <varlistentry>
4120        <term>Returns:</term>
4121        <listitem>
4122          <para>
4123            <code><phrase role="keyword">true</phrase></code> if <code><phrase role="identifier">l</phrase><phrase
4124            role="special">.</phrase><phrase role="identifier">get_id</phrase><phrase
4125            role="special">()</phrase> <phrase role="special">&lt;</phrase> <phrase
4126            role="identifier">r</phrase><phrase role="special">.</phrase><phrase
4127            role="identifier">get_id</phrase><phrase role="special">()</phrase></code>
4128            is <code><phrase role="keyword">true</phrase></code>, <code><phrase role="keyword">false</phrase></code>
4129            otherwise.
4130          </para>
4131        </listitem>
4132      </varlistentry>
4133      <varlistentry>
4134        <term>Throws:</term>
4135        <listitem>
4136          <para>
4137            Nothing.
4138          </para>
4139        </listitem>
4140      </varlistentry>
4141    </variablelist>
4142  </section>
4143  <section id="fiber.stack">
4144    <title><anchor id="stack"/><link linkend="fiber.stack">Stack allocation</link></title>
4145    <para>
4146      A <link linkend="class_fiber"><code>fiber</code></link> uses internally an __econtext__ which manages a set of registers
4147      and a stack. The memory used by the stack is allocated/deallocated via a <emphasis>stack_allocator</emphasis>
4148      which is required to model a <link linkend="stack_allocator_concept"><emphasis>stack-allocator
4149      concept</emphasis></link>.
4150    </para>
4151    <para>
4152      A <emphasis>stack_allocator</emphasis> can be passed to <link linkend="fiber_fiber"><code><phrase
4153      role="identifier">fiber</phrase><phrase role="special">::</phrase><phrase role="identifier">fiber</phrase><phrase
4154      role="special">()</phrase></code></link> or to <link linkend="fibers_async"><code>fibers::async()</code></link>.
4155    </para>
4156    <anchor id="stack_allocator_concept"/>
4157    <bridgehead renderas="sect3" id="fiber.stack.h0">
4158      <phrase id="fiber.stack.stack_allocator_concept"/><link linkend="fiber.stack.stack_allocator_concept">stack-allocator
4159      concept</link>
4160    </bridgehead>
4161    <para>
4162      A <emphasis>stack_allocator</emphasis> must satisfy the <emphasis>stack-allocator
4163      concept</emphasis> requirements shown in the following table, in which <code><phrase
4164      role="identifier">a</phrase></code> is an object of a <emphasis>stack_allocator</emphasis>
4165      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
4166      role="identifier">stack_context</phrase></code></ulink>, and <code><phrase
4167      role="identifier">size</phrase></code> is a <code><phrase role="identifier">std</phrase><phrase
4168      role="special">::</phrase><phrase role="identifier">size_t</phrase></code>:
4169    </para>
4170    <informaltable frame="all">
4171      <tgroup cols="3">
4172        <thead>
4173          <row>
4174            <entry>
4175              <para>
4176                expression
4177              </para>
4178            </entry>
4179            <entry>
4180              <para>
4181                return type
4182              </para>
4183            </entry>
4184            <entry>
4185              <para>
4186                notes
4187              </para>
4188            </entry>
4189          </row>
4190        </thead>
4191        <tbody>
4192          <row>
4193            <entry>
4194              <para>
4195                <code><phrase role="identifier">a</phrase><phrase role="special">(</phrase><phrase
4196                role="identifier">size</phrase><phrase role="special">)</phrase></code>
4197              </para>
4198            </entry>
4199            <entry>
4200            </entry>
4201            <entry>
4202              <para>
4203                creates a stack allocator
4204              </para>
4205            </entry>
4206          </row>
4207          <row>
4208            <entry>
4209              <para>
4210                <code><phrase role="identifier">a</phrase><phrase role="special">.</phrase><phrase
4211                role="identifier">allocate</phrase><phrase role="special">()</phrase></code>
4212              </para>
4213            </entry>
4214            <entry>
4215              <para>
4216                <ulink url="http://www.boost.org/doc/libs/release/libs/context/doc/html/context/stack/stack_context.html"><code><phrase
4217                role="identifier">stack_context</phrase></code></ulink>
4218              </para>
4219            </entry>
4220            <entry>
4221              <para>
4222                creates a stack
4223              </para>
4224            </entry>
4225          </row>
4226          <row>
4227            <entry>
4228              <para>
4229                <code><phrase role="identifier">a</phrase><phrase role="special">.</phrase><phrase
4230                role="identifier">deallocate</phrase><phrase role="special">(</phrase>
4231                <phrase role="identifier">sctx</phrase><phrase role="special">)</phrase></code>
4232              </para>
4233            </entry>
4234            <entry>
4235              <para>
4236                <code><phrase role="keyword">void</phrase></code>
4237              </para>
4238            </entry>
4239            <entry>
4240              <para>
4241                deallocates the stack created by <code><phrase role="identifier">a</phrase><phrase
4242                role="special">.</phrase><phrase role="identifier">allocate</phrase><phrase
4243                role="special">()</phrase></code>
4244              </para>
4245            </entry>
4246          </row>
4247        </tbody>
4248      </tgroup>
4249    </informaltable>
4250    <important>
4251      <para>
4252        The implementation of <code><phrase role="identifier">allocate</phrase><phrase
4253        role="special">()</phrase></code> might include logic to protect against
4254        exceeding the context's available stack size rather than leaving it as undefined
4255        behaviour.
4256      </para>
4257    </important>
4258    <important>
4259      <para>
4260        Calling <code><phrase role="identifier">deallocate</phrase><phrase role="special">()</phrase></code>
4261        with a <ulink url="http://www.boost.org/doc/libs/release/libs/context/doc/html/context/stack/stack_context.html"><code><phrase
4262        role="identifier">stack_context</phrase></code></ulink> not obtained from
4263        <code><phrase role="identifier">allocate</phrase><phrase role="special">()</phrase></code>
4264        results in undefined behaviour.
4265      </para>
4266    </important>
4267    <note>
4268      <para>
4269        The memory for the stack is not required to be aligned; alignment takes place
4270        inside __econtext__.
4271      </para>
4272    </note>
4273    <para>
4274      See also <ulink url="http://www.boost.org/doc/libs/release/libs/context/doc/html/context/stack.html">Boost.Context
4275      stack allocation</ulink>. In particular, <code><phrase role="identifier">traits_type</phrase></code>
4276      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
4277      role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">context</phrase><phrase
4278      role="special">::</phrase><phrase role="identifier">stack_traits</phrase></code></ulink>.
4279    </para>
4280    <para>
4281      <bridgehead renderas="sect4" id="class_protected_fixedsize_stack_bridgehead">
4282  <phrase id="class_protected_fixedsize_stack"/>
4283  <link linkend="class_protected_fixedsize_stack">Class
4284      <code>protected_fixedsize_stack</code></link>
4285</bridgehead>
4286    </para>
4287    <para>
4288      <emphasis role="bold">Boost.Fiber</emphasis> provides the class <link linkend="class_protected_fixedsize_stack"><code>protected_fixedsize_stack</code></link> which
4289      models the <link linkend="stack_allocator_concept"><emphasis>stack-allocator
4290      concept</emphasis></link>. It appends a guard page at the end of each stack
4291      to protect against exceeding the stack. If the guard page is accessed (read
4292      or write operation) a segmentation fault/access violation is generated by the
4293      operating system.
4294    </para>
4295    <important>
4296      <para>
4297        Using <link linkend="class_protected_fixedsize_stack"><code>protected_fixedsize_stack</code></link> is expensive.
4298        Launching a new fiber with a stack of this type incurs the overhead of setting
4299        the memory protection; once allocated, this stack is just as efficient to
4300        use as <link linkend="class_fixedsize_stack"><code>fixedsize_stack</code></link>.
4301      </para>
4302    </important>
4303    <note>
4304      <para>
4305        The appended <code><phrase role="identifier">guard</phrase> <phrase role="identifier">page</phrase></code>
4306        is <emphasis role="bold">not</emphasis> mapped to physical memory, only virtual
4307        addresses are used.
4308      </para>
4309    </note>
4310<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>
4311
4312<phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase>
4313<phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase>
4314
4315<phrase role="keyword">struct</phrase> <phrase role="identifier">protected_fixedsize</phrase> <phrase role="special">{</phrase>
4316    <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>
4317
4318    <phrase role="identifier">stack_context</phrase> <phrase role="identifier">allocate</phrase><phrase role="special">();</phrase>
4319
4320    <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>
4321<phrase role="special">}</phrase>
4322
4323<phrase role="special">}}</phrase>
4324</programlisting>
4325    <para>
4326      <bridgehead renderas="sect4" id="protected_fixedsize_allocate_bridgehead">
4327  <phrase id="protected_fixedsize_allocate"/>
4328  <link linkend="protected_fixedsize_allocate">Member
4329      function <code>allocate</code>()</link>
4330</bridgehead>
4331    </para>
4332<programlisting><phrase role="identifier">stack_context</phrase> <phrase role="identifier">allocate</phrase><phrase role="special">();</phrase>
4333</programlisting>
4334    <variablelist>
4335      <title></title>
4336      <varlistentry>
4337        <term>Preconditions:</term>
4338        <listitem>
4339          <para>
4340            <code><phrase role="identifier">traits_type</phrase><phrase role="special">::</phrase><phrase
4341            role="identifier">minimum_size</phrase><phrase role="special">()</phrase>
4342            <phrase role="special">&lt;=</phrase> <phrase role="identifier">size</phrase></code>
4343            and <code><phrase role="identifier">traits_type</phrase><phrase role="special">::</phrase><phrase
4344            role="identifier">is_unbounded</phrase><phrase role="special">()</phrase>
4345            <phrase role="special">||</phrase> <phrase role="special">(</phrase>
4346            <phrase role="identifier">size</phrase> <phrase role="special">&lt;=</phrase>
4347            <phrase role="identifier">traits_type</phrase><phrase role="special">::</phrase><phrase
4348            role="identifier">maximum_size</phrase><phrase role="special">()</phrase>
4349            <phrase role="special">)</phrase></code>.
4350          </para>
4351        </listitem>
4352      </varlistentry>
4353      <varlistentry>
4354        <term>Effects:</term>
4355        <listitem>
4356          <para>
4357            Allocates memory of at least <code><phrase role="identifier">size</phrase></code>
4358            bytes and stores a pointer to the stack and its actual size in <code><phrase
4359            role="identifier">sctx</phrase></code>. Depending on the architecture
4360            (the stack grows downwards/upwards) the stored address is the highest/lowest
4361            address of the stack.
4362          </para>
4363        </listitem>
4364      </varlistentry>
4365    </variablelist>
4366    <para>
4367      <bridgehead renderas="sect4" id="protected_fixesize_deallocate_bridgehead">
4368  <phrase id="protected_fixesize_deallocate"/>
4369  <link linkend="protected_fixesize_deallocate">Member
4370      function <code>deallocate</code>()</link>
4371</bridgehead>
4372    </para>
4373<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>
4374</programlisting>
4375    <variablelist>
4376      <title></title>
4377      <varlistentry>
4378        <term>Preconditions:</term>
4379        <listitem>
4380          <para>
4381            <code><phrase role="identifier">sctx</phrase><phrase role="special">.</phrase><phrase
4382            role="identifier">sp</phrase></code> is valid, <code><phrase role="identifier">traits_type</phrase><phrase
4383            role="special">::</phrase><phrase role="identifier">minimum_size</phrase><phrase
4384            role="special">()</phrase> <phrase role="special">&lt;=</phrase> <phrase
4385            role="identifier">sctx</phrase><phrase role="special">.</phrase><phrase
4386            role="identifier">size</phrase></code> and <code><phrase role="identifier">traits_type</phrase><phrase
4387            role="special">::</phrase><phrase role="identifier">is_unbounded</phrase><phrase
4388            role="special">()</phrase> <phrase role="special">||</phrase> <phrase
4389            role="special">(</phrase> <phrase role="identifier">sctx</phrase><phrase
4390            role="special">.</phrase><phrase role="identifier">size</phrase> <phrase
4391            role="special">&lt;=</phrase> <phrase role="identifier">traits_type</phrase><phrase
4392            role="special">::</phrase><phrase role="identifier">maximum_size</phrase><phrase
4393            role="special">()</phrase> <phrase role="special">)</phrase></code>.
4394          </para>
4395        </listitem>
4396      </varlistentry>
4397      <varlistentry>
4398        <term>Effects:</term>
4399        <listitem>
4400          <para>
4401            Deallocates the stack space.
4402          </para>
4403        </listitem>
4404      </varlistentry>
4405    </variablelist>
4406    <para>
4407      <bridgehead renderas="sect4" id="class_pooled_fixedsize_stack_bridgehead">
4408  <phrase id="class_pooled_fixedsize_stack"/>
4409  <link linkend="class_pooled_fixedsize_stack">Class
4410      <code>pooled_fixedsize_stack</code></link>
4411</bridgehead>
4412    </para>
4413    <para>
4414      <emphasis role="bold">Boost.Fiber</emphasis> provides the class <link linkend="class_pooled_fixedsize_stack"><code>pooled_fixedsize_stack</code></link> which
4415      models the <link linkend="stack_allocator_concept"><emphasis>stack-allocator
4416      concept</emphasis></link>. In contrast to <link linkend="class_protected_fixedsize_stack"><code>protected_fixedsize_stack</code></link> it
4417      does not append a guard page at the end of each stack. The memory is managed
4418      internally by <ulink url="http://www.boost.org/doc/libs/release/libs/pool/doc/html/boost/pool.html"><code><phrase
4419      role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">pool</phrase><phrase
4420      role="special">&lt;&gt;</phrase></code></ulink>.
4421    </para>
4422<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>
4423
4424<phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase>
4425<phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase>
4426
4427<phrase role="keyword">struct</phrase> <phrase role="identifier">pooled_fixedsize_stack</phrase> <phrase role="special">{</phrase>
4428    <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>
4429
4430    <phrase role="identifier">stack_context</phrase> <phrase role="identifier">allocate</phrase><phrase role="special">();</phrase>
4431
4432    <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>
4433<phrase role="special">}</phrase>
4434
4435<phrase role="special">}}</phrase>
4436</programlisting>
4437    <para>
4438      <bridgehead renderas="sect4" id="pooled_fixedsize_bridgehead">
4439  <phrase id="pooled_fixedsize"/>
4440  <link linkend="pooled_fixedsize">Constructor</link>
4441</bridgehead>
4442    </para>
4443<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>
4444</programlisting>
4445    <variablelist>
4446      <title></title>
4447      <varlistentry>
4448        <term>Preconditions:</term>
4449        <listitem>
4450          <para>
4451            <code><phrase role="identifier">traits_type</phrase><phrase role="special">::</phrase><phrase
4452            role="identifier">is_unbounded</phrase><phrase role="special">()</phrase>
4453            <phrase role="special">||</phrase> <phrase role="special">(</phrase>
4454            <phrase role="identifier">traits_type</phrase><phrase role="special">::</phrase><phrase
4455            role="identifier">maximum_size</phrase><phrase role="special">()</phrase>
4456            <phrase role="special">&gt;=</phrase> <phrase role="identifier">stack_size</phrase><phrase
4457            role="special">)</phrase></code> and <code><phrase role="number">0</phrase>
4458            <phrase role="special">&lt;</phrase> <phrase role="identifier">next_size</phrase></code>.
4459          </para>
4460        </listitem>
4461      </varlistentry>
4462      <varlistentry>
4463        <term>Effects:</term>
4464        <listitem>
4465          <para>
4466            Allocates memory of at least <code><phrase role="identifier">stack_size</phrase></code>
4467            bytes and stores a pointer to the stack and its actual size in <code><phrase
4468            role="identifier">sctx</phrase></code>. Depending on the architecture
4469            (the stack grows downwards/upwards) the stored address is the highest/lowest
4470            address of the stack. Argument <code><phrase role="identifier">next_size</phrase></code>
4471            determines the number of stacks to request from the system the first
4472            time that <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>
4473            needs to allocate system memory. The third argument <code><phrase role="identifier">max_size</phrase></code>
4474            controls how much memory might be allocated for stacks &mdash; a value of zero
4475            means no upper limit.
4476          </para>
4477        </listitem>
4478      </varlistentry>
4479    </variablelist>
4480    <para>
4481      <bridgehead renderas="sect4" id="pooled_fixedsize_allocate_bridgehead">
4482  <phrase id="pooled_fixedsize_allocate"/>
4483  <link linkend="pooled_fixedsize_allocate">Member
4484      function <code>allocate</code>()</link>
4485</bridgehead>
4486    </para>
4487<programlisting><phrase role="identifier">stack_context</phrase> <phrase role="identifier">allocate</phrase><phrase role="special">();</phrase>
4488</programlisting>
4489    <variablelist>
4490      <title></title>
4491      <varlistentry>
4492        <term>Preconditions:</term>
4493        <listitem>
4494          <para>
4495            <code><phrase role="identifier">traits_type</phrase><phrase role="special">::</phrase><phrase
4496            role="identifier">is_unbounded</phrase><phrase role="special">()</phrase>
4497            <phrase role="special">||</phrase> <phrase role="special">(</phrase>
4498            <phrase role="identifier">traits_type</phrase><phrase role="special">::</phrase><phrase
4499            role="identifier">maximum_size</phrase><phrase role="special">()</phrase>
4500            <phrase role="special">&gt;=</phrase> <phrase role="identifier">stack_size</phrase><phrase
4501            role="special">)</phrase></code>.
4502          </para>
4503        </listitem>
4504      </varlistentry>
4505      <varlistentry>
4506        <term>Effects:</term>
4507        <listitem>
4508          <para>
4509            Allocates memory of at least <code><phrase role="identifier">stack_size</phrase></code>
4510            bytes and stores a pointer to the stack and its actual size in <code><phrase
4511            role="identifier">sctx</phrase></code>. Depending on the architecture
4512            (the stack grows downwards/upwards) the stored address is the highest/lowest
4513            address of the stack.
4514          </para>
4515        </listitem>
4516      </varlistentry>
4517    </variablelist>
4518    <para>
4519      <bridgehead renderas="sect4" id="pooled_fixesize_deallocate_bridgehead">
4520  <phrase id="pooled_fixesize_deallocate"/>
4521  <link linkend="pooled_fixesize_deallocate">Member
4522      function <code>deallocate</code>()</link>
4523</bridgehead>
4524    </para>
4525<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>
4526</programlisting>
4527    <variablelist>
4528      <title></title>
4529      <varlistentry>
4530        <term>Preconditions:</term>
4531        <listitem>
4532          <para>
4533            <code><phrase role="identifier">sctx</phrase><phrase role="special">.</phrase><phrase
4534            role="identifier">sp</phrase></code> is valid, <code><phrase role="identifier">traits_type</phrase><phrase
4535            role="special">::</phrase><phrase role="identifier">is_unbounded</phrase><phrase
4536            role="special">()</phrase> <phrase role="special">||</phrase> <phrase
4537            role="special">(</phrase> <phrase role="identifier">traits_type</phrase><phrase
4538            role="special">::</phrase><phrase role="identifier">maximum_size</phrase><phrase
4539            role="special">()</phrase> <phrase role="special">&gt;=</phrase> <phrase
4540            role="identifier">sctx</phrase><phrase role="special">.</phrase><phrase
4541            role="identifier">size</phrase><phrase role="special">)</phrase></code>.
4542          </para>
4543        </listitem>
4544      </varlistentry>
4545      <varlistentry>
4546        <term>Effects:</term>
4547        <listitem>
4548          <para>
4549            Deallocates the stack space.
4550          </para>
4551        </listitem>
4552      </varlistentry>
4553    </variablelist>
4554    <note>
4555      <para>
4556        This stack allocator is not thread safe.
4557      </para>
4558    </note>
4559    <para>
4560      <bridgehead renderas="sect4" id="class_fixedsize_stack_bridgehead">
4561  <phrase id="class_fixedsize_stack"/>
4562  <link linkend="class_fixedsize_stack">Class
4563      <code>fixedsize_stack</code></link>
4564</bridgehead>
4565    </para>
4566    <para>
4567      <emphasis role="bold">Boost.Fiber</emphasis> provides the class <link linkend="class_fixedsize_stack"><code>fixedsize_stack</code></link> which
4568      models the <link linkend="stack_allocator_concept"><emphasis>stack-allocator
4569      concept</emphasis></link>. In contrast to <link linkend="class_protected_fixedsize_stack"><code>protected_fixedsize_stack</code></link> it
4570      does not append a guard page at the end of each stack. The memory is simply
4571      managed by <code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase
4572      role="identifier">malloc</phrase><phrase role="special">()</phrase></code>
4573      and <code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase
4574      role="identifier">free</phrase><phrase role="special">()</phrase></code>.
4575    </para>
4576<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>
4577
4578<phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase>
4579<phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase>
4580
4581<phrase role="keyword">struct</phrase> <phrase role="identifier">fixedsize_stack</phrase> <phrase role="special">{</phrase>
4582    <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>
4583
4584    <phrase role="identifier">stack_context</phrase> <phrase role="identifier">allocate</phrase><phrase role="special">();</phrase>
4585
4586    <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>
4587<phrase role="special">}</phrase>
4588
4589<phrase role="special">}}</phrase>
4590</programlisting>
4591    <para>
4592      <bridgehead renderas="sect4" id="fixedsize_allocate_bridgehead">
4593  <phrase id="fixedsize_allocate"/>
4594  <link linkend="fixedsize_allocate">Member function
4595      <code>allocate</code>()</link>
4596</bridgehead>
4597    </para>
4598<programlisting><phrase role="identifier">stack_context</phrase> <phrase role="identifier">allocate</phrase><phrase role="special">();</phrase>
4599</programlisting>
4600    <variablelist>
4601      <title></title>
4602      <varlistentry>
4603        <term>Preconditions:</term>
4604        <listitem>
4605          <para>
4606            <code><phrase role="identifier">traits_type</phrase><phrase role="special">::</phrase><phrase
4607            role="identifier">minimum_size</phrase><phrase role="special">()</phrase>
4608            <phrase role="special">&lt;=</phrase> <phrase role="identifier">size</phrase></code>
4609            and <code><phrase role="identifier">traits_type</phrase><phrase role="special">::</phrase><phrase
4610            role="identifier">is_unbounded</phrase><phrase role="special">()</phrase>
4611            <phrase role="special">||</phrase> <phrase role="special">(</phrase>
4612            <phrase role="identifier">traits_type</phrase><phrase role="special">::</phrase><phrase
4613            role="identifier">maximum_size</phrase><phrase role="special">()</phrase>
4614            <phrase role="special">&gt;=</phrase> <phrase role="identifier">size</phrase><phrase
4615            role="special">)</phrase></code>.
4616          </para>
4617        </listitem>
4618      </varlistentry>
4619      <varlistentry>
4620        <term>Effects:</term>
4621        <listitem>
4622          <para>
4623            Allocates memory of at least <code><phrase role="identifier">size</phrase></code>
4624            bytes and stores a pointer to the stack and its actual size in <code><phrase
4625            role="identifier">sctx</phrase></code>. Depending on the architecture
4626            (the stack grows downwards/upwards) the stored address is the highest/lowest
4627            address of the stack.
4628          </para>
4629        </listitem>
4630      </varlistentry>
4631    </variablelist>
4632    <para>
4633      <bridgehead renderas="sect4" id="fixesize_deallocate_bridgehead">
4634  <phrase id="fixesize_deallocate"/>
4635  <link linkend="fixesize_deallocate">Member
4636      function <code>deallocate</code>()</link>
4637</bridgehead>
4638    </para>
4639<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>
4640</programlisting>
4641    <variablelist>
4642      <title></title>
4643      <varlistentry>
4644        <term>Preconditions:</term>
4645        <listitem>
4646          <para>
4647            <code><phrase role="identifier">sctx</phrase><phrase role="special">.</phrase><phrase
4648            role="identifier">sp</phrase></code> is valid, <code><phrase role="identifier">traits_type</phrase><phrase
4649            role="special">::</phrase><phrase role="identifier">minimum_size</phrase><phrase
4650            role="special">()</phrase> <phrase role="special">&lt;=</phrase> <phrase
4651            role="identifier">sctx</phrase><phrase role="special">.</phrase><phrase
4652            role="identifier">size</phrase></code> and <code><phrase role="identifier">traits_type</phrase><phrase
4653            role="special">::</phrase><phrase role="identifier">is_unbounded</phrase><phrase
4654            role="special">()</phrase> <phrase role="special">||</phrase> <phrase
4655            role="special">(</phrase> <phrase role="identifier">traits_type</phrase><phrase
4656            role="special">::</phrase><phrase role="identifier">maximum_size</phrase><phrase
4657            role="special">()</phrase> <phrase role="special">&gt;=</phrase> <phrase
4658            role="identifier">sctx</phrase><phrase role="special">.</phrase><phrase
4659            role="identifier">size</phrase><phrase role="special">)</phrase></code>.
4660          </para>
4661        </listitem>
4662      </varlistentry>
4663      <varlistentry>
4664        <term>Effects:</term>
4665        <listitem>
4666          <para>
4667            Deallocates the stack space.
4668          </para>
4669        </listitem>
4670      </varlistentry>
4671    </variablelist>
4672    <para>
4673      <anchor id="segmented"/><bridgehead renderas="sect4" id="class_segmented_stack_bridgehead">
4674  <phrase id="class_segmented_stack"/>
4675  <link linkend="class_segmented_stack">Class
4676      <code>segmented_stack</code></link>
4677</bridgehead>
4678    </para>
4679    <para>
4680      <emphasis role="bold">Boost.Fiber</emphasis> supports usage of a <link linkend="class_segmented_stack"><code>segmented_stack</code></link>,
4681      i.e. the stack grows on demand. The fiber is created with a minimal stack size
4682      which will be increased as required. Class <link linkend="class_segmented_stack"><code>segmented_stack</code></link> models
4683      the <link linkend="stack_allocator_concept"><emphasis>stack-allocator concept</emphasis></link>.
4684      In contrast to <link linkend="class_protected_fixedsize_stack"><code>protected_fixedsize_stack</code></link> and
4685      <link linkend="class_fixedsize_stack"><code>fixedsize_stack</code></link> it creates a stack which grows on demand.
4686    </para>
4687    <note>
4688      <para>
4689        Segmented stacks are currently only supported by <emphasis role="bold">gcc</emphasis>
4690        from version <emphasis role="bold">4.7</emphasis> and <emphasis role="bold">clang</emphasis>
4691        from version <emphasis role="bold">3.4</emphasis> onwards. In order to use
4692        a <link linkend="class_segmented_stack"><code>segmented_stack</code></link> <emphasis role="bold">Boost.Fiber</emphasis>
4693        must be built with property <code><phrase role="identifier">segmented</phrase><phrase
4694        role="special">-</phrase><phrase role="identifier">stacks</phrase></code>,
4695        e.g. <emphasis role="bold">toolset=gcc segmented-stacks=on</emphasis> and
4696        applying BOOST_USE_SEGMENTED_STACKS at b2/bjam command line.
4697      </para>
4698    </note>
4699    <note>
4700      <para>
4701        Segmented stacks can only be used with callcc() using property <code><phrase
4702        role="identifier">context</phrase><phrase role="special">-</phrase><phrase
4703        role="identifier">impl</phrase><phrase role="special">=</phrase><phrase role="identifier">ucontext</phrase></code>.
4704      </para>
4705    </note>
4706<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>
4707
4708<phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase>
4709<phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase>
4710
4711<phrase role="keyword">struct</phrase> <phrase role="identifier">segmented_stack</phrase> <phrase role="special">{</phrase>
4712    <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>
4713
4714    <phrase role="identifier">stack_context</phrase> <phrase role="identifier">allocate</phrase><phrase role="special">();</phrase>
4715
4716    <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>
4717<phrase role="special">}</phrase>
4718
4719<phrase role="special">}}</phrase>
4720</programlisting>
4721    <para>
4722      <bridgehead renderas="sect4" id="segmented_allocate_bridgehead">
4723  <phrase id="segmented_allocate"/>
4724  <link linkend="segmented_allocate">Member function
4725      <code>allocate</code>()</link>
4726</bridgehead>
4727    </para>
4728<programlisting><phrase role="identifier">stack_context</phrase> <phrase role="identifier">allocate</phrase><phrase role="special">();</phrase>
4729</programlisting>
4730    <variablelist>
4731      <title></title>
4732      <varlistentry>
4733        <term>Preconditions:</term>
4734        <listitem>
4735          <para>
4736            <code><phrase role="identifier">traits_type</phrase><phrase role="special">::</phrase><phrase
4737            role="identifier">minimum_size</phrase><phrase role="special">()</phrase>
4738            <phrase role="special">&lt;=</phrase> <phrase role="identifier">size</phrase></code>
4739            and <code><phrase role="identifier">traits_type</phrase><phrase role="special">::</phrase><phrase
4740            role="identifier">is_unbounded</phrase><phrase role="special">()</phrase>
4741            <phrase role="special">||</phrase> <phrase role="special">(</phrase>
4742            <phrase role="identifier">traits_type</phrase><phrase role="special">::</phrase><phrase
4743            role="identifier">maximum_size</phrase><phrase role="special">()</phrase>
4744            <phrase role="special">&gt;=</phrase> <phrase role="identifier">size</phrase><phrase
4745            role="special">)</phrase></code>.
4746          </para>
4747        </listitem>
4748      </varlistentry>
4749      <varlistentry>
4750        <term>Effects:</term>
4751        <listitem>
4752          <para>
4753            Allocates memory of at least <code><phrase role="identifier">size</phrase></code>
4754            bytes and stores a pointer to the stack and its actual size in <code><phrase
4755            role="identifier">sctx</phrase></code>. Depending on the architecture
4756            (the stack grows downwards/upwards) the stored address is the highest/lowest
4757            address of the stack.
4758          </para>
4759        </listitem>
4760      </varlistentry>
4761    </variablelist>
4762    <para>
4763      <bridgehead renderas="sect4" id="segmented_deallocate_bridgehead">
4764  <phrase id="segmented_deallocate"/>
4765  <link linkend="segmented_deallocate">Member
4766      function <code>deallocate</code>()</link>
4767</bridgehead>
4768    </para>
4769<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>
4770</programlisting>
4771    <variablelist>
4772      <title></title>
4773      <varlistentry>
4774        <term>Preconditions:</term>
4775        <listitem>
4776          <para>
4777            <code><phrase role="identifier">sctx</phrase><phrase role="special">.</phrase><phrase
4778            role="identifier">sp</phrase></code> is valid, <code><phrase role="identifier">traits_type</phrase><phrase
4779            role="special">::</phrase><phrase role="identifier">minimum_size</phrase><phrase
4780            role="special">()</phrase> <phrase role="special">&lt;=</phrase> <phrase
4781            role="identifier">sctx</phrase><phrase role="special">.</phrase><phrase
4782            role="identifier">size</phrase></code> and <code><phrase role="identifier">traits_type</phrase><phrase
4783            role="special">::</phrase><phrase role="identifier">is_unbounded</phrase><phrase
4784            role="special">()</phrase> <phrase role="special">||</phrase> <phrase
4785            role="special">(</phrase> <phrase role="identifier">traits_type</phrase><phrase
4786            role="special">::</phrase><phrase role="identifier">maximum_size</phrase><phrase
4787            role="special">()</phrase> <phrase role="special">&gt;=</phrase> <phrase
4788            role="identifier">sctx</phrase><phrase role="special">.</phrase><phrase
4789            role="identifier">size</phrase><phrase role="special">)</phrase></code>.
4790          </para>
4791        </listitem>
4792      </varlistentry>
4793      <varlistentry>
4794        <term>Effects:</term>
4795        <listitem>
4796          <para>
4797            Deallocates the stack space.
4798          </para>
4799        </listitem>
4800      </varlistentry>
4801    </variablelist>
4802    <note>
4803      <para>
4804        If the library is compiled for segmented stacks, <link linkend="class_segmented_stack"><code>segmented_stack</code></link> is
4805        the only available stack allocator.
4806      </para>
4807    </note>
4808    <section id="fiber.stack.valgrind">
4809      <title><link linkend="fiber.stack.valgrind">Support for valgrind</link></title>
4810      <para>
4811        Running programs that switch stacks under valgrind causes problems. Property
4812        (b2 command-line) <code><phrase role="identifier">valgrind</phrase><phrase
4813        role="special">=</phrase><phrase role="identifier">on</phrase></code> let
4814        valgrind treat the memory regions as stack space which suppresses the errors.
4815      </para>
4816    </section>
4817  </section>
4818  <section id="fiber.synchronization">
4819    <title><anchor id="synchronization"/><link linkend="fiber.synchronization">Synchronization</link></title>
4820    <para>
4821      In general, <emphasis role="bold">Boost.Fiber</emphasis> synchronization objects
4822      can neither be moved nor copied. A synchronization object acts as a mutually-agreed
4823      rendezvous point between different fibers. If such an object were copied somewhere
4824      else, the new copy would have no consumers. If such an object were <emphasis>moved</emphasis>
4825      somewhere else, leaving the original instance in an unspecified state, existing
4826      consumers would behave strangely.
4827    </para>
4828    <para>
4829      The fiber synchronization objects provided by this library will, by default,
4830      safely synchronize fibers running on different threads. However, this level
4831      of synchronization can be removed (for performance) by building the library
4832      with <emphasis role="bold"><code><phrase role="identifier">BOOST_FIBERS_NO_ATOMICS</phrase></code></emphasis>
4833      defined. When the library is built with that macro, you must ensure that all
4834      the fibers referencing a particular synchronization object are running in the
4835      same thread.
4836    </para>
4837    <section id="fiber.synchronization.mutex_types">
4838      <title><link linkend="fiber.synchronization.mutex_types">Mutex Types</link></title>
4839      <para>
4840        <bridgehead renderas="sect4" id="class_mutex_bridgehead">
4841  <phrase id="class_mutex"/>
4842  <link linkend="class_mutex">Class <code>mutex</code></link>
4843</bridgehead>
4844      </para>
4845<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>
4846
4847<phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase>
4848<phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase>
4849
4850<phrase role="keyword">class</phrase> <phrase role="identifier">mutex</phrase> <phrase role="special">{</phrase>
4851<phrase role="keyword">public</phrase><phrase role="special">:</phrase>
4852    <phrase role="identifier">mutex</phrase><phrase role="special">();</phrase>
4853    <phrase role="special">~</phrase><phrase role="identifier">mutex</phrase><phrase role="special">();</phrase>
4854
4855    <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>
4856    <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>
4857
4858    <phrase role="keyword">void</phrase> <phrase role="identifier">lock</phrase><phrase role="special">();</phrase>
4859    <phrase role="keyword">bool</phrase> <phrase role="identifier">try_lock</phrase><phrase role="special">();</phrase>
4860    <phrase role="keyword">void</phrase> <phrase role="identifier">unlock</phrase><phrase role="special">();</phrase>
4861<phrase role="special">};</phrase>
4862
4863<phrase role="special">}}</phrase>
4864</programlisting>
4865      <para>
4866        <link linkend="class_mutex"><code>mutex</code></link> provides an exclusive-ownership mutex. At most one fiber
4867        can own the lock on a given instance of <link linkend="class_mutex"><code>mutex</code></link> at any time. Multiple
4868        concurrent calls to <code><phrase role="identifier">lock</phrase><phrase
4869        role="special">()</phrase></code>, <code><phrase role="identifier">try_lock</phrase><phrase
4870        role="special">()</phrase></code> and <code><phrase role="identifier">unlock</phrase><phrase
4871        role="special">()</phrase></code> shall be permitted.
4872      </para>
4873      <para>
4874        Any fiber blocked in <code><phrase role="identifier">lock</phrase><phrase
4875        role="special">()</phrase></code> is suspended until the owning fiber releases
4876        the lock by calling <code><phrase role="identifier">unlock</phrase><phrase
4877        role="special">()</phrase></code>.
4878      </para>
4879      <para>
4880        <bridgehead renderas="sect4" id="mutex_lock_bridgehead">
4881  <phrase id="mutex_lock"/>
4882  <link linkend="mutex_lock">Member function <code>lock</code>()</link>
4883</bridgehead>
4884      </para>
4885<programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">lock</phrase><phrase role="special">();</phrase>
4886</programlisting>
4887      <variablelist>
4888        <title></title>
4889        <varlistentry>
4890          <term>Precondition:</term>
4891          <listitem>
4892            <para>
4893              The calling fiber doesn't own the mutex.
4894            </para>
4895          </listitem>
4896        </varlistentry>
4897        <varlistentry>
4898          <term>Effects:</term>
4899          <listitem>
4900            <para>
4901              The current fiber blocks until ownership can be obtained.
4902            </para>
4903          </listitem>
4904        </varlistentry>
4905        <varlistentry>
4906          <term>Throws:</term>
4907          <listitem>
4908            <para>
4909              <code><phrase role="identifier">lock_error</phrase></code>
4910            </para>
4911          </listitem>
4912        </varlistentry>
4913        <varlistentry>
4914          <term>Error Conditions:</term>
4915          <listitem>
4916            <para>
4917              <emphasis role="bold">resource_deadlock_would_occur</emphasis>: if
4918              <code><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase
4919              role="identifier">this_fiber</phrase><phrase role="special">::</phrase><phrase
4920              role="identifier">get_id</phrase><phrase role="special">()</phrase></code>
4921              already owns the mutex.
4922            </para>
4923          </listitem>
4924        </varlistentry>
4925      </variablelist>
4926      <para>
4927        <bridgehead renderas="sect4" id="mutex_try_lock_bridgehead">
4928  <phrase id="mutex_try_lock"/>
4929  <link linkend="mutex_try_lock">Member function <code>try_lock</code>()</link>
4930</bridgehead>
4931      </para>
4932<programlisting><phrase role="keyword">bool</phrase> <phrase role="identifier">try_lock</phrase><phrase role="special">();</phrase>
4933</programlisting>
4934      <variablelist>
4935        <title></title>
4936        <varlistentry>
4937          <term>Precondition:</term>
4938          <listitem>
4939            <para>
4940              The calling fiber doesn't own the mutex.
4941            </para>
4942          </listitem>
4943        </varlistentry>
4944        <varlistentry>
4945          <term>Effects:</term>
4946          <listitem>
4947            <para>
4948              Attempt to obtain ownership for the current fiber without blocking.
4949            </para>
4950          </listitem>
4951        </varlistentry>
4952        <varlistentry>
4953          <term>Returns:</term>
4954          <listitem>
4955            <para>
4956              <code><phrase role="keyword">true</phrase></code> if ownership was
4957              obtained for the current fiber, <code><phrase role="keyword">false</phrase></code>
4958              otherwise.
4959            </para>
4960          </listitem>
4961        </varlistentry>
4962        <varlistentry>
4963          <term>Throws:</term>
4964          <listitem>
4965            <para>
4966              <code><phrase role="identifier">lock_error</phrase></code>
4967            </para>
4968          </listitem>
4969        </varlistentry>
4970        <varlistentry>
4971          <term>Error Conditions:</term>
4972          <listitem>
4973            <para>
4974              <emphasis role="bold">resource_deadlock_would_occur</emphasis>: if
4975              <code><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase
4976              role="identifier">this_fiber</phrase><phrase role="special">::</phrase><phrase
4977              role="identifier">get_id</phrase><phrase role="special">()</phrase></code>
4978              already owns the mutex.
4979            </para>
4980          </listitem>
4981        </varlistentry>
4982      </variablelist>
4983      <para>
4984        <bridgehead renderas="sect4" id="mutex_unlock_bridgehead">
4985  <phrase id="mutex_unlock"/>
4986  <link linkend="mutex_unlock">Member function <code>unlock</code>()</link>
4987</bridgehead>
4988      </para>
4989<programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">unlock</phrase><phrase role="special">();</phrase>
4990</programlisting>
4991      <variablelist>
4992        <title></title>
4993        <varlistentry>
4994          <term>Precondition:</term>
4995          <listitem>
4996            <para>
4997              The current fiber owns <code><phrase role="special">*</phrase><phrase
4998              role="keyword">this</phrase></code>.
4999            </para>
5000          </listitem>
5001        </varlistentry>
5002        <varlistentry>
5003          <term>Effects:</term>
5004          <listitem>
5005            <para>
5006              Releases a lock on <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>
5007              by the current fiber.
5008            </para>
5009          </listitem>
5010        </varlistentry>
5011        <varlistentry>
5012          <term>Throws:</term>
5013          <listitem>
5014            <para>
5015              <code><phrase role="identifier">lock_error</phrase></code>
5016            </para>
5017          </listitem>
5018        </varlistentry>
5019        <varlistentry>
5020          <term>Error Conditions:</term>
5021          <listitem>
5022            <para>
5023              <emphasis role="bold">operation_not_permitted</emphasis>: if <code><phrase
5024              role="identifier">boost</phrase><phrase role="special">::</phrase><phrase
5025              role="identifier">this_fiber</phrase><phrase role="special">::</phrase><phrase
5026              role="identifier">get_id</phrase><phrase role="special">()</phrase></code>
5027              does not own the mutex.
5028            </para>
5029          </listitem>
5030        </varlistentry>
5031      </variablelist>
5032      <para>
5033        <bridgehead renderas="sect4" id="class_timed_mutex_bridgehead">
5034  <phrase id="class_timed_mutex"/>
5035  <link linkend="class_timed_mutex">Class <code>timed_mutex</code></link>
5036</bridgehead>
5037      </para>
5038<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>
5039
5040<phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase>
5041<phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase>
5042
5043<phrase role="keyword">class</phrase> <phrase role="identifier">timed_mutex</phrase> <phrase role="special">{</phrase>
5044<phrase role="keyword">public</phrase><phrase role="special">:</phrase>
5045    <phrase role="identifier">timed_mutex</phrase><phrase role="special">();</phrase>
5046    <phrase role="special">~</phrase><phrase role="identifier">timed_mutex</phrase><phrase role="special">();</phrase>
5047
5048    <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>
5049    <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>
5050
5051    <phrase role="keyword">void</phrase> <phrase role="identifier">lock</phrase><phrase role="special">();</phrase>
5052    <phrase role="keyword">bool</phrase> <phrase role="identifier">try_lock</phrase><phrase role="special">();</phrase>
5053    <phrase role="keyword">void</phrase> <phrase role="identifier">unlock</phrase><phrase role="special">();</phrase>
5054
5055    <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>
5056    <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>
5057    <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>
5058    <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>
5059<phrase role="special">};</phrase>
5060
5061<phrase role="special">}}</phrase>
5062</programlisting>
5063      <para>
5064        <link linkend="class_timed_mutex"><code>timed_mutex</code></link> provides an exclusive-ownership mutex. At most
5065        one fiber can own the lock on a given instance of <link linkend="class_timed_mutex"><code>timed_mutex</code></link> at
5066        any time. Multiple concurrent calls to <code><phrase role="identifier">lock</phrase><phrase
5067        role="special">()</phrase></code>, <code><phrase role="identifier">try_lock</phrase><phrase
5068        role="special">()</phrase></code>, <code><phrase role="identifier">try_lock_until</phrase><phrase
5069        role="special">()</phrase></code>, <code><phrase role="identifier">try_lock_for</phrase><phrase
5070        role="special">()</phrase></code> and <code><phrase role="identifier">unlock</phrase><phrase
5071        role="special">()</phrase></code> shall be permitted.
5072      </para>
5073      <para>
5074        <bridgehead renderas="sect4" id="timed_mutex_lock_bridgehead">
5075  <phrase id="timed_mutex_lock"/>
5076  <link linkend="timed_mutex_lock">Member function
5077        <code>lock</code>()</link>
5078</bridgehead>
5079      </para>
5080<programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">lock</phrase><phrase role="special">();</phrase>
5081</programlisting>
5082      <variablelist>
5083        <title></title>
5084        <varlistentry>
5085          <term>Precondition:</term>
5086          <listitem>
5087            <para>
5088              The calling fiber doesn't own the mutex.
5089            </para>
5090          </listitem>
5091        </varlistentry>
5092        <varlistentry>
5093          <term>Effects:</term>
5094          <listitem>
5095            <para>
5096              The current fiber blocks until ownership can be obtained.
5097            </para>
5098          </listitem>
5099        </varlistentry>
5100        <varlistentry>
5101          <term>Throws:</term>
5102          <listitem>
5103            <para>
5104              <code><phrase role="identifier">lock_error</phrase></code>
5105            </para>
5106          </listitem>
5107        </varlistentry>
5108        <varlistentry>
5109          <term>Error Conditions:</term>
5110          <listitem>
5111            <para>
5112              <emphasis role="bold">resource_deadlock_would_occur</emphasis>: if
5113              <code><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase
5114              role="identifier">this_fiber</phrase><phrase role="special">::</phrase><phrase
5115              role="identifier">get_id</phrase><phrase role="special">()</phrase></code>
5116              already owns the mutex.
5117            </para>
5118          </listitem>
5119        </varlistentry>
5120      </variablelist>
5121      <para>
5122        <bridgehead renderas="sect4" id="timed_mutex_try_lock_bridgehead">
5123  <phrase id="timed_mutex_try_lock"/>
5124  <link linkend="timed_mutex_try_lock">Member
5125        function <code>try_lock</code>()</link>
5126</bridgehead>
5127      </para>
5128<programlisting><phrase role="keyword">bool</phrase> <phrase role="identifier">try_lock</phrase><phrase role="special">();</phrase>
5129</programlisting>
5130      <variablelist>
5131        <title></title>
5132        <varlistentry>
5133          <term>Precondition:</term>
5134          <listitem>
5135            <para>
5136              The calling fiber doesn't own the mutex.
5137            </para>
5138          </listitem>
5139        </varlistentry>
5140        <varlistentry>
5141          <term>Effects:</term>
5142          <listitem>
5143            <para>
5144              Attempt to obtain ownership for the current fiber without blocking.
5145            </para>
5146          </listitem>
5147        </varlistentry>
5148        <varlistentry>
5149          <term>Returns:</term>
5150          <listitem>
5151            <para>
5152              <code><phrase role="keyword">true</phrase></code> if ownership was
5153              obtained for the current fiber, <code><phrase role="keyword">false</phrase></code>
5154              otherwise.
5155            </para>
5156          </listitem>
5157        </varlistentry>
5158        <varlistentry>
5159          <term>Throws:</term>
5160          <listitem>
5161            <para>
5162              <code><phrase role="identifier">lock_error</phrase></code>
5163            </para>
5164          </listitem>
5165        </varlistentry>
5166        <varlistentry>
5167          <term>Error Conditions:</term>
5168          <listitem>
5169            <para>
5170              <emphasis role="bold">resource_deadlock_would_occur</emphasis>: if
5171              <code><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase
5172              role="identifier">this_fiber</phrase><phrase role="special">::</phrase><phrase
5173              role="identifier">get_id</phrase><phrase role="special">()</phrase></code>
5174              already owns the mutex.
5175            </para>
5176          </listitem>
5177        </varlistentry>
5178      </variablelist>
5179      <para>
5180        <bridgehead renderas="sect4" id="timed_mutex_unlock_bridgehead">
5181  <phrase id="timed_mutex_unlock"/>
5182  <link linkend="timed_mutex_unlock">Member function
5183        <code>unlock</code>()</link>
5184</bridgehead>
5185      </para>
5186<programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">unlock</phrase><phrase role="special">();</phrase>
5187</programlisting>
5188      <variablelist>
5189        <title></title>
5190        <varlistentry>
5191          <term>Precondition:</term>
5192          <listitem>
5193            <para>
5194              The current fiber owns <code><phrase role="special">*</phrase><phrase
5195              role="keyword">this</phrase></code>.
5196            </para>
5197          </listitem>
5198        </varlistentry>
5199        <varlistentry>
5200          <term>Effects:</term>
5201          <listitem>
5202            <para>
5203              Releases a lock on <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>
5204              by the current fiber.
5205            </para>
5206          </listitem>
5207        </varlistentry>
5208        <varlistentry>
5209          <term>Throws:</term>
5210          <listitem>
5211            <para>
5212              <code><phrase role="identifier">lock_error</phrase></code>
5213            </para>
5214          </listitem>
5215        </varlistentry>
5216        <varlistentry>
5217          <term>Error Conditions:</term>
5218          <listitem>
5219            <para>
5220              <emphasis role="bold">operation_not_permitted</emphasis>: if <code><phrase
5221              role="identifier">boost</phrase><phrase role="special">::</phrase><phrase
5222              role="identifier">this_fiber</phrase><phrase role="special">::</phrase><phrase
5223              role="identifier">get_id</phrase><phrase role="special">()</phrase></code>
5224              does not own the mutex.
5225            </para>
5226          </listitem>
5227        </varlistentry>
5228      </variablelist>
5229      <para>
5230        <bridgehead renderas="sect4" id="timed_mutex_try_lock_until_bridgehead">
5231  <phrase id="timed_mutex_try_lock_until"/>
5232  <link linkend="timed_mutex_try_lock_until">Templated
5233        member function <code>try_lock_until</code>()</link>
5234</bridgehead>
5235      </para>
5236<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>
5237<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>
5238</programlisting>
5239      <variablelist>
5240        <title></title>
5241        <varlistentry>
5242          <term>Precondition:</term>
5243          <listitem>
5244            <para>
5245              The calling fiber doesn't own the mutex.
5246            </para>
5247          </listitem>
5248        </varlistentry>
5249        <varlistentry>
5250          <term>Effects:</term>
5251          <listitem>
5252            <para>
5253              Attempt to obtain ownership for the current fiber. Blocks until ownership
5254              can be obtained, or the specified time is reached. If the specified
5255              time has already passed, behaves as <link linkend="timed_mutex_try_lock"><code>timed_mutex::try_lock()</code></link>.
5256            </para>
5257          </listitem>
5258        </varlistentry>
5259        <varlistentry>
5260          <term>Returns:</term>
5261          <listitem>
5262            <para>
5263              <code><phrase role="keyword">true</phrase></code> if ownership was
5264              obtained for the current fiber, <code><phrase role="keyword">false</phrase></code>
5265              otherwise.
5266            </para>
5267          </listitem>
5268        </varlistentry>
5269        <varlistentry>
5270          <term>Throws:</term>
5271          <listitem>
5272            <para>
5273              <code><phrase role="identifier">lock_error</phrase></code>, timeout-related
5274              exceptions.
5275            </para>
5276          </listitem>
5277        </varlistentry>
5278        <varlistentry>
5279          <term>Error Conditions:</term>
5280          <listitem>
5281            <para>
5282              <emphasis role="bold">resource_deadlock_would_occur</emphasis>: if
5283              <code><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase
5284              role="identifier">this_fiber</phrase><phrase role="special">::</phrase><phrase
5285              role="identifier">get_id</phrase><phrase role="special">()</phrase></code>
5286              already owns the mutex.
5287            </para>
5288          </listitem>
5289        </varlistentry>
5290      </variablelist>
5291      <para>
5292        <bridgehead renderas="sect4" id="timed_mutex_try_lock_for_bridgehead">
5293  <phrase id="timed_mutex_try_lock_for"/>
5294  <link linkend="timed_mutex_try_lock_for">Templated
5295        member function <code>try_lock_for</code>()</link>
5296</bridgehead>
5297      </para>
5298<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>
5299<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>
5300</programlisting>
5301      <variablelist>
5302        <title></title>
5303        <varlistentry>
5304          <term>Precondition:</term>
5305          <listitem>
5306            <para>
5307              The calling fiber doesn't own the mutex.
5308            </para>
5309          </listitem>
5310        </varlistentry>
5311        <varlistentry>
5312          <term>Effects:</term>
5313          <listitem>
5314            <para>
5315              Attempt to obtain ownership for the current fiber. Blocks until ownership
5316              can be obtained, or the specified time is reached. If the specified
5317              time has already passed, behaves as <link linkend="timed_mutex_try_lock"><code>timed_mutex::try_lock()</code></link>.
5318            </para>
5319          </listitem>
5320        </varlistentry>
5321        <varlistentry>
5322          <term>Returns:</term>
5323          <listitem>
5324            <para>
5325              <code><phrase role="keyword">true</phrase></code> if ownership was
5326              obtained for the current fiber, <code><phrase role="keyword">false</phrase></code>
5327              otherwise.
5328            </para>
5329          </listitem>
5330        </varlistentry>
5331        <varlistentry>
5332          <term>Throws:</term>
5333          <listitem>
5334            <para>
5335              <code><phrase role="identifier">lock_error</phrase></code>, timeout-related
5336              exceptions.
5337            </para>
5338          </listitem>
5339        </varlistentry>
5340        <varlistentry>
5341          <term>Error Conditions:</term>
5342          <listitem>
5343            <para>
5344              <emphasis role="bold">resource_deadlock_would_occur</emphasis>: if
5345              <code><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase
5346              role="identifier">this_fiber</phrase><phrase role="special">::</phrase><phrase
5347              role="identifier">get_id</phrase><phrase role="special">()</phrase></code>
5348              already owns the mutex.
5349            </para>
5350          </listitem>
5351        </varlistentry>
5352      </variablelist>
5353      <para>
5354        <bridgehead renderas="sect4" id="class_recursive_mutex_bridgehead">
5355  <phrase id="class_recursive_mutex"/>
5356  <link linkend="class_recursive_mutex">Class
5357        <code>recursive_mutex</code></link>
5358</bridgehead>
5359      </para>
5360<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>
5361
5362<phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase>
5363<phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase>
5364
5365<phrase role="keyword">class</phrase> <phrase role="identifier">recursive_mutex</phrase> <phrase role="special">{</phrase>
5366<phrase role="keyword">public</phrase><phrase role="special">:</phrase>
5367    <phrase role="identifier">recursive_mutex</phrase><phrase role="special">();</phrase>
5368    <phrase role="special">~</phrase><phrase role="identifier">recursive_mutex</phrase><phrase role="special">();</phrase>
5369
5370    <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>
5371    <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>
5372
5373    <phrase role="keyword">void</phrase> <phrase role="identifier">lock</phrase><phrase role="special">();</phrase>
5374    <phrase role="keyword">bool</phrase> <phrase role="identifier">try_lock</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
5375    <phrase role="keyword">void</phrase> <phrase role="identifier">unlock</phrase><phrase role="special">();</phrase>
5376<phrase role="special">};</phrase>
5377
5378<phrase role="special">}}</phrase>
5379</programlisting>
5380      <para>
5381        <link linkend="class_recursive_mutex"><code>recursive_mutex</code></link> provides an exclusive-ownership recursive
5382        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
5383        any time. Multiple concurrent calls to <code><phrase role="identifier">lock</phrase><phrase
5384        role="special">()</phrase></code>, <code><phrase role="identifier">try_lock</phrase><phrase
5385        role="special">()</phrase></code> and <code><phrase role="identifier">unlock</phrase><phrase
5386        role="special">()</phrase></code> shall be permitted. A fiber that already
5387        has exclusive ownership of a given <link linkend="class_recursive_mutex"><code>recursive_mutex</code></link> instance
5388        can call <code><phrase role="identifier">lock</phrase><phrase role="special">()</phrase></code>
5389        or <code><phrase role="identifier">try_lock</phrase><phrase role="special">()</phrase></code>
5390        to acquire an additional level of ownership of the mutex. <code><phrase role="identifier">unlock</phrase><phrase
5391        role="special">()</phrase></code> must be called once for each level of ownership
5392        acquired by a single fiber before ownership can be acquired by another fiber.
5393      </para>
5394      <para>
5395        <bridgehead renderas="sect4" id="recursive_mutex_lock_bridgehead">
5396  <phrase id="recursive_mutex_lock"/>
5397  <link linkend="recursive_mutex_lock">Member
5398        function <code>lock</code>()</link>
5399</bridgehead>
5400      </para>
5401<programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">lock</phrase><phrase role="special">();</phrase>
5402</programlisting>
5403      <variablelist>
5404        <title></title>
5405        <varlistentry>
5406          <term>Effects:</term>
5407          <listitem>
5408            <para>
5409              The current fiber blocks until ownership can be obtained.
5410            </para>
5411          </listitem>
5412        </varlistentry>
5413        <varlistentry>
5414          <term>Throws:</term>
5415          <listitem>
5416            <para>
5417              Nothing
5418            </para>
5419          </listitem>
5420        </varlistentry>
5421      </variablelist>
5422      <para>
5423        <bridgehead renderas="sect4" id="recursive_mutex_try_lock_bridgehead">
5424  <phrase id="recursive_mutex_try_lock"/>
5425  <link linkend="recursive_mutex_try_lock">Member
5426        function <code>try_lock</code>()</link>
5427</bridgehead>
5428      </para>
5429<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>
5430</programlisting>
5431      <variablelist>
5432        <title></title>
5433        <varlistentry>
5434          <term>Effects:</term>
5435          <listitem>
5436            <para>
5437              Attempt to obtain ownership for the current fiber without blocking.
5438            </para>
5439          </listitem>
5440        </varlistentry>
5441        <varlistentry>
5442          <term>Returns:</term>
5443          <listitem>
5444            <para>
5445              <code><phrase role="keyword">true</phrase></code> if ownership was
5446              obtained for the current fiber, <code><phrase role="keyword">false</phrase></code>
5447              otherwise.
5448            </para>
5449          </listitem>
5450        </varlistentry>
5451        <varlistentry>
5452          <term>Throws:</term>
5453          <listitem>
5454            <para>
5455              Nothing.
5456            </para>
5457          </listitem>
5458        </varlistentry>
5459      </variablelist>
5460      <para>
5461        <bridgehead renderas="sect4" id="recursive_mutex_unlock_bridgehead">
5462  <phrase id="recursive_mutex_unlock"/>
5463  <link linkend="recursive_mutex_unlock">Member
5464        function <code>unlock</code>()</link>
5465</bridgehead>
5466      </para>
5467<programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">unlock</phrase><phrase role="special">();</phrase>
5468</programlisting>
5469      <variablelist>
5470        <title></title>
5471        <varlistentry>
5472          <term>Effects:</term>
5473          <listitem>
5474            <para>
5475              Releases a lock on <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>
5476              by the current fiber.
5477            </para>
5478          </listitem>
5479        </varlistentry>
5480        <varlistentry>
5481          <term>Throws:</term>
5482          <listitem>
5483            <para>
5484              <code><phrase role="identifier">lock_error</phrase></code>
5485            </para>
5486          </listitem>
5487        </varlistentry>
5488        <varlistentry>
5489          <term>Error Conditions:</term>
5490          <listitem>
5491            <para>
5492              <emphasis role="bold">operation_not_permitted</emphasis>: if <code><phrase
5493              role="identifier">boost</phrase><phrase role="special">::</phrase><phrase
5494              role="identifier">this_fiber</phrase><phrase role="special">::</phrase><phrase
5495              role="identifier">get_id</phrase><phrase role="special">()</phrase></code>
5496              does not own the mutex.
5497            </para>
5498          </listitem>
5499        </varlistentry>
5500      </variablelist>
5501      <para>
5502        <bridgehead renderas="sect4" id="class_recursive_timed_mutex_bridgehead">
5503  <phrase id="class_recursive_timed_mutex"/>
5504  <link linkend="class_recursive_timed_mutex">Class
5505        <code>recursive_timed_mutex</code></link>
5506</bridgehead>
5507      </para>
5508<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>
5509
5510<phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase>
5511<phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase>
5512
5513<phrase role="keyword">class</phrase> <phrase role="identifier">recursive_timed_mutex</phrase> <phrase role="special">{</phrase>
5514<phrase role="keyword">public</phrase><phrase role="special">:</phrase>
5515    <phrase role="identifier">recursive_timed_mutex</phrase><phrase role="special">();</phrase>
5516    <phrase role="special">~</phrase><phrase role="identifier">recursive_timed_mutex</phrase><phrase role="special">();</phrase>
5517
5518    <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>
5519    <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>
5520
5521    <phrase role="keyword">void</phrase> <phrase role="identifier">lock</phrase><phrase role="special">();</phrase>
5522    <phrase role="keyword">bool</phrase> <phrase role="identifier">try_lock</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
5523    <phrase role="keyword">void</phrase> <phrase role="identifier">unlock</phrase><phrase role="special">();</phrase>
5524
5525    <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>
5526    <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>
5527    <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>
5528    <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>
5529<phrase role="special">};</phrase>
5530
5531<phrase role="special">}}</phrase>
5532</programlisting>
5533      <para>
5534        <link linkend="class_recursive_timed_mutex"><code>recursive_timed_mutex</code></link> provides an exclusive-ownership
5535        recursive mutex. At most one fiber can own the lock on a given instance of
5536        <link linkend="class_recursive_timed_mutex"><code>recursive_timed_mutex</code></link> at any time. Multiple concurrent
5537        calls to <code><phrase role="identifier">lock</phrase><phrase role="special">()</phrase></code>,
5538        <code><phrase role="identifier">try_lock</phrase><phrase role="special">()</phrase></code>,
5539        <code><phrase role="identifier">try_lock_for</phrase><phrase role="special">()</phrase></code>,
5540        <code><phrase role="identifier">try_lock_until</phrase><phrase role="special">()</phrase></code>
5541        and <code><phrase role="identifier">unlock</phrase><phrase role="special">()</phrase></code>
5542        shall be permitted. A fiber that already has exclusive ownership of a given
5543        <link linkend="class_recursive_timed_mutex"><code>recursive_timed_mutex</code></link> instance can call <code><phrase
5544        role="identifier">lock</phrase><phrase role="special">()</phrase></code>,
5545        <code><phrase role="identifier">try_lock</phrase><phrase role="special">()</phrase></code>,
5546        <code><phrase role="identifier">try_lock_for</phrase><phrase role="special">()</phrase></code>
5547        or <code><phrase role="identifier">try_lock_until</phrase><phrase role="special">()</phrase></code>
5548        to acquire an additional level of ownership of the mutex. <code><phrase role="identifier">unlock</phrase><phrase
5549        role="special">()</phrase></code> must be called once for each level of ownership
5550        acquired by a single fiber before ownership can be acquired by another fiber.
5551      </para>
5552      <para>
5553        <bridgehead renderas="sect4" id="recursive_timed_mutex_lock_bridgehead">
5554  <phrase id="recursive_timed_mutex_lock"/>
5555  <link linkend="recursive_timed_mutex_lock">Member
5556        function <code>lock</code>()</link>
5557</bridgehead>
5558      </para>
5559<programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">lock</phrase><phrase role="special">();</phrase>
5560</programlisting>
5561      <variablelist>
5562        <title></title>
5563        <varlistentry>
5564          <term>Effects:</term>
5565          <listitem>
5566            <para>
5567              The current fiber blocks until ownership can be obtained.
5568            </para>
5569          </listitem>
5570        </varlistentry>
5571        <varlistentry>
5572          <term>Throws:</term>
5573          <listitem>
5574            <para>
5575              Nothing
5576            </para>
5577          </listitem>
5578        </varlistentry>
5579      </variablelist>
5580      <para>
5581        <bridgehead renderas="sect4" id="recursive_timed_mutex_try_lock_bridgehead">
5582  <phrase id="recursive_timed_mutex_try_lock"/>
5583  <link linkend="recursive_timed_mutex_try_lock">Member
5584        function <code>try_lock</code>()</link>
5585</bridgehead>
5586      </para>
5587<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>
5588</programlisting>
5589      <variablelist>
5590        <title></title>
5591        <varlistentry>
5592          <term>Effects:</term>
5593          <listitem>
5594            <para>
5595              Attempt to obtain ownership for the current fiber without blocking.
5596            </para>
5597          </listitem>
5598        </varlistentry>
5599        <varlistentry>
5600          <term>Returns:</term>
5601          <listitem>
5602            <para>
5603              <code><phrase role="keyword">true</phrase></code> if ownership was
5604              obtained for the current fiber, <code><phrase role="keyword">false</phrase></code>
5605              otherwise.
5606            </para>
5607          </listitem>
5608        </varlistentry>
5609        <varlistentry>
5610          <term>Throws:</term>
5611          <listitem>
5612            <para>
5613              Nothing.
5614            </para>
5615          </listitem>
5616        </varlistentry>
5617      </variablelist>
5618      <para>
5619        <bridgehead renderas="sect4" id="recursive_timed_mutex_unlock_bridgehead">
5620  <phrase id="recursive_timed_mutex_unlock"/>
5621  <link linkend="recursive_timed_mutex_unlock">Member
5622        function <code>unlock</code>()</link>
5623</bridgehead>
5624      </para>
5625<programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">unlock</phrase><phrase role="special">();</phrase>
5626</programlisting>
5627      <variablelist>
5628        <title></title>
5629        <varlistentry>
5630          <term>Effects:</term>
5631          <listitem>
5632            <para>
5633              Releases a lock on <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>
5634              by the current fiber.
5635            </para>
5636          </listitem>
5637        </varlistentry>
5638        <varlistentry>
5639          <term>Throws:</term>
5640          <listitem>
5641            <para>
5642              <code><phrase role="identifier">lock_error</phrase></code>
5643            </para>
5644          </listitem>
5645        </varlistentry>
5646        <varlistentry>
5647          <term>Error Conditions:</term>
5648          <listitem>
5649            <para>
5650              <emphasis role="bold">operation_not_permitted</emphasis>: if <code><phrase
5651              role="identifier">boost</phrase><phrase role="special">::</phrase><phrase
5652              role="identifier">this_fiber</phrase><phrase role="special">::</phrase><phrase
5653              role="identifier">get_id</phrase><phrase role="special">()</phrase></code>
5654              does not own the mutex.
5655            </para>
5656          </listitem>
5657        </varlistentry>
5658      </variablelist>
5659      <para>
5660        <bridgehead renderas="sect4" id="recursive_timed_mutex_try_lock_until_bridgehead">
5661  <phrase id="recursive_timed_mutex_try_lock_until"/>
5662  <link linkend="recursive_timed_mutex_try_lock_until">Templated
5663        member function <code>try_lock_until</code>()</link>
5664</bridgehead>
5665      </para>
5666<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>
5667<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>
5668</programlisting>
5669      <variablelist>
5670        <title></title>
5671        <varlistentry>
5672          <term>Effects:</term>
5673          <listitem>
5674            <para>
5675              Attempt to obtain ownership for the current fiber. Blocks until ownership
5676              can be obtained, or the specified time is reached. If the specified
5677              time has already passed, behaves as <link linkend="recursive_timed_mutex_try_lock"><code>recursive_timed_mutex::try_lock()</code></link>.
5678            </para>
5679          </listitem>
5680        </varlistentry>
5681        <varlistentry>
5682          <term>Returns:</term>
5683          <listitem>
5684            <para>
5685              <code><phrase role="keyword">true</phrase></code> if ownership was
5686              obtained for the current fiber, <code><phrase role="keyword">false</phrase></code>
5687              otherwise.
5688            </para>
5689          </listitem>
5690        </varlistentry>
5691        <varlistentry>
5692          <term>Throws:</term>
5693          <listitem>
5694            <para>
5695              Timeout-related exceptions.
5696            </para>
5697          </listitem>
5698        </varlistentry>
5699      </variablelist>
5700      <para>
5701        <bridgehead renderas="sect4" id="recursive_timed_mutex_try_lock_for_bridgehead">
5702  <phrase id="recursive_timed_mutex_try_lock_for"/>
5703  <link linkend="recursive_timed_mutex_try_lock_for">Templated
5704        member function <code>try_lock_for</code>()</link>
5705</bridgehead>
5706      </para>
5707<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>
5708<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>
5709</programlisting>
5710      <variablelist>
5711        <title></title>
5712        <varlistentry>
5713          <term>Effects:</term>
5714          <listitem>
5715            <para>
5716              Attempt to obtain ownership for the current fiber. Blocks until ownership
5717              can be obtained, or the specified time is reached. If the specified
5718              time has already passed, behaves as <link linkend="recursive_timed_mutex_try_lock"><code>recursive_timed_mutex::try_lock()</code></link>.
5719            </para>
5720          </listitem>
5721        </varlistentry>
5722        <varlistentry>
5723          <term>Returns:</term>
5724          <listitem>
5725            <para>
5726              <code><phrase role="keyword">true</phrase></code> if ownership was
5727              obtained for the current fiber, <code><phrase role="keyword">false</phrase></code>
5728              otherwise.
5729            </para>
5730          </listitem>
5731        </varlistentry>
5732        <varlistentry>
5733          <term>Throws:</term>
5734          <listitem>
5735            <para>
5736              Timeout-related exceptions.
5737            </para>
5738          </listitem>
5739        </varlistentry>
5740      </variablelist>
5741    </section>
5742    <section id="fiber.synchronization.conditions">
5743      <title><link linkend="fiber.synchronization.conditions">Condition Variables</link></title>
5744      <bridgehead renderas="sect4" id="fiber.synchronization.conditions.h0">
5745        <phrase id="fiber.synchronization.conditions.synopsis"/><link linkend="fiber.synchronization.conditions.synopsis">Synopsis</link>
5746      </bridgehead>
5747<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>
5748    <phrase role="identifier">no_timeout</phrase><phrase role="special">,</phrase>
5749    <phrase role="identifier">timeout</phrase>
5750<phrase role="special">};</phrase>
5751
5752<phrase role="keyword">class</phrase> <phrase role="identifier">condition_variable</phrase><phrase role="special">;</phrase>
5753<phrase role="keyword">class</phrase> <phrase role="identifier">condition_variable_any</phrase><phrase role="special">;</phrase>
5754</programlisting>
5755      <para>
5756        The class <link linkend="class_condition_variable"><code>condition_variable</code></link> provides a mechanism
5757        for a fiber to wait for notification from another fiber. When the fiber awakens
5758        from the wait, then it checks to see if the appropriate condition is now
5759        true, and continues if so. If the condition is not true, then the fiber calls
5760        <code><phrase role="identifier">wait</phrase></code> again to resume waiting.
5761        In the simplest case, this condition is just a boolean variable:
5762      </para>
5763<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>
5764<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>
5765<phrase role="keyword">bool</phrase> <phrase role="identifier">data_ready</phrase> <phrase role="special">=</phrase> <phrase role="keyword">false</phrase><phrase role="special">;</phrase>
5766
5767<phrase role="keyword">void</phrase> <phrase role="identifier">process_data</phrase><phrase role="special">();</phrase>
5768
5769<phrase role="keyword">void</phrase> <phrase role="identifier">wait_for_data_to_process</phrase><phrase role="special">()</phrase> <phrase role="special">{</phrase>
5770    <phrase role="special">{</phrase>
5771        <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>
5772        <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>
5773            <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>
5774        <phrase role="special">}</phrase>
5775    <phrase role="special">}</phrase>   <phrase role="comment">// release lk</phrase>
5776    <phrase role="identifier">process_data</phrase><phrase role="special">();</phrase>
5777<phrase role="special">}</phrase>
5778</programlisting>
5779      <para>
5780        Notice that the <code><phrase role="identifier">lk</phrase></code> is passed
5781        to <link linkend="condition_variable_wait"><code>condition_variable::wait()</code></link>: <code><phrase role="identifier">wait</phrase><phrase
5782        role="special">()</phrase></code> will atomically add the fiber to the set
5783        of fibers waiting on the condition variable, and unlock the <link linkend="class_mutex"><code>mutex</code></link>.
5784        When the fiber is awakened, the <code><phrase role="identifier">mutex</phrase></code>
5785        will be locked again before the call to <code><phrase role="identifier">wait</phrase><phrase
5786        role="special">()</phrase></code> returns. This allows other fibers to acquire
5787        the <code><phrase role="identifier">mutex</phrase></code> in order to update
5788        the shared data, and ensures that the data associated with the condition
5789        is correctly synchronized.
5790      </para>
5791      <para>
5792        <code><phrase role="identifier">wait_for_data_to_process</phrase><phrase
5793        role="special">()</phrase></code> could equivalently be written:
5794      </para>
5795<programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">wait_for_data_to_process</phrase><phrase role="special">()</phrase> <phrase role="special">{</phrase>
5796    <phrase role="special">{</phrase>
5797        <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>
5798        <phrase role="comment">// make condition_variable::wait() perform the loop</phrase>
5799        <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>
5800    <phrase role="special">}</phrase>   <phrase role="comment">// release lk</phrase>
5801    <phrase role="identifier">process_data</phrase><phrase role="special">();</phrase>
5802<phrase role="special">}</phrase>
5803</programlisting>
5804      <para>
5805        In the meantime, another fiber sets <code><phrase role="identifier">data_ready</phrase></code>
5806        to <code><phrase role="keyword">true</phrase></code>, and then calls either
5807        <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
5808        the <link linkend="class_condition_variable"><code>condition_variable</code></link> <code><phrase role="identifier">cond</phrase></code>
5809        to wake one waiting fiber or all the waiting fibers respectively.
5810      </para>
5811<programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">retrieve_data</phrase><phrase role="special">();</phrase>
5812<phrase role="keyword">void</phrase> <phrase role="identifier">prepare_data</phrase><phrase role="special">();</phrase>
5813
5814<phrase role="keyword">void</phrase> <phrase role="identifier">prepare_data_for_processing</phrase><phrase role="special">()</phrase> <phrase role="special">{</phrase>
5815    <phrase role="identifier">retrieve_data</phrase><phrase role="special">();</phrase>
5816    <phrase role="identifier">prepare_data</phrase><phrase role="special">();</phrase>
5817    <phrase role="special">{</phrase>
5818        <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>
5819        <phrase role="identifier">data_ready</phrase> <phrase role="special">=</phrase> <phrase role="keyword">true</phrase><phrase role="special">;</phrase>
5820    <phrase role="special">}</phrase>
5821    <phrase role="identifier">cond</phrase><phrase role="special">.</phrase><phrase role="identifier">notify_one</phrase><phrase role="special">();</phrase>
5822<phrase role="special">}</phrase>
5823</programlisting>
5824      <para>
5825        Note that the same <link linkend="class_mutex"><code>mutex</code></link> is locked before the shared data is updated,
5826        but that the <code><phrase role="identifier">mutex</phrase></code> does not
5827        have to be locked across the call to <link linkend="condition_variable_notify_one"><code>condition_variable::notify_one()</code></link>.
5828      </para>
5829      <para>
5830        Locking is important because the synchronization objects provided by <emphasis
5831        role="bold">Boost.Fiber</emphasis> can be used to synchronize fibers running
5832        on different threads.
5833      </para>
5834      <para>
5835        <emphasis role="bold">Boost.Fiber</emphasis> provides both <link linkend="class_condition_variable"><code>condition_variable</code></link> and
5836        <link linkend="class_condition_variable_any"><code>condition_variable_any</code></link>. <code><phrase role="identifier">boost</phrase><phrase
5837        role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase
5838        role="special">::</phrase><phrase role="identifier">condition_variable</phrase></code>
5839        can only wait on <ulink url="http://en.cppreference.com/w/cpp/thread/unique_lock"><code><phrase
5840        role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">unique_lock</phrase></code></ulink><code><phrase
5841        role="special">&lt;</phrase> <phrase role="identifier">boost</phrase><phrase
5842        role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase
5843        role="special">::</phrase></code><link linkend="class_mutex"><code>mutex</code></link><code> <phrase role="special">&gt;</phrase></code>
5844        while <code><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase
5845        role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase
5846        role="identifier">condition_variable_any</phrase></code> can wait on user-defined
5847        lock types.
5848      </para>
5849      <anchor id="condition_variable_spurious_wakeups"/>
5850      <bridgehead renderas="sect4" id="fiber.synchronization.conditions.h1">
5851        <phrase id="fiber.synchronization.conditions.no_spurious_wakeups"/><link
5852        linkend="fiber.synchronization.conditions.no_spurious_wakeups">No Spurious
5853        Wakeups</link>
5854      </bridgehead>
5855      <para>
5856        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
5857        subject to spurious wakeup: <link linkend="condition_variable_wait"><code>condition_variable::wait()</code></link> can
5858        only wake up when <link linkend="condition_variable_notify_one"><code>condition_variable::notify_one()</code></link> or
5859        <link linkend="condition_variable_notify_all"><code>condition_variable::notify_all()</code></link> is called. Even
5860        so, it is prudent to use one of the <code><phrase role="identifier">wait</phrase><phrase
5861        role="special">(</phrase> <phrase role="identifier">lock</phrase><phrase
5862        role="special">,</phrase> <phrase role="identifier">predicate</phrase> <phrase
5863        role="special">)</phrase></code> overloads.
5864      </para>
5865      <para>
5866        Consider a set of consumer fibers processing items from a <ulink url="http://en.cppreference.com/w/cpp/container/queue"><code><phrase
5867        role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">queue</phrase></code></ulink>.
5868        The queue is continually populated by a set of producer fibers.
5869      </para>
5870      <para>
5871        The consumer fibers might reasonably wait on a <code><phrase role="identifier">condition_variable</phrase></code>
5872        as long as the queue remains <ulink url="http://en.cppreference.com/w/cpp/container/queue/empty"><code><phrase
5873        role="identifier">empty</phrase><phrase role="special">()</phrase></code></ulink>.
5874      </para>
5875      <para>
5876        Because producer fibers might <ulink url="http://en.cppreference.com/w/cpp/container/queue/push"><code><phrase
5877        role="identifier">push</phrase><phrase role="special">()</phrase></code></ulink>
5878        items to the queue in bursts, they call <link linkend="condition_variable_notify_all"><code>condition_variable::notify_all()</code></link> rather
5879        than <link linkend="condition_variable_notify_one"><code>condition_variable::notify_one()</code></link>.
5880      </para>
5881      <para>
5882        But a given consumer fiber might well wake up from <link linkend="condition_variable_wait"><code>condition_variable::wait()</code></link> and
5883        find the queue <code><phrase role="identifier">empty</phrase><phrase role="special">()</phrase></code>,
5884        because other consumer fibers might already have processed all pending items.
5885      </para>
5886      <para>
5887        (See also <link linkend="spurious_wakeup">spurious wakeup</link>.)
5888      </para>
5889      <anchor id="class_cv_status"/>
5890      <bridgehead renderas="sect4" id="fiber.synchronization.conditions.h2">
5891        <phrase id="fiber.synchronization.conditions.enumeration__code__phrase_role__identifier__cv_status__phrase___code_"/><link
5892        linkend="fiber.synchronization.conditions.enumeration__code__phrase_role__identifier__cv_status__phrase___code_">Enumeration
5893        <code><phrase role="identifier">cv_status</phrase></code></link>
5894      </bridgehead>
5895      <para>
5896        A timed wait operation might return because of timeout or not.
5897      </para>
5898<programlisting><phrase role="keyword">enum</phrase> <phrase role="keyword">class</phrase> <phrase role="identifier">cv_status</phrase> <phrase role="special">{</phrase>
5899    <phrase role="identifier">no_timeout</phrase><phrase role="special">,</phrase>
5900    <phrase role="identifier">timeout</phrase>
5901<phrase role="special">};</phrase>
5902</programlisting>
5903      <bridgehead renderas="sect4" id="fiber.synchronization.conditions.h3">
5904        <phrase id="fiber.synchronization.conditions._code__phrase_role__identifier__no_timeout__phrase___code_"/><link
5905        linkend="fiber.synchronization.conditions._code__phrase_role__identifier__no_timeout__phrase___code_"><code><phrase
5906        role="identifier">no_timeout</phrase></code></link>
5907      </bridgehead>
5908      <variablelist>
5909        <title></title>
5910        <varlistentry>
5911          <term>Effects:</term>
5912          <listitem>
5913            <para>
5914              The condition variable was awakened with <code><phrase role="identifier">notify_one</phrase></code>
5915              or <code><phrase role="identifier">notify_all</phrase></code>.
5916            </para>
5917          </listitem>
5918        </varlistentry>
5919      </variablelist>
5920      <bridgehead renderas="sect4" id="fiber.synchronization.conditions.h4">
5921        <phrase id="fiber.synchronization.conditions._code__phrase_role__identifier__timeout__phrase___code_"/><link
5922        linkend="fiber.synchronization.conditions._code__phrase_role__identifier__timeout__phrase___code_"><code><phrase
5923        role="identifier">timeout</phrase></code></link>
5924      </bridgehead>
5925      <variablelist>
5926        <title></title>
5927        <varlistentry>
5928          <term>Effects:</term>
5929          <listitem>
5930            <para>
5931              The condition variable was awakened by timeout.
5932            </para>
5933          </listitem>
5934        </varlistentry>
5935      </variablelist>
5936      <para>
5937        <bridgehead renderas="sect4" id="class_condition_variable_any_bridgehead">
5938  <phrase id="class_condition_variable_any"/>
5939  <link linkend="class_condition_variable_any">Class
5940        <code>condition_variable_any</code></link>
5941</bridgehead>
5942      </para>
5943<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>
5944
5945<phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase>
5946<phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase>
5947
5948<phrase role="keyword">class</phrase> condition_variable_any <phrase role="special">{</phrase>
5949<phrase role="keyword">public</phrase><phrase role="special">:</phrase>
5950    condition_variable_any<phrase role="special">();</phrase>
5951    <phrase role="special">~</phrase>condition_variable_any<phrase role="special">();</phrase>
5952
5953    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>
5954    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>
5955
5956    <phrase role="keyword">void</phrase> <phrase role="identifier">notify_one</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
5957    <phrase role="keyword">void</phrase> <phrase role="identifier">notify_all</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
5958
5959    template&lt; typename LockType &gt;
5960    void <phrase role="identifier">wait</phrase><phrase role="special">(</phrase> LockType <phrase role="special">&amp;);</phrase>
5961
5962    <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> typename LockType, typename <phrase role="identifier">Pred</phrase> <phrase role="special">&gt;</phrase>
5963    <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>
5964
5965    <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>
5966    <phrase role="identifier">cv_status</phrase> <phrase role="identifier">wait_until</phrase><phrase role="special">(</phrase> LockType <phrase role="special">&amp;,</phrase>
5967                          <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>
5968
5969    <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>
5970    <phrase role="keyword">bool</phrase> <phrase role="identifier">wait_until</phrase><phrase role="special">(</phrase> LockType <phrase role="special">&amp;,</phrase>
5971                     <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>
5972                     <phrase role="identifier">Pred</phrase><phrase role="special">);</phrase>
5973
5974    <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>
5975    <phrase role="identifier">cv_status</phrase> <phrase role="identifier">wait_for</phrase><phrase role="special">(</phrase> LockType <phrase role="special">&amp;,</phrase>
5976                        <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>
5977
5978    <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>
5979    <phrase role="keyword">bool</phrase> <phrase role="identifier">wait_for</phrase><phrase role="special">(</phrase> LockType <phrase role="special">&amp;,</phrase>
5980                   <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>
5981                   <phrase role="identifier">Pred</phrase><phrase role="special">);</phrase>
5982<phrase role="special">};</phrase>
5983
5984<phrase role="special">}}</phrase>
5985</programlisting>
5986      <bridgehead renderas="sect4" id="fiber.synchronization.conditions.h5">
5987        <phrase id="fiber.synchronization.conditions.constructor"/><link linkend="fiber.synchronization.conditions.constructor">Constructor</link>
5988      </bridgehead>
5989<programlisting>condition_variable_any<phrase role="special">()</phrase>
5990</programlisting>
5991      <variablelist>
5992        <title></title>
5993        <varlistentry>
5994          <term>Effects:</term>
5995          <listitem>
5996            <para>
5997              Creates the object.
5998            </para>
5999          </listitem>
6000        </varlistentry>
6001        <varlistentry>
6002          <term>Throws:</term>
6003          <listitem>
6004            <para>
6005              Nothing.
6006            </para>
6007          </listitem>
6008        </varlistentry>
6009      </variablelist>
6010      <bridgehead renderas="sect4" id="fiber.synchronization.conditions.h6">
6011        <phrase id="fiber.synchronization.conditions.destructor"/><link linkend="fiber.synchronization.conditions.destructor">Destructor</link>
6012      </bridgehead>
6013<programlisting><phrase role="special">~</phrase>condition_variable_any<phrase role="special">()</phrase>
6014</programlisting>
6015      <variablelist>
6016        <title></title>
6017        <varlistentry>
6018          <term>Precondition:</term>
6019          <listitem>
6020            <para>
6021              All fibers waiting on <code><phrase role="special">*</phrase><phrase
6022              role="keyword">this</phrase></code> have been notified by a call to
6023              <code><phrase role="identifier">notify_one</phrase></code> or <code><phrase
6024              role="identifier">notify_all</phrase></code> (though the respective
6025              calls to <code><phrase role="identifier">wait</phrase></code>, <code><phrase
6026              role="identifier">wait_for</phrase></code> or <code><phrase role="identifier">wait_until</phrase></code>
6027              need not have returned).
6028            </para>
6029          </listitem>
6030        </varlistentry>
6031        <varlistentry>
6032          <term>Effects:</term>
6033          <listitem>
6034            <para>
6035              Destroys the object.
6036            </para>
6037          </listitem>
6038        </varlistentry>
6039      </variablelist>
6040      <para>
6041        <bridgehead renderas="sect4" id="condition_variable_any_notify_one_bridgehead">
6042  <phrase id="condition_variable_any_notify_one"/>
6043  <link linkend="condition_variable_any_notify_one">Member
6044        function <code>notify_one</code>()</link>
6045</bridgehead>
6046      </para>
6047<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>
6048</programlisting>
6049      <variablelist>
6050        <title></title>
6051        <varlistentry>
6052          <term>Effects:</term>
6053          <listitem>
6054            <para>
6055              If any fibers are currently <link linkend="blocking"><emphasis>blocked</emphasis></link>
6056              waiting on <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>
6057              in a call to <code><phrase role="identifier">wait</phrase></code>,
6058              <code><phrase role="identifier">wait_for</phrase></code> or <code><phrase
6059              role="identifier">wait_until</phrase></code>, unblocks one of those
6060              fibers.
6061            </para>
6062          </listitem>
6063        </varlistentry>
6064        <varlistentry>
6065          <term>Throws:</term>
6066          <listitem>
6067            <para>
6068              Nothing.
6069            </para>
6070          </listitem>
6071        </varlistentry>
6072        <varlistentry>
6073          <term>Note:</term>
6074          <listitem>
6075            <para>
6076              It is arbitrary which waiting fiber is resumed.
6077            </para>
6078          </listitem>
6079        </varlistentry>
6080      </variablelist>
6081      <para>
6082        <bridgehead renderas="sect4" id="condition_variable_any_notify_all_bridgehead">
6083  <phrase id="condition_variable_any_notify_all"/>
6084  <link linkend="condition_variable_any_notify_all">Member
6085        function <code>notify_all</code>()</link>
6086</bridgehead>
6087      </para>
6088<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>
6089</programlisting>
6090      <variablelist>
6091        <title></title>
6092        <varlistentry>
6093          <term>Effects:</term>
6094          <listitem>
6095            <para>
6096              If any fibers are currently <link linkend="blocking"><emphasis>blocked</emphasis></link>
6097              waiting on <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>
6098              in a call to <code><phrase role="identifier">wait</phrase></code>,
6099              <code><phrase role="identifier">wait_for</phrase></code> or <code><phrase
6100              role="identifier">wait_until</phrase></code>, unblocks all of those
6101              fibers.
6102            </para>
6103          </listitem>
6104        </varlistentry>
6105        <varlistentry>
6106          <term>Throws:</term>
6107          <listitem>
6108            <para>
6109              Nothing.
6110            </para>
6111          </listitem>
6112        </varlistentry>
6113        <varlistentry>
6114          <term>Note:</term>
6115          <listitem>
6116            <para>
6117              This is why a waiting fiber must <emphasis>also</emphasis> check for
6118              the desired program state using a mechanism external to the <code>condition_variable_any</code>,
6119              and retry the wait until that state is reached. A fiber waiting on
6120              a <code>condition_variable_any</code> might well wake up a number of times before
6121              the desired state is reached.
6122            </para>
6123          </listitem>
6124        </varlistentry>
6125      </variablelist>
6126      <para>
6127        <bridgehead renderas="sect4" id="condition_variable_any_wait_bridgehead">
6128  <phrase id="condition_variable_any_wait"/>
6129  <link linkend="condition_variable_any_wait">Templated
6130        member function <code>wait</code>()</link>
6131</bridgehead>
6132      </para>
6133<programlisting>template&lt; typename LockType &gt;
6134    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>
6135
6136<phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> typename LockType, typename <phrase role="identifier">Pred</phrase> <phrase role="special">&gt;</phrase>
6137<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>
6138</programlisting>
6139      <variablelist>
6140        <title></title>
6141        <varlistentry>
6142          <term>Precondition:</term>
6143          <listitem>
6144            <para>
6145              <code><phrase role="identifier">lk</phrase></code> is locked by the
6146              current fiber, and either no other fiber is currently waiting on <code><phrase
6147              role="special">*</phrase><phrase role="keyword">this</phrase></code>,
6148              or the execution of the <ulink url="http://en.cppreference.com/w/cpp/thread/unique_lock/mutex"><code><phrase
6149              role="identifier">mutex</phrase><phrase role="special">()</phrase></code></ulink>
6150              member function on the <code><phrase role="identifier">lk</phrase></code>
6151              objects supplied in the calls to <code><phrase role="identifier">wait</phrase></code>
6152              in all the fibers currently waiting on <code><phrase role="special">*</phrase><phrase
6153              role="keyword">this</phrase></code> would return the same value as
6154              <code><phrase role="identifier">lk</phrase><phrase role="special">-&gt;</phrase><phrase
6155              role="identifier">mutex</phrase><phrase role="special">()</phrase></code>
6156              for this call to <code><phrase role="identifier">wait</phrase></code>.
6157            </para>
6158          </listitem>
6159        </varlistentry>
6160        <varlistentry>
6161          <term>Effects:</term>
6162          <listitem>
6163            <para>
6164              Atomically call <code><phrase role="identifier">lk</phrase><phrase
6165              role="special">.</phrase><phrase role="identifier">unlock</phrase><phrase
6166              role="special">()</phrase></code> and blocks the current fiber. The
6167              fiber will unblock when notified by a call to <code><phrase role="keyword">this</phrase><phrase
6168              role="special">-&gt;</phrase><phrase role="identifier">notify_one</phrase><phrase
6169              role="special">()</phrase></code> or <code><phrase role="keyword">this</phrase><phrase
6170              role="special">-&gt;</phrase><phrase role="identifier">notify_all</phrase><phrase
6171              role="special">()</phrase></code>. When the fiber is unblocked (for
6172              whatever reason), the lock is reacquired by invoking <code><phrase
6173              role="identifier">lk</phrase><phrase role="special">.</phrase><phrase
6174              role="identifier">lock</phrase><phrase role="special">()</phrase></code>
6175              before the call to <code><phrase role="identifier">wait</phrase></code>
6176              returns. The lock is also reacquired by invoking <code><phrase role="identifier">lk</phrase><phrase
6177              role="special">.</phrase><phrase role="identifier">lock</phrase><phrase
6178              role="special">()</phrase></code> if the function exits with an exception.
6179              The member function accepting <code><phrase role="identifier">pred</phrase></code>
6180              is shorthand for:
6181<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>
6182    <phrase role="identifier">wait</phrase><phrase role="special">(</phrase> <phrase role="identifier">lk</phrase><phrase role="special">);</phrase>
6183<phrase role="special">}</phrase>
6184</programlisting>
6185            </para>
6186          </listitem>
6187        </varlistentry>
6188        <varlistentry>
6189          <term>Postcondition:</term>
6190          <listitem>
6191            <para>
6192              <code><phrase role="identifier">lk</phrase></code> is locked by the
6193              current fiber.
6194            </para>
6195          </listitem>
6196        </varlistentry>
6197        <varlistentry>
6198          <term>Throws:</term>
6199          <listitem>
6200            <para>
6201              <code><phrase role="identifier">fiber_error</phrase></code> if an error
6202              occurs.
6203            </para>
6204          </listitem>
6205        </varlistentry>
6206        <varlistentry>
6207          <term>Note:</term>
6208          <listitem>
6209            <para>
6210              The Precondition is a bit dense. It merely states that all the fibers
6211              concurrently calling <code><phrase role="identifier">wait</phrase></code>
6212              on <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>
6213              must wait on <code><phrase role="identifier">lk</phrase></code> objects
6214              governing the <emphasis>same</emphasis> <link linkend="class_mutex"><code>mutex</code></link>. Three distinct
6215              objects are involved in any <code>condition_variable_any::wait()</code> call: the
6216              <code>condition_variable_any</code> itself, the <code><phrase role="identifier">mutex</phrase></code>
6217              coordinating access between fibers and a local lock object (e.g. <ulink
6218              url="http://en.cppreference.com/w/cpp/thread/unique_lock"><code><phrase
6219              role="identifier">std</phrase><phrase role="special">::</phrase><phrase
6220              role="identifier">unique_lock</phrase></code></ulink>). In general,
6221              you can partition the lifespan of a given <code>condition_variable_any</code> instance
6222              into periods with one or more fibers waiting on it, separated by periods
6223              when no fibers are waiting on it. When more than one fiber is waiting
6224              on that <code>condition_variable_any</code>, all must pass lock objects referencing
6225              the <emphasis>same</emphasis> <code><phrase role="identifier">mutex</phrase></code>
6226              instance.
6227            </para>
6228          </listitem>
6229        </varlistentry>
6230      </variablelist>
6231      <para>
6232        <bridgehead renderas="sect4" id="condition_variable_any_wait_until_bridgehead">
6233  <phrase id="condition_variable_any_wait_until"/>
6234  <link linkend="condition_variable_any_wait_until">Templated
6235        member function <code>wait_until</code>()</link>
6236</bridgehead>
6237      </para>
6238<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>
6239<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>
6240                      <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>
6241
6242<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>
6243<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>
6244                 <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>
6245                 <phrase role="identifier">Pred</phrase> <phrase role="identifier">pred</phrase><phrase role="special">);</phrase>
6246</programlisting>
6247      <variablelist>
6248        <title></title>
6249        <varlistentry>
6250          <term>Precondition:</term>
6251          <listitem>
6252            <para>
6253              <code><phrase role="identifier">lk</phrase></code> is locked by the
6254              current fiber, and either no other fiber is currently waiting on <code><phrase
6255              role="special">*</phrase><phrase role="keyword">this</phrase></code>,
6256              or the execution of the <code><phrase role="identifier">mutex</phrase><phrase
6257              role="special">()</phrase></code> member function on the <code><phrase
6258              role="identifier">lk</phrase></code> objects supplied in the calls
6259              to <code><phrase role="identifier">wait</phrase></code>, <code><phrase
6260              role="identifier">wait_for</phrase></code> or <code><phrase role="identifier">wait_until</phrase></code>
6261              in all the fibers currently waiting on <code><phrase role="special">*</phrase><phrase
6262              role="keyword">this</phrase></code> would return the same value as
6263              <code><phrase role="identifier">lk</phrase><phrase role="special">.</phrase><phrase
6264              role="identifier">mutex</phrase><phrase role="special">()</phrase></code>
6265              for this call to <code><phrase role="identifier">wait_until</phrase></code>.
6266            </para>
6267          </listitem>
6268        </varlistentry>
6269        <varlistentry>
6270          <term>Effects:</term>
6271          <listitem>
6272            <para>
6273              Atomically call <code><phrase role="identifier">lk</phrase><phrase
6274              role="special">.</phrase><phrase role="identifier">unlock</phrase><phrase
6275              role="special">()</phrase></code> and blocks the current fiber. The
6276              fiber will unblock when notified by a call to <code><phrase role="keyword">this</phrase><phrase
6277              role="special">-&gt;</phrase><phrase role="identifier">notify_one</phrase><phrase
6278              role="special">()</phrase></code> or <code><phrase role="keyword">this</phrase><phrase
6279              role="special">-&gt;</phrase><phrase role="identifier">notify_all</phrase><phrase
6280              role="special">()</phrase></code>, when the system time would be equal
6281              to or later than the specified <code><phrase role="identifier">abs_time</phrase></code>.
6282              When the fiber is unblocked (for whatever reason), the lock is reacquired
6283              by invoking <code><phrase role="identifier">lk</phrase><phrase role="special">.</phrase><phrase
6284              role="identifier">lock</phrase><phrase role="special">()</phrase></code>
6285              before the call to <code><phrase role="identifier">wait_until</phrase></code>
6286              returns. The lock is also reacquired by invoking <code><phrase role="identifier">lk</phrase><phrase
6287              role="special">.</phrase><phrase role="identifier">lock</phrase><phrase
6288              role="special">()</phrase></code> if the function exits with an exception.
6289              The member function accepting <code><phrase role="identifier">pred</phrase></code>
6290              is shorthand for:
6291<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>
6292    <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>
6293        <phrase role="keyword">return</phrase> <phrase role="identifier">pred</phrase><phrase role="special">();</phrase>
6294<phrase role="special">}</phrase>
6295<phrase role="keyword">return</phrase> <phrase role="keyword">true</phrase><phrase role="special">;</phrase>
6296</programlisting>
6297              That is, even if <code><phrase role="identifier">wait_until</phrase><phrase
6298              role="special">()</phrase></code> times out, it can still return <code><phrase
6299              role="keyword">true</phrase></code> if <code><phrase role="identifier">pred</phrase><phrase
6300              role="special">()</phrase></code> returns <code><phrase role="keyword">true</phrase></code>
6301              at that time.
6302            </para>
6303          </listitem>
6304        </varlistentry>
6305        <varlistentry>
6306          <term>Postcondition:</term>
6307          <listitem>
6308            <para>
6309              <code><phrase role="identifier">lk</phrase></code> is locked by the
6310              current fiber.
6311            </para>
6312          </listitem>
6313        </varlistentry>
6314        <varlistentry>
6315          <term>Throws:</term>
6316          <listitem>
6317            <para>
6318              <code><phrase role="identifier">fiber_error</phrase></code> if an error
6319              occurs or timeout-related exceptions.
6320            </para>
6321          </listitem>
6322        </varlistentry>
6323        <varlistentry>
6324          <term>Returns:</term>
6325          <listitem>
6326            <para>
6327              The overload without <code><phrase role="identifier">pred</phrase></code>
6328              returns <code><phrase role="identifier">cv_status</phrase><phrase role="special">::</phrase><phrase
6329              role="identifier">no_timeout</phrase></code> if awakened by <code><phrase
6330              role="identifier">notify_one</phrase><phrase role="special">()</phrase></code>
6331              or <code><phrase role="identifier">notify_all</phrase><phrase role="special">()</phrase></code>,
6332              or <code><phrase role="identifier">cv_status</phrase><phrase role="special">::</phrase><phrase
6333              role="identifier">timeout</phrase></code> if awakened because the system
6334              time is past <code><phrase role="identifier">abs_time</phrase></code>.
6335            </para>
6336          </listitem>
6337        </varlistentry>
6338        <varlistentry>
6339          <term>Returns:</term>
6340          <listitem>
6341            <para>
6342              The overload accepting <code><phrase role="identifier">pred</phrase></code>
6343              returns <code><phrase role="keyword">false</phrase></code> if the call
6344              is returning because the time specified by <code><phrase role="identifier">abs_time</phrase></code>
6345              was reached and the predicate returns <code><phrase role="keyword">false</phrase></code>,
6346              <code><phrase role="keyword">true</phrase></code> otherwise.
6347            </para>
6348          </listitem>
6349        </varlistentry>
6350        <varlistentry>
6351          <term>Note:</term>
6352          <listitem>
6353            <para>
6354              See <emphasis role="bold">Note</emphasis> for <link linkend="condition_variable_any_wait"><code>condition_variable_any::wait()</code></link>.
6355            </para>
6356          </listitem>
6357        </varlistentry>
6358      </variablelist>
6359      <para>
6360        <bridgehead renderas="sect4" id="condition_variable_any_wait_for_bridgehead">
6361  <phrase id="condition_variable_any_wait_for"/>
6362  <link linkend="condition_variable_any_wait_for">Templated
6363        member function <code>wait_for</code>()</link>
6364</bridgehead>
6365      </para>
6366<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>
6367<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>
6368                    <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>
6369
6370<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>
6371<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>
6372               <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>
6373               <phrase role="identifier">Pred</phrase> <phrase role="identifier">pred</phrase><phrase role="special">);</phrase>
6374</programlisting>
6375      <variablelist>
6376        <title></title>
6377        <varlistentry>
6378          <term>Precondition:</term>
6379          <listitem>
6380            <para>
6381              <code><phrase role="identifier">lk</phrase></code> is locked by the
6382              current fiber, and either no other fiber is currently waiting on <code><phrase
6383              role="special">*</phrase><phrase role="keyword">this</phrase></code>,
6384              or the execution of the <code><phrase role="identifier">mutex</phrase><phrase
6385              role="special">()</phrase></code> member function on the <code><phrase
6386              role="identifier">lk</phrase></code> objects supplied in the calls
6387              to <code><phrase role="identifier">wait</phrase></code>, <code><phrase
6388              role="identifier">wait_for</phrase></code> or <code><phrase role="identifier">wait_until</phrase></code>
6389              in all the fibers currently waiting on <code><phrase role="special">*</phrase><phrase
6390              role="keyword">this</phrase></code> would return the same value as
6391              <code><phrase role="identifier">lk</phrase><phrase role="special">.</phrase><phrase
6392              role="identifier">mutex</phrase><phrase role="special">()</phrase></code>
6393              for this call to <code><phrase role="identifier">wait_for</phrase></code>.
6394            </para>
6395          </listitem>
6396        </varlistentry>
6397        <varlistentry>
6398          <term>Effects:</term>
6399          <listitem>
6400            <para>
6401              Atomically call <code><phrase role="identifier">lk</phrase><phrase
6402              role="special">.</phrase><phrase role="identifier">unlock</phrase><phrase
6403              role="special">()</phrase></code> and blocks the current fiber. The
6404              fiber will unblock when notified by a call to <code><phrase role="keyword">this</phrase><phrase
6405              role="special">-&gt;</phrase><phrase role="identifier">notify_one</phrase><phrase
6406              role="special">()</phrase></code> or <code><phrase role="keyword">this</phrase><phrase
6407              role="special">-&gt;</phrase><phrase role="identifier">notify_all</phrase><phrase
6408              role="special">()</phrase></code>, when a time interval equal to or
6409              greater than the specified <code><phrase role="identifier">rel_time</phrase></code>
6410              has elapsed. When the fiber is unblocked (for whatever reason), the
6411              lock is reacquired by invoking <code><phrase role="identifier">lk</phrase><phrase
6412              role="special">.</phrase><phrase role="identifier">lock</phrase><phrase
6413              role="special">()</phrase></code> before the call to <code><phrase
6414              role="identifier">wait</phrase></code> returns. The lock is also reacquired
6415              by invoking <code><phrase role="identifier">lk</phrase><phrase role="special">.</phrase><phrase
6416              role="identifier">lock</phrase><phrase role="special">()</phrase></code>
6417              if the function exits with an exception. The <code><phrase role="identifier">wait_for</phrase><phrase
6418              role="special">()</phrase></code> member function accepting <code><phrase
6419              role="identifier">pred</phrase></code> is shorthand for:
6420<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>
6421    <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>
6422        <phrase role="keyword">return</phrase> <phrase role="identifier">pred</phrase><phrase role="special">();</phrase>
6423    <phrase role="special">}</phrase>
6424<phrase role="special">}</phrase>
6425<phrase role="keyword">return</phrase> <phrase role="keyword">true</phrase><phrase role="special">;</phrase>
6426</programlisting>
6427              (except of course that <code><phrase role="identifier">rel_time</phrase></code>
6428              is adjusted for each iteration). The point is that, even if <code><phrase
6429              role="identifier">wait_for</phrase><phrase role="special">()</phrase></code>
6430              times out, it can still return <code><phrase role="keyword">true</phrase></code>
6431              if <code><phrase role="identifier">pred</phrase><phrase role="special">()</phrase></code>
6432              returns <code><phrase role="keyword">true</phrase></code> at that time.
6433            </para>
6434          </listitem>
6435        </varlistentry>
6436        <varlistentry>
6437          <term>Postcondition:</term>
6438          <listitem>
6439            <para>
6440              <code><phrase role="identifier">lk</phrase></code> is locked by the
6441              current fiber.
6442            </para>
6443          </listitem>
6444        </varlistentry>
6445        <varlistentry>
6446          <term>Throws:</term>
6447          <listitem>
6448            <para>
6449              <code><phrase role="identifier">fiber_error</phrase></code> if an error
6450              occurs or timeout-related exceptions.
6451            </para>
6452          </listitem>
6453        </varlistentry>
6454        <varlistentry>
6455          <term>Returns:</term>
6456          <listitem>
6457            <para>
6458              The overload without <code><phrase role="identifier">pred</phrase></code>
6459              returns <code><phrase role="identifier">cv_status</phrase><phrase role="special">::</phrase><phrase
6460              role="identifier">no_timeout</phrase></code> if awakened by <code><phrase
6461              role="identifier">notify_one</phrase><phrase role="special">()</phrase></code>
6462              or <code><phrase role="identifier">notify_all</phrase><phrase role="special">()</phrase></code>,
6463              or <code><phrase role="identifier">cv_status</phrase><phrase role="special">::</phrase><phrase
6464              role="identifier">timeout</phrase></code> if awakened because at least
6465              <code><phrase role="identifier">rel_time</phrase></code> has elapsed.
6466            </para>
6467          </listitem>
6468        </varlistentry>
6469        <varlistentry>
6470          <term>Returns:</term>
6471          <listitem>
6472            <para>
6473              The overload accepting <code><phrase role="identifier">pred</phrase></code>
6474              returns <code><phrase role="keyword">false</phrase></code> if the call
6475              is returning because at least <code><phrase role="identifier">rel_time</phrase></code>
6476              has elapsed and the predicate returns <code><phrase role="keyword">false</phrase></code>,
6477              <code><phrase role="keyword">true</phrase></code> otherwise.
6478            </para>
6479          </listitem>
6480        </varlistentry>
6481        <varlistentry>
6482          <term>Note:</term>
6483          <listitem>
6484            <para>
6485              See <emphasis role="bold">Note</emphasis> for <link linkend="condition_variable_any_wait"><code>condition_variable_any::wait()</code></link>.
6486            </para>
6487          </listitem>
6488        </varlistentry>
6489      </variablelist>
6490      <para>
6491        <bridgehead renderas="sect4" id="class_condition_variable_bridgehead">
6492  <phrase id="class_condition_variable"/>
6493  <link linkend="class_condition_variable">Class
6494        <code>condition_variable</code></link>
6495</bridgehead>
6496      </para>
6497<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>
6498
6499<phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase>
6500<phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase>
6501
6502<phrase role="keyword">class</phrase> condition_variable <phrase role="special">{</phrase>
6503<phrase role="keyword">public</phrase><phrase role="special">:</phrase>
6504    condition_variable<phrase role="special">();</phrase>
6505    <phrase role="special">~</phrase>condition_variable<phrase role="special">();</phrase>
6506
6507    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>
6508    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>
6509
6510    <phrase role="keyword">void</phrase> <phrase role="identifier">notify_one</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
6511    <phrase role="keyword">void</phrase> <phrase role="identifier">notify_all</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
6512
6513    void <phrase role="identifier">wait</phrase><phrase role="special">(</phrase> std::unique_lock&lt; mutex &gt; <phrase role="special">&amp;);</phrase>
6514
6515    <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> typename <phrase role="identifier">Pred</phrase> <phrase role="special">&gt;</phrase>
6516    <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>
6517
6518    <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>
6519    <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>
6520                          <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>
6521
6522    <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>
6523    <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>
6524                     <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>
6525                     <phrase role="identifier">Pred</phrase><phrase role="special">);</phrase>
6526
6527    <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>
6528    <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>
6529                        <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>
6530
6531    <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>
6532    <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>
6533                   <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>
6534                   <phrase role="identifier">Pred</phrase><phrase role="special">);</phrase>
6535<phrase role="special">};</phrase>
6536
6537<phrase role="special">}}</phrase>
6538</programlisting>
6539      <bridgehead renderas="sect4" id="fiber.synchronization.conditions.h7">
6540        <phrase id="fiber.synchronization.conditions.constructor0"/><link linkend="fiber.synchronization.conditions.constructor0">Constructor</link>
6541      </bridgehead>
6542<programlisting>condition_variable<phrase role="special">()</phrase>
6543</programlisting>
6544      <variablelist>
6545        <title></title>
6546        <varlistentry>
6547          <term>Effects:</term>
6548          <listitem>
6549            <para>
6550              Creates the object.
6551            </para>
6552          </listitem>
6553        </varlistentry>
6554        <varlistentry>
6555          <term>Throws:</term>
6556          <listitem>
6557            <para>
6558              Nothing.
6559            </para>
6560          </listitem>
6561        </varlistentry>
6562      </variablelist>
6563      <bridgehead renderas="sect4" id="fiber.synchronization.conditions.h8">
6564        <phrase id="fiber.synchronization.conditions.destructor0"/><link linkend="fiber.synchronization.conditions.destructor0">Destructor</link>
6565      </bridgehead>
6566<programlisting><phrase role="special">~</phrase>condition_variable<phrase role="special">()</phrase>
6567</programlisting>
6568      <variablelist>
6569        <title></title>
6570        <varlistentry>
6571          <term>Precondition:</term>
6572          <listitem>
6573            <para>
6574              All fibers waiting on <code><phrase role="special">*</phrase><phrase
6575              role="keyword">this</phrase></code> have been notified by a call to
6576              <code><phrase role="identifier">notify_one</phrase></code> or <code><phrase
6577              role="identifier">notify_all</phrase></code> (though the respective
6578              calls to <code><phrase role="identifier">wait</phrase></code>, <code><phrase
6579              role="identifier">wait_for</phrase></code> or <code><phrase role="identifier">wait_until</phrase></code>
6580              need not have returned).
6581            </para>
6582          </listitem>
6583        </varlistentry>
6584        <varlistentry>
6585          <term>Effects:</term>
6586          <listitem>
6587            <para>
6588              Destroys the object.
6589            </para>
6590          </listitem>
6591        </varlistentry>
6592      </variablelist>
6593      <para>
6594        <bridgehead renderas="sect4" id="condition_variable_notify_one_bridgehead">
6595  <phrase id="condition_variable_notify_one"/>
6596  <link linkend="condition_variable_notify_one">Member
6597        function <code>notify_one</code>()</link>
6598</bridgehead>
6599      </para>
6600<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>
6601</programlisting>
6602      <variablelist>
6603        <title></title>
6604        <varlistentry>
6605          <term>Effects:</term>
6606          <listitem>
6607            <para>
6608              If any fibers are currently <link linkend="blocking"><emphasis>blocked</emphasis></link>
6609              waiting on <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>
6610              in a call to <code><phrase role="identifier">wait</phrase></code>,
6611              <code><phrase role="identifier">wait_for</phrase></code> or <code><phrase
6612              role="identifier">wait_until</phrase></code>, unblocks one of those
6613              fibers.
6614            </para>
6615          </listitem>
6616        </varlistentry>
6617        <varlistentry>
6618          <term>Throws:</term>
6619          <listitem>
6620            <para>
6621              Nothing.
6622            </para>
6623          </listitem>
6624        </varlistentry>
6625        <varlistentry>
6626          <term>Note:</term>
6627          <listitem>
6628            <para>
6629              It is arbitrary which waiting fiber is resumed.
6630            </para>
6631          </listitem>
6632        </varlistentry>
6633      </variablelist>
6634      <para>
6635        <bridgehead renderas="sect4" id="condition_variable_notify_all_bridgehead">
6636  <phrase id="condition_variable_notify_all"/>
6637  <link linkend="condition_variable_notify_all">Member
6638        function <code>notify_all</code>()</link>
6639</bridgehead>
6640      </para>
6641<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>
6642</programlisting>
6643      <variablelist>
6644        <title></title>
6645        <varlistentry>
6646          <term>Effects:</term>
6647          <listitem>
6648            <para>
6649              If any fibers are currently <link linkend="blocking"><emphasis>blocked</emphasis></link>
6650              waiting on <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>
6651              in a call to <code><phrase role="identifier">wait</phrase></code>,
6652              <code><phrase role="identifier">wait_for</phrase></code> or <code><phrase
6653              role="identifier">wait_until</phrase></code>, unblocks all of those
6654              fibers.
6655            </para>
6656          </listitem>
6657        </varlistentry>
6658        <varlistentry>
6659          <term>Throws:</term>
6660          <listitem>
6661            <para>
6662              Nothing.
6663            </para>
6664          </listitem>
6665        </varlistentry>
6666        <varlistentry>
6667          <term>Note:</term>
6668          <listitem>
6669            <para>
6670              This is why a waiting fiber must <emphasis>also</emphasis> check for
6671              the desired program state using a mechanism external to the <code>condition_variable</code>,
6672              and retry the wait until that state is reached. A fiber waiting on
6673              a <code>condition_variable</code> might well wake up a number of times before the
6674              desired state is reached.
6675            </para>
6676          </listitem>
6677        </varlistentry>
6678      </variablelist>
6679      <para>
6680        <bridgehead renderas="sect4" id="condition_variable_wait_bridgehead">
6681  <phrase id="condition_variable_wait"/>
6682  <link linkend="condition_variable_wait">Templated
6683        member function <code>wait</code>()</link>
6684</bridgehead>
6685      </para>
6686<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>
6687
6688<phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> typename <phrase role="identifier">Pred</phrase> <phrase role="special">&gt;</phrase>
6689<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>
6690</programlisting>
6691      <variablelist>
6692        <title></title>
6693        <varlistentry>
6694          <term>Precondition:</term>
6695          <listitem>
6696            <para>
6697              <code><phrase role="identifier">lk</phrase></code> is locked by the
6698              current fiber, and either no other fiber is currently waiting on <code><phrase
6699              role="special">*</phrase><phrase role="keyword">this</phrase></code>,
6700              or the execution of the <ulink url="http://en.cppreference.com/w/cpp/thread/unique_lock/mutex"><code><phrase
6701              role="identifier">mutex</phrase><phrase role="special">()</phrase></code></ulink>
6702              member function on the <code><phrase role="identifier">lk</phrase></code>
6703              objects supplied in the calls to <code><phrase role="identifier">wait</phrase></code>
6704              in all the fibers currently waiting on <code><phrase role="special">*</phrase><phrase
6705              role="keyword">this</phrase></code> would return the same value as
6706              <code><phrase role="identifier">lk</phrase><phrase role="special">-&gt;</phrase><phrase
6707              role="identifier">mutex</phrase><phrase role="special">()</phrase></code>
6708              for this call to <code><phrase role="identifier">wait</phrase></code>.
6709            </para>
6710          </listitem>
6711        </varlistentry>
6712        <varlistentry>
6713          <term>Effects:</term>
6714          <listitem>
6715            <para>
6716              Atomically call <code><phrase role="identifier">lk</phrase><phrase
6717              role="special">.</phrase><phrase role="identifier">unlock</phrase><phrase
6718              role="special">()</phrase></code> and blocks the current fiber. The
6719              fiber will unblock when notified by a call to <code><phrase role="keyword">this</phrase><phrase
6720              role="special">-&gt;</phrase><phrase role="identifier">notify_one</phrase><phrase
6721              role="special">()</phrase></code> or <code><phrase role="keyword">this</phrase><phrase
6722              role="special">-&gt;</phrase><phrase role="identifier">notify_all</phrase><phrase
6723              role="special">()</phrase></code>. When the fiber is unblocked (for
6724              whatever reason), the lock is reacquired by invoking <code><phrase
6725              role="identifier">lk</phrase><phrase role="special">.</phrase><phrase
6726              role="identifier">lock</phrase><phrase role="special">()</phrase></code>
6727              before the call to <code><phrase role="identifier">wait</phrase></code>
6728              returns. The lock is also reacquired by invoking <code><phrase role="identifier">lk</phrase><phrase
6729              role="special">.</phrase><phrase role="identifier">lock</phrase><phrase
6730              role="special">()</phrase></code> if the function exits with an exception.
6731              The member function accepting <code><phrase role="identifier">pred</phrase></code>
6732              is shorthand for:
6733<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>
6734    <phrase role="identifier">wait</phrase><phrase role="special">(</phrase> <phrase role="identifier">lk</phrase><phrase role="special">);</phrase>
6735<phrase role="special">}</phrase>
6736</programlisting>
6737            </para>
6738          </listitem>
6739        </varlistentry>
6740        <varlistentry>
6741          <term>Postcondition:</term>
6742          <listitem>
6743            <para>
6744              <code><phrase role="identifier">lk</phrase></code> is locked by the
6745              current fiber.
6746            </para>
6747          </listitem>
6748        </varlistentry>
6749        <varlistentry>
6750          <term>Throws:</term>
6751          <listitem>
6752            <para>
6753              <code><phrase role="identifier">fiber_error</phrase></code> if an error
6754              occurs.
6755            </para>
6756          </listitem>
6757        </varlistentry>
6758        <varlistentry>
6759          <term>Note:</term>
6760          <listitem>
6761            <para>
6762              The Precondition is a bit dense. It merely states that all the fibers
6763              concurrently calling <code><phrase role="identifier">wait</phrase></code>
6764              on <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>
6765              must wait on <code><phrase role="identifier">lk</phrase></code> objects
6766              governing the <emphasis>same</emphasis> <link linkend="class_mutex"><code>mutex</code></link>. Three distinct
6767              objects are involved in any <code>condition_variable::wait()</code> call: the <code>condition_variable</code> itself,
6768              the <code><phrase role="identifier">mutex</phrase></code> coordinating
6769              access between fibers and a local lock object (e.g. <ulink url="http://en.cppreference.com/w/cpp/thread/unique_lock"><code><phrase
6770              role="identifier">std</phrase><phrase role="special">::</phrase><phrase
6771              role="identifier">unique_lock</phrase></code></ulink>). In general,
6772              you can partition the lifespan of a given <code>condition_variable</code> instance
6773              into periods with one or more fibers waiting on it, separated by periods
6774              when no fibers are waiting on it. When more than one fiber is waiting
6775              on that <code>condition_variable</code>, all must pass lock objects referencing
6776              the <emphasis>same</emphasis> <code><phrase role="identifier">mutex</phrase></code>
6777              instance.
6778            </para>
6779          </listitem>
6780        </varlistentry>
6781      </variablelist>
6782      <para>
6783        <bridgehead renderas="sect4" id="condition_variable_wait_until_bridgehead">
6784  <phrase id="condition_variable_wait_until"/>
6785  <link linkend="condition_variable_wait_until">Templated
6786        member function <code>wait_until</code>()</link>
6787</bridgehead>
6788      </para>
6789<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>
6790<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>
6791                      <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>
6792
6793<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>
6794<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>
6795                 <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>
6796                 <phrase role="identifier">Pred</phrase> <phrase role="identifier">pred</phrase><phrase role="special">);</phrase>
6797</programlisting>
6798      <variablelist>
6799        <title></title>
6800        <varlistentry>
6801          <term>Precondition:</term>
6802          <listitem>
6803            <para>
6804              <code><phrase role="identifier">lk</phrase></code> is locked by the
6805              current fiber, and either no other fiber is currently waiting on <code><phrase
6806              role="special">*</phrase><phrase role="keyword">this</phrase></code>,
6807              or the execution of the <code><phrase role="identifier">mutex</phrase><phrase
6808              role="special">()</phrase></code> member function on the <code><phrase
6809              role="identifier">lk</phrase></code> objects supplied in the calls
6810              to <code><phrase role="identifier">wait</phrase></code>, <code><phrase
6811              role="identifier">wait_for</phrase></code> or <code><phrase role="identifier">wait_until</phrase></code>
6812              in all the fibers currently waiting on <code><phrase role="special">*</phrase><phrase
6813              role="keyword">this</phrase></code> would return the same value as
6814              <code><phrase role="identifier">lk</phrase><phrase role="special">.</phrase><phrase
6815              role="identifier">mutex</phrase><phrase role="special">()</phrase></code>
6816              for this call to <code><phrase role="identifier">wait_until</phrase></code>.
6817            </para>
6818          </listitem>
6819        </varlistentry>
6820        <varlistentry>
6821          <term>Effects:</term>
6822          <listitem>
6823            <para>
6824              Atomically call <code><phrase role="identifier">lk</phrase><phrase
6825              role="special">.</phrase><phrase role="identifier">unlock</phrase><phrase
6826              role="special">()</phrase></code> and blocks the current fiber. The
6827              fiber will unblock when notified by a call to <code><phrase role="keyword">this</phrase><phrase
6828              role="special">-&gt;</phrase><phrase role="identifier">notify_one</phrase><phrase
6829              role="special">()</phrase></code> or <code><phrase role="keyword">this</phrase><phrase
6830              role="special">-&gt;</phrase><phrase role="identifier">notify_all</phrase><phrase
6831              role="special">()</phrase></code>, when the system time would be equal
6832              to or later than the specified <code><phrase role="identifier">abs_time</phrase></code>.
6833              When the fiber is unblocked (for whatever reason), the lock is reacquired
6834              by invoking <code><phrase role="identifier">lk</phrase><phrase role="special">.</phrase><phrase
6835              role="identifier">lock</phrase><phrase role="special">()</phrase></code>
6836              before the call to <code><phrase role="identifier">wait_until</phrase></code>
6837              returns. The lock is also reacquired by invoking <code><phrase role="identifier">lk</phrase><phrase
6838              role="special">.</phrase><phrase role="identifier">lock</phrase><phrase
6839              role="special">()</phrase></code> if the function exits with an exception.
6840              The member function accepting <code><phrase role="identifier">pred</phrase></code>
6841              is shorthand for:
6842<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>
6843    <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>
6844        <phrase role="keyword">return</phrase> <phrase role="identifier">pred</phrase><phrase role="special">();</phrase>
6845<phrase role="special">}</phrase>
6846<phrase role="keyword">return</phrase> <phrase role="keyword">true</phrase><phrase role="special">;</phrase>
6847</programlisting>
6848              That is, even if <code><phrase role="identifier">wait_until</phrase><phrase
6849              role="special">()</phrase></code> times out, it can still return <code><phrase
6850              role="keyword">true</phrase></code> if <code><phrase role="identifier">pred</phrase><phrase
6851              role="special">()</phrase></code> returns <code><phrase role="keyword">true</phrase></code>
6852              at that time.
6853            </para>
6854          </listitem>
6855        </varlistentry>
6856        <varlistentry>
6857          <term>Postcondition:</term>
6858          <listitem>
6859            <para>
6860              <code><phrase role="identifier">lk</phrase></code> is locked by the
6861              current fiber.
6862            </para>
6863          </listitem>
6864        </varlistentry>
6865        <varlistentry>
6866          <term>Throws:</term>
6867          <listitem>
6868            <para>
6869              <code><phrase role="identifier">fiber_error</phrase></code> if an error
6870              occurs or timeout-related exceptions.
6871            </para>
6872          </listitem>
6873        </varlistentry>
6874        <varlistentry>
6875          <term>Returns:</term>
6876          <listitem>
6877            <para>
6878              The overload without <code><phrase role="identifier">pred</phrase></code>
6879              returns <code><phrase role="identifier">cv_status</phrase><phrase role="special">::</phrase><phrase
6880              role="identifier">no_timeout</phrase></code> if awakened by <code><phrase
6881              role="identifier">notify_one</phrase><phrase role="special">()</phrase></code>
6882              or <code><phrase role="identifier">notify_all</phrase><phrase role="special">()</phrase></code>,
6883              or <code><phrase role="identifier">cv_status</phrase><phrase role="special">::</phrase><phrase
6884              role="identifier">timeout</phrase></code> if awakened because the system
6885              time is past <code><phrase role="identifier">abs_time</phrase></code>.
6886            </para>
6887          </listitem>
6888        </varlistentry>
6889        <varlistentry>
6890          <term>Returns:</term>
6891          <listitem>
6892            <para>
6893              The overload accepting <code><phrase role="identifier">pred</phrase></code>
6894              returns <code><phrase role="keyword">false</phrase></code> if the call
6895              is returning because the time specified by <code><phrase role="identifier">abs_time</phrase></code>
6896              was reached and the predicate returns <code><phrase role="keyword">false</phrase></code>,
6897              <code><phrase role="keyword">true</phrase></code> otherwise.
6898            </para>
6899          </listitem>
6900        </varlistentry>
6901        <varlistentry>
6902          <term>Note:</term>
6903          <listitem>
6904            <para>
6905              See <emphasis role="bold">Note</emphasis> for <link linkend="condition_variable_wait"><code>condition_variable::wait()</code></link>.
6906            </para>
6907          </listitem>
6908        </varlistentry>
6909      </variablelist>
6910      <para>
6911        <bridgehead renderas="sect4" id="condition_variable_wait_for_bridgehead">
6912  <phrase id="condition_variable_wait_for"/>
6913  <link linkend="condition_variable_wait_for">Templated
6914        member function <code>wait_for</code>()</link>
6915</bridgehead>
6916      </para>
6917<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>
6918<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>
6919                    <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>
6920
6921<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>
6922<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>
6923               <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>
6924               <phrase role="identifier">Pred</phrase> <phrase role="identifier">pred</phrase><phrase role="special">);</phrase>
6925</programlisting>
6926      <variablelist>
6927        <title></title>
6928        <varlistentry>
6929          <term>Precondition:</term>
6930          <listitem>
6931            <para>
6932              <code><phrase role="identifier">lk</phrase></code> is locked by the
6933              current fiber, and either no other fiber is currently waiting on <code><phrase
6934              role="special">*</phrase><phrase role="keyword">this</phrase></code>,
6935              or the execution of the <code><phrase role="identifier">mutex</phrase><phrase
6936              role="special">()</phrase></code> member function on the <code><phrase
6937              role="identifier">lk</phrase></code> objects supplied in the calls
6938              to <code><phrase role="identifier">wait</phrase></code>, <code><phrase
6939              role="identifier">wait_for</phrase></code> or <code><phrase role="identifier">wait_until</phrase></code>
6940              in all the fibers currently waiting on <code><phrase role="special">*</phrase><phrase
6941              role="keyword">this</phrase></code> would return the same value as
6942              <code><phrase role="identifier">lk</phrase><phrase role="special">.</phrase><phrase
6943              role="identifier">mutex</phrase><phrase role="special">()</phrase></code>
6944              for this call to <code><phrase role="identifier">wait_for</phrase></code>.
6945            </para>
6946          </listitem>
6947        </varlistentry>
6948        <varlistentry>
6949          <term>Effects:</term>
6950          <listitem>
6951            <para>
6952              Atomically call <code><phrase role="identifier">lk</phrase><phrase
6953              role="special">.</phrase><phrase role="identifier">unlock</phrase><phrase
6954              role="special">()</phrase></code> and blocks the current fiber. The
6955              fiber will unblock when notified by a call to <code><phrase role="keyword">this</phrase><phrase
6956              role="special">-&gt;</phrase><phrase role="identifier">notify_one</phrase><phrase
6957              role="special">()</phrase></code> or <code><phrase role="keyword">this</phrase><phrase
6958              role="special">-&gt;</phrase><phrase role="identifier">notify_all</phrase><phrase
6959              role="special">()</phrase></code>, when a time interval equal to or
6960              greater than the specified <code><phrase role="identifier">rel_time</phrase></code>
6961              has elapsed. When the fiber is unblocked (for whatever reason), the
6962              lock is reacquired by invoking <code><phrase role="identifier">lk</phrase><phrase
6963              role="special">.</phrase><phrase role="identifier">lock</phrase><phrase
6964              role="special">()</phrase></code> before the call to <code><phrase
6965              role="identifier">wait</phrase></code> returns. The lock is also reacquired
6966              by invoking <code><phrase role="identifier">lk</phrase><phrase role="special">.</phrase><phrase
6967              role="identifier">lock</phrase><phrase role="special">()</phrase></code>
6968              if the function exits with an exception. The <code><phrase role="identifier">wait_for</phrase><phrase
6969              role="special">()</phrase></code> member function accepting <code><phrase
6970              role="identifier">pred</phrase></code> is shorthand for:
6971<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>
6972    <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>
6973        <phrase role="keyword">return</phrase> <phrase role="identifier">pred</phrase><phrase role="special">();</phrase>
6974    <phrase role="special">}</phrase>
6975<phrase role="special">}</phrase>
6976<phrase role="keyword">return</phrase> <phrase role="keyword">true</phrase><phrase role="special">;</phrase>
6977</programlisting>
6978              (except of course that <code><phrase role="identifier">rel_time</phrase></code>
6979              is adjusted for each iteration). The point is that, even if <code><phrase
6980              role="identifier">wait_for</phrase><phrase role="special">()</phrase></code>
6981              times out, it can still return <code><phrase role="keyword">true</phrase></code>
6982              if <code><phrase role="identifier">pred</phrase><phrase role="special">()</phrase></code>
6983              returns <code><phrase role="keyword">true</phrase></code> at that time.
6984            </para>
6985          </listitem>
6986        </varlistentry>
6987        <varlistentry>
6988          <term>Postcondition:</term>
6989          <listitem>
6990            <para>
6991              <code><phrase role="identifier">lk</phrase></code> is locked by the
6992              current fiber.
6993            </para>
6994          </listitem>
6995        </varlistentry>
6996        <varlistentry>
6997          <term>Throws:</term>
6998          <listitem>
6999            <para>
7000              <code><phrase role="identifier">fiber_error</phrase></code> if an error
7001              occurs or timeout-related exceptions.
7002            </para>
7003          </listitem>
7004        </varlistentry>
7005        <varlistentry>
7006          <term>Returns:</term>
7007          <listitem>
7008            <para>
7009              The overload without <code><phrase role="identifier">pred</phrase></code>
7010              returns <code><phrase role="identifier">cv_status</phrase><phrase role="special">::</phrase><phrase
7011              role="identifier">no_timeout</phrase></code> if awakened by <code><phrase
7012              role="identifier">notify_one</phrase><phrase role="special">()</phrase></code>
7013              or <code><phrase role="identifier">notify_all</phrase><phrase role="special">()</phrase></code>,
7014              or <code><phrase role="identifier">cv_status</phrase><phrase role="special">::</phrase><phrase
7015              role="identifier">timeout</phrase></code> if awakened because at least
7016              <code><phrase role="identifier">rel_time</phrase></code> has elapsed.
7017            </para>
7018          </listitem>
7019        </varlistentry>
7020        <varlistentry>
7021          <term>Returns:</term>
7022          <listitem>
7023            <para>
7024              The overload accepting <code><phrase role="identifier">pred</phrase></code>
7025              returns <code><phrase role="keyword">false</phrase></code> if the call
7026              is returning because at least <code><phrase role="identifier">rel_time</phrase></code>
7027              has elapsed and the predicate returns <code><phrase role="keyword">false</phrase></code>,
7028              <code><phrase role="keyword">true</phrase></code> otherwise.
7029            </para>
7030          </listitem>
7031        </varlistentry>
7032        <varlistentry>
7033          <term>Note:</term>
7034          <listitem>
7035            <para>
7036              See <emphasis role="bold">Note</emphasis> for <link linkend="condition_variable_wait"><code>condition_variable::wait()</code></link>.
7037            </para>
7038          </listitem>
7039        </varlistentry>
7040      </variablelist>
7041    </section>
7042    <section id="fiber.synchronization.barriers">
7043      <title><link linkend="fiber.synchronization.barriers">Barriers</link></title>
7044      <para>
7045        A barrier is a concept also known as a <emphasis>rendezvous</emphasis>, it
7046        is a synchronization point between multiple contexts of execution (fibers).
7047        The barrier is configured for a particular number of fibers (<code><phrase
7048        role="identifier">n</phrase></code>), and as fibers reach the barrier they
7049        must wait until all <code><phrase role="identifier">n</phrase></code> fibers
7050        have arrived. Once the <code><phrase role="identifier">n</phrase></code>-th
7051        fiber has reached the barrier, all the waiting fibers can proceed, and the
7052        barrier is reset.
7053      </para>
7054      <para>
7055        The fact that the barrier automatically resets is significant. Consider a
7056        case in which you launch some number of fibers and want to wait only until
7057        the first of them has completed. You might be tempted to use a <code><phrase
7058        role="identifier">barrier</phrase><phrase role="special">(</phrase><phrase
7059        role="number">2</phrase><phrase role="special">)</phrase></code> as the synchronization
7060        mechanism, making each new fiber call its <link linkend="barrier_wait"><code>barrier::wait()</code></link> method,
7061        then calling <code><phrase role="identifier">wait</phrase><phrase role="special">()</phrase></code>
7062        in the launching fiber to wait until the first other fiber completes.
7063      </para>
7064      <para>
7065        That will in fact unblock the launching fiber. The unfortunate part is that
7066        it will continue blocking the <emphasis>remaining</emphasis> fibers.
7067      </para>
7068      <para>
7069        Consider the following scenario:
7070      </para>
7071      <orderedlist>
7072        <listitem>
7073          <simpara>
7074            Fiber <quote>main</quote> launches fibers A, B, C and D, then calls
7075            <code><phrase role="identifier">barrier</phrase><phrase role="special">::</phrase><phrase
7076            role="identifier">wait</phrase><phrase role="special">()</phrase></code>.
7077          </simpara>
7078        </listitem>
7079        <listitem>
7080          <simpara>
7081            Fiber C finishes first and likewise calls <code><phrase role="identifier">barrier</phrase><phrase
7082            role="special">::</phrase><phrase role="identifier">wait</phrase><phrase
7083            role="special">()</phrase></code>.
7084          </simpara>
7085        </listitem>
7086        <listitem>
7087          <simpara>
7088            Fiber <quote>main</quote> is unblocked, as desired.
7089          </simpara>
7090        </listitem>
7091        <listitem>
7092          <simpara>
7093            Fiber B calls <code><phrase role="identifier">barrier</phrase><phrase
7094            role="special">::</phrase><phrase role="identifier">wait</phrase><phrase
7095            role="special">()</phrase></code>. Fiber B is <emphasis>blocked!</emphasis>
7096          </simpara>
7097        </listitem>
7098        <listitem>
7099          <simpara>
7100            Fiber A calls <code><phrase role="identifier">barrier</phrase><phrase
7101            role="special">::</phrase><phrase role="identifier">wait</phrase><phrase
7102            role="special">()</phrase></code>. Fibers A and B are unblocked.
7103          </simpara>
7104        </listitem>
7105        <listitem>
7106          <simpara>
7107            Fiber D calls <code><phrase role="identifier">barrier</phrase><phrase
7108            role="special">::</phrase><phrase role="identifier">wait</phrase><phrase
7109            role="special">()</phrase></code>. Fiber D is blocked indefinitely.
7110          </simpara>
7111        </listitem>
7112      </orderedlist>
7113      <para>
7114        (See also <link linkend="wait_first_simple_section">when_any, simple completion</link>.)
7115      </para>
7116      <note>
7117        <para>
7118          It is unwise to tie the lifespan of a barrier to any one of its participating
7119          fibers. Although conceptually all waiting fibers awaken <quote>simultaneously,</quote>
7120          because of the nature of fibers, in practice they will awaken one by one
7121          in indeterminate order.<footnote id="fiber.synchronization.barriers.f0">
7122          <para>
7123            The current implementation wakes fibers in FIFO order: the first to call
7124            <code><phrase role="identifier">wait</phrase><phrase role="special">()</phrase></code>
7125            wakes first, and so forth. But it is perilous to rely on the order in
7126            which the various fibers will reach the <code><phrase role="identifier">wait</phrase><phrase
7127            role="special">()</phrase></code> call.
7128          </para>
7129          </footnote> The rest of the waiting fibers will still be blocked in <code><phrase
7130          role="identifier">wait</phrase><phrase role="special">()</phrase></code>,
7131          which must, before returning, access data members in the barrier object.
7132        </para>
7133      </note>
7134      <para>
7135        <bridgehead renderas="sect4" id="class_barrier_bridgehead">
7136  <phrase id="class_barrier"/>
7137  <link linkend="class_barrier">Class <code>barrier</code></link>
7138</bridgehead>
7139      </para>
7140<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>
7141
7142<phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase>
7143<phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase>
7144
7145<phrase role="keyword">class</phrase> <phrase role="identifier">barrier</phrase> <phrase role="special">{</phrase>
7146<phrase role="keyword">public</phrase><phrase role="special">:</phrase>
7147    <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>
7148
7149    <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>
7150    <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>
7151
7152    <phrase role="keyword">bool</phrase> <phrase role="identifier">wait</phrase><phrase role="special">();</phrase>
7153<phrase role="special">};</phrase>
7154
7155<phrase role="special">}}</phrase>
7156</programlisting>
7157      <para>
7158        Instances of <link linkend="class_barrier"><code>barrier</code></link> are not copyable or movable.
7159      </para>
7160      <bridgehead renderas="sect4" id="fiber.synchronization.barriers.h0">
7161        <phrase id="fiber.synchronization.barriers.constructor"/><link linkend="fiber.synchronization.barriers.constructor">Constructor</link>
7162      </bridgehead>
7163<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>
7164</programlisting>
7165      <variablelist>
7166        <title></title>
7167        <varlistentry>
7168          <term>Effects:</term>
7169          <listitem>
7170            <para>
7171              Construct a barrier for <code><phrase role="identifier">initial</phrase></code>
7172              fibers.
7173            </para>
7174          </listitem>
7175        </varlistentry>
7176        <varlistentry>
7177          <term>Throws:</term>
7178          <listitem>
7179            <para>
7180              <code><phrase role="identifier">fiber_error</phrase></code>
7181            </para>
7182          </listitem>
7183        </varlistentry>
7184        <varlistentry>
7185          <term>Error Conditions:</term>
7186          <listitem>
7187            <para>
7188              <emphasis role="bold">invalid_argument</emphasis>: if <code><phrase
7189              role="identifier">initial</phrase></code> is zero.
7190            </para>
7191          </listitem>
7192        </varlistentry>
7193      </variablelist>
7194      <para>
7195        <bridgehead renderas="sect4" id="barrier_wait_bridgehead">
7196  <phrase id="barrier_wait"/>
7197  <link linkend="barrier_wait">Member function <code>wait</code>()</link>
7198</bridgehead>
7199      </para>
7200<programlisting><phrase role="keyword">bool</phrase> <phrase role="identifier">wait</phrase><phrase role="special">();</phrase>
7201</programlisting>
7202      <variablelist>
7203        <title></title>
7204        <varlistentry>
7205          <term>Effects:</term>
7206          <listitem>
7207            <para>
7208              Block until <code><phrase role="identifier">initial</phrase></code>
7209              fibers have called <code><phrase role="identifier">wait</phrase></code>
7210              on <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>.
7211              When the <code><phrase role="identifier">initial</phrase></code>-th
7212              fiber calls <code><phrase role="identifier">wait</phrase></code>, all
7213              waiting fibers are unblocked, and the barrier is reset.
7214            </para>
7215          </listitem>
7216        </varlistentry>
7217        <varlistentry>
7218          <term>Returns:</term>
7219          <listitem>
7220            <para>
7221              <code><phrase role="keyword">true</phrase></code> for exactly one fiber
7222              from each batch of waiting fibers, <code><phrase role="keyword">false</phrase></code>
7223              otherwise.
7224            </para>
7225          </listitem>
7226        </varlistentry>
7227        <varlistentry>
7228          <term>Throws:</term>
7229          <listitem>
7230            <para>
7231              <code><phrase role="identifier">fiber_error</phrase></code>
7232            </para>
7233          </listitem>
7234        </varlistentry>
7235      </variablelist>
7236    </section>
7237    <section id="fiber.synchronization.channels">
7238      <title><link linkend="fiber.synchronization.channels">Channels</link></title>
7239      <para>
7240        A channel is a model to communicate and synchronize <code><phrase role="identifier">Threads</phrase>
7241        <phrase role="identifier">of</phrase> <phrase role="identifier">Execution</phrase></code>
7242        <footnote id="fiber.synchronization.channels.f0">
7243        <para>
7244          The smallest ordered sequence of instructions that can be managed independently
7245          by a scheduler is called a <code><phrase role="identifier">Thread</phrase>
7246          <phrase role="identifier">of</phrase> <phrase role="identifier">Execution</phrase></code>.
7247        </para>
7248        </footnote> via message passing.
7249      </para>
7250      <anchor id="class_channel_op_status"/>
7251      <bridgehead renderas="sect4" id="fiber.synchronization.channels.h0">
7252        <phrase id="fiber.synchronization.channels.enumeration__code__phrase_role__identifier__channel_op_status__phrase___code_"/><link
7253        linkend="fiber.synchronization.channels.enumeration__code__phrase_role__identifier__channel_op_status__phrase___code_">Enumeration
7254        <code><phrase role="identifier">channel_op_status</phrase></code></link>
7255      </bridgehead>
7256      <para>
7257        channel operations return the state of the channel.
7258      </para>
7259<programlisting><phrase role="keyword">enum</phrase> <phrase role="keyword">class</phrase> <phrase role="identifier">channel_op_status</phrase> <phrase role="special">{</phrase>
7260    <phrase role="identifier">success</phrase><phrase role="special">,</phrase>
7261    <phrase role="identifier">empty</phrase><phrase role="special">,</phrase>
7262    <phrase role="identifier">full</phrase><phrase role="special">,</phrase>
7263    <phrase role="identifier">closed</phrase><phrase role="special">,</phrase>
7264    <phrase role="identifier">timeout</phrase>
7265<phrase role="special">};</phrase>
7266</programlisting>
7267      <bridgehead renderas="sect4" id="fiber.synchronization.channels.h1">
7268        <phrase id="fiber.synchronization.channels._code__phrase_role__identifier__success__phrase___code_"/><link
7269        linkend="fiber.synchronization.channels._code__phrase_role__identifier__success__phrase___code_"><code><phrase
7270        role="identifier">success</phrase></code></link>
7271      </bridgehead>
7272      <variablelist>
7273        <title></title>
7274        <varlistentry>
7275          <term>Effects:</term>
7276          <listitem>
7277            <para>
7278              Operation was successful.
7279            </para>
7280          </listitem>
7281        </varlistentry>
7282      </variablelist>
7283      <bridgehead renderas="sect4" id="fiber.synchronization.channels.h2">
7284        <phrase id="fiber.synchronization.channels._code__phrase_role__identifier__empty__phrase___code_"/><link
7285        linkend="fiber.synchronization.channels._code__phrase_role__identifier__empty__phrase___code_"><code><phrase
7286        role="identifier">empty</phrase></code></link>
7287      </bridgehead>
7288      <variablelist>
7289        <title></title>
7290        <varlistentry>
7291          <term>Effects:</term>
7292          <listitem>
7293            <para>
7294              channel is empty, operation failed.
7295            </para>
7296          </listitem>
7297        </varlistentry>
7298      </variablelist>
7299      <bridgehead renderas="sect4" id="fiber.synchronization.channels.h3">
7300        <phrase id="fiber.synchronization.channels._code__phrase_role__identifier__full__phrase___code_"/><link
7301        linkend="fiber.synchronization.channels._code__phrase_role__identifier__full__phrase___code_"><code><phrase
7302        role="identifier">full</phrase></code></link>
7303      </bridgehead>
7304      <variablelist>
7305        <title></title>
7306        <varlistentry>
7307          <term>Effects:</term>
7308          <listitem>
7309            <para>
7310              channel is full, operation failed.
7311            </para>
7312          </listitem>
7313        </varlistentry>
7314      </variablelist>
7315      <bridgehead renderas="sect4" id="fiber.synchronization.channels.h4">
7316        <phrase id="fiber.synchronization.channels._code__phrase_role__identifier__closed__phrase___code_"/><link
7317        linkend="fiber.synchronization.channels._code__phrase_role__identifier__closed__phrase___code_"><code><phrase
7318        role="identifier">closed</phrase></code></link>
7319      </bridgehead>
7320      <variablelist>
7321        <title></title>
7322        <varlistentry>
7323          <term>Effects:</term>
7324          <listitem>
7325            <para>
7326              channel is closed, operation failed.
7327            </para>
7328          </listitem>
7329        </varlistentry>
7330      </variablelist>
7331      <bridgehead renderas="sect4" id="fiber.synchronization.channels.h5">
7332        <phrase id="fiber.synchronization.channels._code__phrase_role__identifier__timeout__phrase___code_"/><link
7333        linkend="fiber.synchronization.channels._code__phrase_role__identifier__timeout__phrase___code_"><code><phrase
7334        role="identifier">timeout</phrase></code></link>
7335      </bridgehead>
7336      <variablelist>
7337        <title></title>
7338        <varlistentry>
7339          <term>Effects:</term>
7340          <listitem>
7341            <para>
7342              The operation did not become ready before specified timeout elapsed.
7343            </para>
7344          </listitem>
7345        </varlistentry>
7346      </variablelist>
7347      <section id="fiber.synchronization.channels.buffered_channel">
7348        <title><link linkend="fiber.synchronization.channels.buffered_channel">Buffered
7349        Channel</link></title>
7350        <para>
7351          <emphasis role="bold">Boost.Fiber</emphasis> provides a bounded, buffered
7352          channel (MPMC queue) suitable to synchonize fibers (running on same or
7353          different threads) via asynchronouss message passing.
7354        </para>
7355<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>
7356
7357<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>
7358    <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>
7359        <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>
7360    <phrase role="special">}</phrase>
7361    <phrase role="identifier">chan</phrase><phrase role="special">.</phrase><phrase role="identifier">close</phrase><phrase role="special">();</phrase>
7362<phrase role="special">}</phrase>
7363
7364<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>
7365    <phrase role="keyword">int</phrase> <phrase role="identifier">i</phrase><phrase role="special">;</phrase>
7366    <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>
7367        <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>
7368    <phrase role="special">}</phrase>
7369<phrase role="special">}</phrase>
7370
7371<phrase role="identifier">channel_t</phrase> <phrase role="identifier">chan</phrase><phrase role="special">{</phrase> <phrase role="number">2</phrase> <phrase role="special">};</phrase>
7372<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>
7373<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>
7374
7375<phrase role="identifier">f1</phrase><phrase role="special">.</phrase><phrase role="identifier">join</phrase><phrase role="special">();</phrase>
7376<phrase role="identifier">f2</phrase><phrase role="special">.</phrase><phrase role="identifier">join</phrase><phrase role="special">();</phrase>
7377</programlisting>
7378        <para>
7379          Class <code><phrase role="identifier">buffered_channel</phrase></code>
7380          supports range-for syntax:
7381        </para>
7382<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>
7383
7384<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>
7385    <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>
7386    <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>
7387    <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>
7388    <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>
7389    <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>
7390    <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>
7391    <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>
7392    <phrase role="identifier">chan</phrase><phrase role="special">.</phrase><phrase role="identifier">close</phrase><phrase role="special">();</phrase>
7393<phrase role="special">}</phrase>
7394
7395<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>
7396    <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>
7397        <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>
7398    <phrase role="special">}</phrase>
7399    <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>
7400<phrase role="special">}</phrase>
7401</programlisting>
7402        <para>
7403          <bridgehead renderas="sect4" id="class_buffered_channel_bridgehead">
7404  <phrase id="class_buffered_channel"/>
7405  <link linkend="class_buffered_channel">Template
7406          <code>buffered_channel&lt;&gt;</code></link>
7407</bridgehead>
7408        </para>
7409<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>
7410
7411<phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase>
7412<phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase>
7413
7414<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>
7415<phrase role="keyword">class</phrase> <phrase role="identifier">buffered_channel</phrase> <phrase role="special">{</phrase>
7416<phrase role="keyword">public</phrase><phrase role="special">:</phrase>
7417    <phrase role="keyword">typedef</phrase> <phrase role="identifier">T</phrase>   <phrase role="identifier">value_type</phrase><phrase role="special">;</phrase>
7418
7419    <phrase role="keyword">class</phrase> <phrase role="identifier">iterator</phrase><phrase role="special">;</phrase>
7420
7421    <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>
7422
7423    <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>
7424    <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>
7425
7426    <phrase role="keyword">void</phrase> <phrase role="identifier">close</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
7427
7428    <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>
7429    <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>
7430    <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>
7431    <phrase role="identifier">channel_op_status</phrase> <phrase role="identifier">push_wait_for</phrase><phrase role="special">(</phrase>
7432        <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>
7433        <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>
7434    <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>
7435        <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>
7436    <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>
7437    <phrase role="identifier">channel_op_status</phrase> <phrase role="identifier">push_wait_until</phrase><phrase role="special">(</phrase>
7438        <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>
7439        <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>
7440    <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>
7441    <phrase role="identifier">channel_op_status</phrase> <phrase role="identifier">push_wait_until</phrase><phrase role="special">(</phrase>
7442        <phrase role="identifier">value_type</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="identifier">va</phrase><phrase role="special">,</phrase>
7443        <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>
7444    <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>
7445    <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>
7446
7447    <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>
7448    <phrase role="identifier">value_type</phrase> <phrase role="identifier">value_pop</phrase><phrase role="special">();</phrase>
7449    <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>
7450    <phrase role="identifier">channel_op_status</phrase> <phrase role="identifier">pop_wait_for</phrase><phrase role="special">(</phrase>
7451        <phrase role="identifier">value_type</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">va</phrase><phrase role="special">,</phrase>
7452        <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>
7453    <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>
7454    <phrase role="identifier">channel_op_status</phrase> <phrase role="identifier">pop_wait_until</phrase><phrase role="special">(</phrase>
7455        <phrase role="identifier">value_type</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">va</phrase><phrase role="special">,</phrase>
7456        <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>
7457    <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>
7458<phrase role="special">};</phrase>
7459
7460<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>
7461<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>
7462
7463<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>
7464<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>
7465
7466<phrase role="special">}}</phrase>
7467</programlisting>
7468        <bridgehead renderas="sect5" id="fiber.synchronization.channels.buffered_channel.h0">
7469          <phrase id="fiber.synchronization.channels.buffered_channel.constructor"/><link
7470          linkend="fiber.synchronization.channels.buffered_channel.constructor">Constructor</link>
7471        </bridgehead>
7472<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>
7473</programlisting>
7474        <variablelist>
7475          <title></title>
7476          <varlistentry>
7477            <term>Preconditions:</term>
7478            <listitem>
7479              <para>
7480                <code><phrase role="number">2</phrase><phrase role="special">&lt;=</phrase><phrase
7481                role="identifier">capacity</phrase> <phrase role="special">&amp;&amp;</phrase>
7482                <phrase role="number">0</phrase><phrase role="special">==(</phrase><phrase
7483                role="identifier">capacity</phrase> <phrase role="special">&amp;</phrase>
7484                <phrase role="special">(</phrase><phrase role="identifier">capacity</phrase><phrase
7485                role="special">-</phrase><phrase role="number">1</phrase><phrase
7486                role="special">))</phrase></code>
7487              </para>
7488            </listitem>
7489          </varlistentry>
7490          <varlistentry>
7491            <term>Effects:</term>
7492            <listitem>
7493              <para>
7494                The constructor constructs an object of class <code><phrase role="identifier">buffered_channel</phrase></code>
7495                with an internal buffer of size <code><phrase role="identifier">capacity</phrase></code>.
7496              </para>
7497            </listitem>
7498          </varlistentry>
7499          <varlistentry>
7500            <term>Throws:</term>
7501            <listitem>
7502              <para>
7503                <code><phrase role="identifier">fiber_error</phrase></code>
7504              </para>
7505            </listitem>
7506          </varlistentry>
7507          <varlistentry>
7508            <term>Error Conditions:</term>
7509            <listitem>
7510              <para>
7511                <emphasis role="bold">invalid_argument</emphasis>: if <code><phrase
7512                role="number">0</phrase><phrase role="special">==</phrase><phrase
7513                role="identifier">capacity</phrase> <phrase role="special">||</phrase>
7514                <phrase role="number">0</phrase><phrase role="special">!=(</phrase><phrase
7515                role="identifier">capacity</phrase> <phrase role="special">&amp;</phrase>
7516                <phrase role="special">(</phrase><phrase role="identifier">capacity</phrase><phrase
7517                role="special">-</phrase><phrase role="number">1</phrase><phrase
7518                role="special">))</phrase></code>.
7519              </para>
7520            </listitem>
7521          </varlistentry>
7522          <varlistentry>
7523            <term>Notes:</term>
7524            <listitem>
7525              <para>
7526                A <code><phrase role="identifier">push</phrase><phrase role="special">()</phrase></code>,
7527                <code><phrase role="identifier">push_wait_for</phrase><phrase role="special">()</phrase></code>
7528                or <code><phrase role="identifier">push_wait_until</phrase><phrase
7529                role="special">()</phrase></code> will not block until the number
7530                of values in the channel becomes equal to <code><phrase role="identifier">capacity</phrase></code>.
7531                The channel can hold only <code><phrase role="identifier">capacity</phrase>
7532                <phrase role="special">-</phrase> <phrase role="number">1</phrase></code>
7533                elements, otherwise it is considered to be full.
7534              </para>
7535            </listitem>
7536          </varlistentry>
7537        </variablelist>
7538        <para>
7539          <bridgehead renderas="sect4" id="buffered_channel_close_bridgehead">
7540  <phrase id="buffered_channel_close"/>
7541  <link linkend="buffered_channel_close">Member
7542          function <code>close</code>()</link>
7543</bridgehead>
7544        </para>
7545<programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">close</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
7546</programlisting>
7547        <variablelist>
7548          <title></title>
7549          <varlistentry>
7550            <term>Effects:</term>
7551            <listitem>
7552              <para>
7553                Deactivates the channel. No values can be put after calling <code><phrase
7554                role="keyword">this</phrase><phrase role="special">-&gt;</phrase><phrase
7555                role="identifier">close</phrase><phrase role="special">()</phrase></code>.
7556                Fibers blocked in <code><phrase role="keyword">this</phrase><phrase
7557                role="special">-&gt;</phrase><phrase role="identifier">pop</phrase><phrase
7558                role="special">()</phrase></code>, <code><phrase role="keyword">this</phrase><phrase
7559                role="special">-&gt;</phrase><phrase role="identifier">pop_wait_for</phrase><phrase
7560                role="special">()</phrase></code> or <code><phrase role="keyword">this</phrase><phrase
7561                role="special">-&gt;</phrase><phrase role="identifier">pop_wait_until</phrase><phrase
7562                role="special">()</phrase></code> will return <code><phrase role="identifier">closed</phrase></code>.
7563                Fibers blocked in <code><phrase role="keyword">this</phrase><phrase
7564                role="special">-&gt;</phrase><phrase role="identifier">value_pop</phrase><phrase
7565                role="special">()</phrase></code> will receive an exception.
7566              </para>
7567            </listitem>
7568          </varlistentry>
7569          <varlistentry>
7570            <term>Throws:</term>
7571            <listitem>
7572              <para>
7573                Nothing.
7574              </para>
7575            </listitem>
7576          </varlistentry>
7577          <varlistentry>
7578            <term>Note:</term>
7579            <listitem>
7580              <para>
7581                <code><phrase role="identifier">close</phrase><phrase role="special">()</phrase></code>
7582                is like closing a pipe. It informs waiting consumers that no more
7583                values will arrive.
7584              </para>
7585            </listitem>
7586          </varlistentry>
7587        </variablelist>
7588        <para>
7589          <bridgehead renderas="sect4" id="buffered_channel_push_bridgehead">
7590  <phrase id="buffered_channel_push"/>
7591  <link linkend="buffered_channel_push">Member
7592          function <code>push</code>()</link>
7593</bridgehead>
7594        </para>
7595<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>
7596<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>
7597</programlisting>
7598        <variablelist>
7599          <title></title>
7600          <varlistentry>
7601            <term>Effects:</term>
7602            <listitem>
7603              <para>
7604                If channel is closed, returns <code><phrase role="identifier">closed</phrase></code>.
7605                Otherwise enqueues the value in the channel, wakes up a fiber blocked
7606                on <code><phrase role="keyword">this</phrase><phrase role="special">-&gt;</phrase><phrase
7607                role="identifier">pop</phrase><phrase role="special">()</phrase></code>,
7608                <code><phrase role="keyword">this</phrase><phrase role="special">-&gt;</phrase><phrase
7609                role="identifier">value_pop</phrase><phrase role="special">()</phrase></code>,
7610                <code><phrase role="keyword">this</phrase><phrase role="special">-&gt;</phrase><phrase
7611                role="identifier">pop_wait_for</phrase><phrase role="special">()</phrase></code>
7612                or <code><phrase role="keyword">this</phrase><phrase role="special">-&gt;</phrase><phrase
7613                role="identifier">pop_wait_until</phrase><phrase role="special">()</phrase></code>
7614                and returns <code><phrase role="identifier">success</phrase></code>.
7615                If the channel is full, the fiber is blocked.
7616              </para>
7617            </listitem>
7618          </varlistentry>
7619          <varlistentry>
7620            <term>Throws:</term>
7621            <listitem>
7622              <para>
7623                Exceptions thrown by copy- or move-operations.
7624              </para>
7625            </listitem>
7626          </varlistentry>
7627        </variablelist>
7628        <para>
7629          <bridgehead renderas="sect4" id="buffered_channel_try_push_bridgehead">
7630  <phrase id="buffered_channel_try_push"/>
7631  <link linkend="buffered_channel_try_push">Member
7632          function <code>try_push</code>()</link>
7633</bridgehead>
7634        </para>
7635<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>
7636<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>
7637</programlisting>
7638        <variablelist>
7639          <title></title>
7640          <varlistentry>
7641            <term>Effects:</term>
7642            <listitem>
7643              <para>
7644                If channel is closed, returns <code><phrase role="identifier">closed</phrase></code>.
7645                Otherwise enqueues the value in the channel, wakes up a fiber blocked
7646                on <code><phrase role="keyword">this</phrase><phrase role="special">-&gt;</phrase><phrase
7647                role="identifier">pop</phrase><phrase role="special">()</phrase></code>,
7648                <code><phrase role="keyword">this</phrase><phrase role="special">-&gt;</phrase><phrase
7649                role="identifier">value_pop</phrase><phrase role="special">()</phrase></code>,
7650                <code><phrase role="keyword">this</phrase><phrase role="special">-&gt;</phrase><phrase
7651                role="identifier">pop_wait_for</phrase><phrase role="special">()</phrase></code>
7652                or <code><phrase role="keyword">this</phrase><phrase role="special">-&gt;</phrase><phrase
7653                role="identifier">pop_wait_until</phrase><phrase role="special">()</phrase></code>
7654                and returns <code><phrase role="identifier">success</phrase></code>.
7655                If the channel is full, it doesn't block and returns <code><phrase
7656                role="identifier">full</phrase></code>.
7657              </para>
7658            </listitem>
7659          </varlistentry>
7660          <varlistentry>
7661            <term>Throws:</term>
7662            <listitem>
7663              <para>
7664                Exceptions thrown by copy- or move-operations.
7665              </para>
7666            </listitem>
7667          </varlistentry>
7668        </variablelist>
7669        <para>
7670          <bridgehead renderas="sect4" id="buffered_channel_pop_bridgehead">
7671  <phrase id="buffered_channel_pop"/>
7672  <link linkend="buffered_channel_pop">Member
7673          function <code>pop</code>()</link>
7674</bridgehead>
7675        </para>
7676<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>
7677</programlisting>
7678        <variablelist>
7679          <title></title>
7680          <varlistentry>
7681            <term>Effects:</term>
7682            <listitem>
7683              <para>
7684                Dequeues a value from the channel. If the channel is empty, the fiber
7685                gets suspended until at least one new item is <code><phrase role="identifier">push</phrase><phrase
7686                role="special">()</phrase></code>ed (return value <code><phrase role="identifier">success</phrase></code>
7687                and <code><phrase role="identifier">va</phrase></code> contains dequeued
7688                value) or the channel gets <code><phrase role="identifier">close</phrase><phrase
7689                role="special">()</phrase></code>d (return value <code><phrase role="identifier">closed</phrase></code>).
7690              </para>
7691            </listitem>
7692          </varlistentry>
7693          <varlistentry>
7694            <term>Throws:</term>
7695            <listitem>
7696              <para>
7697                Exceptions thrown by copy- or move-operations.
7698              </para>
7699            </listitem>
7700          </varlistentry>
7701        </variablelist>
7702        <para>
7703          <bridgehead renderas="sect4" id="buffered_channel_value_pop_bridgehead">
7704  <phrase id="buffered_channel_value_pop"/>
7705  <link linkend="buffered_channel_value_pop">Member
7706          function <code>value_pop</code>()</link>
7707</bridgehead>
7708        </para>
7709<programlisting><phrase role="identifier">value_type</phrase> <phrase role="identifier">value_pop</phrase><phrase role="special">();</phrase>
7710</programlisting>
7711        <variablelist>
7712          <title></title>
7713          <varlistentry>
7714            <term>Effects:</term>
7715            <listitem>
7716              <para>
7717                Dequeues a value from the channel. If the channel is empty, the fiber
7718                gets suspended until at least one new item is <code><phrase role="identifier">push</phrase><phrase
7719                role="special">()</phrase></code>ed or the channel gets <code><phrase
7720                role="identifier">close</phrase><phrase role="special">()</phrase></code>d
7721                (which throws an exception).
7722              </para>
7723            </listitem>
7724          </varlistentry>
7725          <varlistentry>
7726            <term>Throws:</term>
7727            <listitem>
7728              <para>
7729                <code><phrase role="identifier">fiber_error</phrase></code> if <code><phrase
7730                role="special">*</phrase><phrase role="keyword">this</phrase></code>
7731                is closed or by copy- or move-operations.
7732              </para>
7733            </listitem>
7734          </varlistentry>
7735          <varlistentry>
7736            <term>Error conditions:</term>
7737            <listitem>
7738              <para>
7739                <code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase
7740                role="identifier">errc</phrase><phrase role="special">::</phrase><phrase
7741                role="identifier">operation_not_permitted</phrase></code>
7742              </para>
7743            </listitem>
7744          </varlistentry>
7745        </variablelist>
7746        <para>
7747          <bridgehead renderas="sect4" id="buffered_channel_try_pop_bridgehead">
7748  <phrase id="buffered_channel_try_pop"/>
7749  <link linkend="buffered_channel_try_pop">Member
7750          function <code>try_pop</code>()</link>
7751</bridgehead>
7752        </para>
7753<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>
7754</programlisting>
7755        <variablelist>
7756          <title></title>
7757          <varlistentry>
7758            <term>Effects:</term>
7759            <listitem>
7760              <para>
7761                If channel is empty, returns <code><phrase role="identifier">empty</phrase></code>.
7762                If channel is closed, returns <code><phrase role="identifier">closed</phrase></code>.
7763                Otherwise it returns <code><phrase role="identifier">success</phrase></code>
7764                and <code><phrase role="identifier">va</phrase></code> contains the
7765                dequeued value.
7766              </para>
7767            </listitem>
7768          </varlistentry>
7769          <varlistentry>
7770            <term>Throws:</term>
7771            <listitem>
7772              <para>
7773                Exceptions thrown by copy- or move-operations.
7774              </para>
7775            </listitem>
7776          </varlistentry>
7777        </variablelist>
7778        <para>
7779          <bridgehead renderas="sect4" id="buffered_channel_pop_wait_for_bridgehead">
7780  <phrase id="buffered_channel_pop_wait_for"/>
7781  <link linkend="buffered_channel_pop_wait_for">Member
7782          function <code>pop_wait_for</code>()</link>
7783</bridgehead>
7784        </para>
7785<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>
7786<phrase role="identifier">channel_op_status</phrase> <phrase role="identifier">pop_wait_for</phrase><phrase role="special">(</phrase>
7787    <phrase role="identifier">value_type</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">va</phrase><phrase role="special">,</phrase>
7788    <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>
7789</programlisting>
7790        <variablelist>
7791          <title></title>
7792          <varlistentry>
7793            <term>Effects:</term>
7794            <listitem>
7795              <para>
7796                Accepts <code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase
7797                role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase
7798                role="identifier">duration</phrase></code> and internally computes
7799                a timeout time as (system time + <code><phrase role="identifier">timeout_duration</phrase></code>).
7800                If channel is not empty, immediately dequeues a value from the channel.
7801                Otherwise the fiber gets suspended until at least one new item is
7802                <code><phrase role="identifier">push</phrase><phrase role="special">()</phrase></code>ed
7803                (return value <code><phrase role="identifier">success</phrase></code>
7804                and <code><phrase role="identifier">va</phrase></code> contains dequeued
7805                value), or the channel gets <code><phrase role="identifier">close</phrase><phrase
7806                role="special">()</phrase></code>d (return value <code><phrase role="identifier">closed</phrase></code>),
7807                or the system time reaches the computed timeout time (return value
7808                <code><phrase role="identifier">timeout</phrase></code>).
7809              </para>
7810            </listitem>
7811          </varlistentry>
7812          <varlistentry>
7813            <term>Throws:</term>
7814            <listitem>
7815              <para>
7816                timeout-related exceptions or by copy- or move-operations.
7817              </para>
7818            </listitem>
7819          </varlistentry>
7820        </variablelist>
7821        <para>
7822          <bridgehead renderas="sect4" id="buffered_channel_pop_wait_until_bridgehead">
7823  <phrase id="buffered_channel_pop_wait_until"/>
7824  <link linkend="buffered_channel_pop_wait_until">Member
7825          function <code>pop_wait_until</code>()</link>
7826</bridgehead>
7827        </para>
7828<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>
7829<phrase role="identifier">channel_op_status</phrase> <phrase role="identifier">pop_wait_until</phrase><phrase role="special">(</phrase>
7830    <phrase role="identifier">value_type</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">va</phrase><phrase role="special">,</phrase>
7831    <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>
7832</programlisting>
7833        <variablelist>
7834          <title></title>
7835          <varlistentry>
7836            <term>Effects:</term>
7837            <listitem>
7838              <para>
7839                Accepts a <code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase
7840                role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase
7841                role="identifier">time_point</phrase><phrase role="special">&lt;</phrase>
7842                <phrase role="identifier">Clock</phrase><phrase role="special">,</phrase>
7843                <phrase role="identifier">Duration</phrase> <phrase role="special">&gt;</phrase></code>.
7844                If channel is not empty, immediately dequeues a value from the channel.
7845                Otherwise the fiber gets suspended until at least one new item is
7846                <code><phrase role="identifier">push</phrase><phrase role="special">()</phrase></code>ed
7847                (return value <code><phrase role="identifier">success</phrase></code>
7848                and <code><phrase role="identifier">va</phrase></code> contains dequeued
7849                value), or the channel gets <code><phrase role="identifier">close</phrase><phrase
7850                role="special">()</phrase></code>d (return value <code><phrase role="identifier">closed</phrase></code>),
7851                or the system time reaches the passed <code><phrase role="identifier">time_point</phrase></code>
7852                (return value <code><phrase role="identifier">timeout</phrase></code>).
7853              </para>
7854            </listitem>
7855          </varlistentry>
7856          <varlistentry>
7857            <term>Throws:</term>
7858            <listitem>
7859              <para>
7860                timeout-related exceptions or by copy- or move-operations.
7861              </para>
7862            </listitem>
7863          </varlistentry>
7864        </variablelist>
7865        <bridgehead renderas="sect5" id="fiber.synchronization.channels.buffered_channel.h1">
7866          <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
7867          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
7868          function <code><phrase role="identifier">begin</phrase><phrase role="special">(</phrase>
7869          <phrase role="identifier">buffered_channel</phrase><phrase role="special">&lt;</phrase>
7870          <phrase role="identifier">T</phrase> <phrase role="special">&gt;</phrase>
7871          <phrase role="special">&amp;)</phrase></code></link>
7872        </bridgehead>
7873<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>
7874<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>
7875</programlisting>
7876        <variablelist>
7877          <title></title>
7878          <varlistentry>
7879            <term>Returns:</term>
7880            <listitem>
7881              <para>
7882                Returns a range-iterator (input-iterator).
7883              </para>
7884            </listitem>
7885          </varlistentry>
7886        </variablelist>
7887        <bridgehead renderas="sect5" id="fiber.synchronization.channels.buffered_channel.h2">
7888          <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
7889          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
7890          function <code><phrase role="identifier">end</phrase><phrase role="special">(</phrase>
7891          <phrase role="identifier">buffered_channel</phrase><phrase role="special">&lt;</phrase>
7892          <phrase role="identifier">T</phrase> <phrase role="special">&gt;</phrase>
7893          <phrase role="special">&amp;)</phrase></code></link>
7894        </bridgehead>
7895<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>
7896<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>
7897</programlisting>
7898        <variablelist>
7899          <title></title>
7900          <varlistentry>
7901            <term>Returns:</term>
7902            <listitem>
7903              <para>
7904                Returns an end range-iterator (input-iterator).
7905              </para>
7906            </listitem>
7907          </varlistentry>
7908        </variablelist>
7909      </section>
7910      <section id="fiber.synchronization.channels.unbuffered_channel">
7911        <title><link linkend="fiber.synchronization.channels.unbuffered_channel">Unbuffered
7912        Channel</link></title>
7913        <para>
7914          <emphasis role="bold">Boost.Fiber</emphasis> provides template <code><phrase
7915          role="identifier">unbuffered_channel</phrase></code> suitable to synchonize
7916          fibers (running on same or different threads) via synchronous message passing.
7917          A fiber waiting to consume an value will block until the value is produced.
7918          If a fiber attempts to send a value through an unbuffered channel and no
7919          fiber is waiting to receive the value, the channel will block the sending
7920          fiber.
7921        </para>
7922        <para>
7923          The unbuffered channel acts as an <code><phrase role="identifier">rendezvous</phrase>
7924          <phrase role="identifier">point</phrase></code>.
7925        </para>
7926<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>
7927
7928<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>
7929    <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>
7930        <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>
7931    <phrase role="special">}</phrase>
7932    <phrase role="identifier">chan</phrase><phrase role="special">.</phrase><phrase role="identifier">close</phrase><phrase role="special">();</phrase>
7933<phrase role="special">}</phrase>
7934
7935<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>
7936    <phrase role="keyword">int</phrase> <phrase role="identifier">i</phrase><phrase role="special">;</phrase>
7937    <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>
7938        <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>
7939    <phrase role="special">}</phrase>
7940<phrase role="special">}</phrase>
7941
7942<phrase role="identifier">channel_t</phrase> <phrase role="identifier">chan</phrase><phrase role="special">{</phrase> <phrase role="number">1</phrase> <phrase role="special">};</phrase>
7943<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>
7944<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>
7945
7946<phrase role="identifier">f1</phrase><phrase role="special">.</phrase><phrase role="identifier">join</phrase><phrase role="special">();</phrase>
7947<phrase role="identifier">f2</phrase><phrase role="special">.</phrase><phrase role="identifier">join</phrase><phrase role="special">();</phrase>
7948</programlisting>
7949        <para>
7950          Range-for syntax is supported:
7951        </para>
7952<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>
7953
7954<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>
7955    <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>
7956    <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>
7957    <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>
7958    <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>
7959    <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>
7960    <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>
7961    <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>
7962    <phrase role="identifier">chan</phrase><phrase role="special">.</phrase><phrase role="identifier">close</phrase><phrase role="special">();</phrase>
7963<phrase role="special">}</phrase>
7964
7965<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>
7966    <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>
7967        <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>
7968    <phrase role="special">}</phrase>
7969    <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>
7970<phrase role="special">}</phrase>
7971</programlisting>
7972        <para>
7973          <bridgehead renderas="sect4" id="class_unbuffered_channel_bridgehead">
7974  <phrase id="class_unbuffered_channel"/>
7975  <link linkend="class_unbuffered_channel">Template
7976          <code>unbuffered_channel&lt;&gt;</code></link>
7977</bridgehead>
7978        </para>
7979<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>
7980
7981<phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase>
7982<phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase>
7983
7984<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>
7985<phrase role="keyword">class</phrase> <phrase role="identifier">unbuffered_channel</phrase> <phrase role="special">{</phrase>
7986<phrase role="keyword">public</phrase><phrase role="special">:</phrase>
7987    <phrase role="keyword">typedef</phrase> <phrase role="identifier">T</phrase>   <phrase role="identifier">value_type</phrase><phrase role="special">;</phrase>
7988
7989    <phrase role="keyword">class</phrase> <phrase role="identifier">iterator</phrase><phrase role="special">;</phrase>
7990
7991    <phrase role="identifier">unbuffered_channel</phrase><phrase role="special">();</phrase>
7992
7993    <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>
7994    <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>
7995
7996    <phrase role="keyword">void</phrase> <phrase role="identifier">close</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
7997
7998    <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>
7999    <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>
8000    <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>
8001    <phrase role="identifier">channel_op_status</phrase> <phrase role="identifier">push_wait_for</phrase><phrase role="special">(</phrase>
8002        <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>
8003        <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>
8004    <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>
8005        <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>
8006    <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>
8007    <phrase role="identifier">channel_op_status</phrase> <phrase role="identifier">push_wait_until</phrase><phrase role="special">(</phrase>
8008        <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>
8009        <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>
8010    <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>
8011    <phrase role="identifier">channel_op_status</phrase> <phrase role="identifier">push_wait_until</phrase><phrase role="special">(</phrase>
8012        <phrase role="identifier">value_type</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="identifier">va</phrase><phrase role="special">,</phrase>
8013        <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>
8014
8015    <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>
8016    <phrase role="identifier">value_type</phrase> <phrase role="identifier">value_pop</phrase><phrase role="special">();</phrase>
8017    <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>
8018    <phrase role="identifier">channel_op_status</phrase> <phrase role="identifier">pop_wait_for</phrase><phrase role="special">(</phrase>
8019        <phrase role="identifier">value_type</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">va</phrase><phrase role="special">,</phrase>
8020        <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>
8021    <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>
8022    <phrase role="identifier">channel_op_status</phrase> <phrase role="identifier">pop_wait_until</phrase><phrase role="special">(</phrase>
8023        <phrase role="identifier">value_type</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">va</phrase><phrase role="special">,</phrase>
8024        <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>
8025<phrase role="special">};</phrase>
8026
8027<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>
8028<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>
8029
8030<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>
8031<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>
8032
8033<phrase role="special">}}</phrase>
8034</programlisting>
8035        <bridgehead renderas="sect5" id="fiber.synchronization.channels.unbuffered_channel.h0">
8036          <phrase id="fiber.synchronization.channels.unbuffered_channel.constructor"/><link
8037          linkend="fiber.synchronization.channels.unbuffered_channel.constructor">Constructor</link>
8038        </bridgehead>
8039<programlisting><phrase role="identifier">unbuffered_channel</phrase><phrase role="special">();</phrase>
8040</programlisting>
8041        <variablelist>
8042          <title></title>
8043          <varlistentry>
8044            <term>Effects:</term>
8045            <listitem>
8046              <para>
8047                The constructor constructs an object of class <code><phrase role="identifier">unbuffered_channel</phrase></code>.
8048              </para>
8049            </listitem>
8050          </varlistentry>
8051        </variablelist>
8052        <para>
8053          <bridgehead renderas="sect4" id="unbuffered_channel_close_bridgehead">
8054  <phrase id="unbuffered_channel_close"/>
8055  <link linkend="unbuffered_channel_close">Member
8056          function <code>close</code>()</link>
8057</bridgehead>
8058        </para>
8059<programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">close</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
8060</programlisting>
8061        <variablelist>
8062          <title></title>
8063          <varlistentry>
8064            <term>Effects:</term>
8065            <listitem>
8066              <para>
8067                Deactivates the channel. No values can be put after calling <code><phrase
8068                role="keyword">this</phrase><phrase role="special">-&gt;</phrase><phrase
8069                role="identifier">close</phrase><phrase role="special">()</phrase></code>.
8070                Fibers blocked in <code><phrase role="keyword">this</phrase><phrase
8071                role="special">-&gt;</phrase><phrase role="identifier">pop</phrase><phrase
8072                role="special">()</phrase></code>, <code><phrase role="keyword">this</phrase><phrase
8073                role="special">-&gt;</phrase><phrase role="identifier">pop_wait_for</phrase><phrase
8074                role="special">()</phrase></code> or <code><phrase role="keyword">this</phrase><phrase
8075                role="special">-&gt;</phrase><phrase role="identifier">pop_wait_until</phrase><phrase
8076                role="special">()</phrase></code> will return <code><phrase role="identifier">closed</phrase></code>.
8077                Fibers blocked in <code><phrase role="keyword">this</phrase><phrase
8078                role="special">-&gt;</phrase><phrase role="identifier">value_pop</phrase><phrase
8079                role="special">()</phrase></code> will receive an exception.
8080              </para>
8081            </listitem>
8082          </varlistentry>
8083          <varlistentry>
8084            <term>Throws:</term>
8085            <listitem>
8086              <para>
8087                Nothing.
8088              </para>
8089            </listitem>
8090          </varlistentry>
8091          <varlistentry>
8092            <term>Note:</term>
8093            <listitem>
8094              <para>
8095                <code><phrase role="identifier">close</phrase><phrase role="special">()</phrase></code>
8096                is like closing a pipe. It informs waiting consumers that no more
8097                values will arrive.
8098              </para>
8099            </listitem>
8100          </varlistentry>
8101        </variablelist>
8102        <para>
8103          <bridgehead renderas="sect4" id="unbuffered_channel_push_bridgehead">
8104  <phrase id="unbuffered_channel_push"/>
8105  <link linkend="unbuffered_channel_push">Member
8106          function <code>push</code>()</link>
8107</bridgehead>
8108        </para>
8109<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>
8110<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>
8111</programlisting>
8112        <variablelist>
8113          <title></title>
8114          <varlistentry>
8115            <term>Effects:</term>
8116            <listitem>
8117              <para>
8118                If channel is closed, returns <code><phrase role="identifier">closed</phrase></code>.
8119                Otherwise enqueues the value in the channel, wakes up a fiber blocked
8120                on <code><phrase role="keyword">this</phrase><phrase role="special">-&gt;</phrase><phrase
8121                role="identifier">pop</phrase><phrase role="special">()</phrase></code>,
8122                <code><phrase role="keyword">this</phrase><phrase role="special">-&gt;</phrase><phrase
8123                role="identifier">value_pop</phrase><phrase role="special">()</phrase></code>,
8124                <code><phrase role="keyword">this</phrase><phrase role="special">-&gt;</phrase><phrase
8125                role="identifier">pop_wait_for</phrase><phrase role="special">()</phrase></code>
8126                or <code><phrase role="keyword">this</phrase><phrase role="special">-&gt;</phrase><phrase
8127                role="identifier">pop_wait_until</phrase><phrase role="special">()</phrase></code>
8128                and returns <code><phrase role="identifier">success</phrase></code>.
8129              </para>
8130            </listitem>
8131          </varlistentry>
8132          <varlistentry>
8133            <term>Throws:</term>
8134            <listitem>
8135              <para>
8136                Exceptions thrown by copy- or move-operations.
8137              </para>
8138            </listitem>
8139          </varlistentry>
8140        </variablelist>
8141        <para>
8142          <bridgehead renderas="sect4" id="unbuffered_channel_pop_bridgehead">
8143  <phrase id="unbuffered_channel_pop"/>
8144  <link linkend="unbuffered_channel_pop">Member
8145          function <code>pop</code>()</link>
8146</bridgehead>
8147        </para>
8148<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>
8149</programlisting>
8150        <variablelist>
8151          <title></title>
8152          <varlistentry>
8153            <term>Effects:</term>
8154            <listitem>
8155              <para>
8156                Dequeues a value from the channel. If the channel is empty, the fiber
8157                gets suspended until at least one new item is <code><phrase role="identifier">push</phrase><phrase
8158                role="special">()</phrase></code>ed (return value <code><phrase role="identifier">success</phrase></code>
8159                and <code><phrase role="identifier">va</phrase></code> contains dequeued
8160                value) or the channel gets <code><phrase role="identifier">close</phrase><phrase
8161                role="special">()</phrase></code>d (return value <code><phrase role="identifier">closed</phrase></code>).
8162              </para>
8163            </listitem>
8164          </varlistentry>
8165          <varlistentry>
8166            <term>Throws:</term>
8167            <listitem>
8168              <para>
8169                Exceptions thrown by copy- or move-operations.
8170              </para>
8171            </listitem>
8172          </varlistentry>
8173        </variablelist>
8174        <para>
8175          <bridgehead renderas="sect4" id="unbuffered_channel_value_pop_bridgehead">
8176  <phrase id="unbuffered_channel_value_pop"/>
8177  <link linkend="unbuffered_channel_value_pop">Member
8178          function <code>value_pop</code>()</link>
8179</bridgehead>
8180        </para>
8181<programlisting><phrase role="identifier">value_type</phrase> <phrase role="identifier">value_pop</phrase><phrase role="special">();</phrase>
8182</programlisting>
8183        <variablelist>
8184          <title></title>
8185          <varlistentry>
8186            <term>Effects:</term>
8187            <listitem>
8188              <para>
8189                Dequeues a value from the channel. If the channel is empty, the fiber
8190                gets suspended until at least one new item is <code><phrase role="identifier">push</phrase><phrase
8191                role="special">()</phrase></code>ed or the channel gets <code><phrase
8192                role="identifier">close</phrase><phrase role="special">()</phrase></code>d
8193                (which throws an exception).
8194              </para>
8195            </listitem>
8196          </varlistentry>
8197          <varlistentry>
8198            <term>Throws:</term>
8199            <listitem>
8200              <para>
8201                <code><phrase role="identifier">fiber_error</phrase></code> if <code><phrase
8202                role="special">*</phrase><phrase role="keyword">this</phrase></code>
8203                is closed or by copy- or move-operations.
8204              </para>
8205            </listitem>
8206          </varlistentry>
8207          <varlistentry>
8208            <term>Error conditions:</term>
8209            <listitem>
8210              <para>
8211                <code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase
8212                role="identifier">errc</phrase><phrase role="special">::</phrase><phrase
8213                role="identifier">operation_not_permitted</phrase></code>
8214              </para>
8215            </listitem>
8216          </varlistentry>
8217        </variablelist>
8218        <para>
8219          <bridgehead renderas="sect4" id="unbuffered_channel_pop_wait_for_bridgehead">
8220  <phrase id="unbuffered_channel_pop_wait_for"/>
8221  <link linkend="unbuffered_channel_pop_wait_for">Member
8222          function <code>pop_wait_for</code>()</link>
8223</bridgehead>
8224        </para>
8225<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>
8226<phrase role="identifier">channel_op_status</phrase> <phrase role="identifier">pop_wait_for</phrase><phrase role="special">(</phrase>
8227    <phrase role="identifier">value_type</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">va</phrase><phrase role="special">,</phrase>
8228    <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>
8229</programlisting>
8230        <variablelist>
8231          <title></title>
8232          <varlistentry>
8233            <term>Effects:</term>
8234            <listitem>
8235              <para>
8236                Accepts <code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase
8237                role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase
8238                role="identifier">duration</phrase></code> and internally computes
8239                a timeout time as (system time + <code><phrase role="identifier">timeout_duration</phrase></code>).
8240                If channel is not empty, immediately dequeues a value from the channel.
8241                Otherwise the fiber gets suspended until at least one new item is
8242                <code><phrase role="identifier">push</phrase><phrase role="special">()</phrase></code>ed
8243                (return value <code><phrase role="identifier">success</phrase></code>
8244                and <code><phrase role="identifier">va</phrase></code> contains dequeued
8245                value), or the channel gets <code><phrase role="identifier">close</phrase><phrase
8246                role="special">()</phrase></code>d (return value <code><phrase role="identifier">closed</phrase></code>),
8247                or the system time reaches the computed timeout time (return value
8248                <code><phrase role="identifier">timeout</phrase></code>).
8249              </para>
8250            </listitem>
8251          </varlistentry>
8252          <varlistentry>
8253            <term>Throws:</term>
8254            <listitem>
8255              <para>
8256                timeout-related exceptions or by copy- or move-operations.
8257              </para>
8258            </listitem>
8259          </varlistentry>
8260        </variablelist>
8261        <para>
8262          <bridgehead renderas="sect4" id="unbuffered_channel_pop_wait_until_bridgehead">
8263  <phrase id="unbuffered_channel_pop_wait_until"/>
8264  <link linkend="unbuffered_channel_pop_wait_until">Member
8265          function <code>pop_wait_until</code>()</link>
8266</bridgehead>
8267        </para>
8268<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>
8269<phrase role="identifier">channel_op_status</phrase> <phrase role="identifier">pop_wait_until</phrase><phrase role="special">(</phrase>
8270    <phrase role="identifier">value_type</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">va</phrase><phrase role="special">,</phrase>
8271    <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>
8272</programlisting>
8273        <variablelist>
8274          <title></title>
8275          <varlistentry>
8276            <term>Effects:</term>
8277            <listitem>
8278              <para>
8279                Accepts a <code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase
8280                role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase
8281                role="identifier">time_point</phrase><phrase role="special">&lt;</phrase>
8282                <phrase role="identifier">Clock</phrase><phrase role="special">,</phrase>
8283                <phrase role="identifier">Duration</phrase> <phrase role="special">&gt;</phrase></code>.
8284                If channel is not empty, immediately dequeues a value from the channel.
8285                Otherwise the fiber gets suspended until at least one new item is
8286                <code><phrase role="identifier">push</phrase><phrase role="special">()</phrase></code>ed
8287                (return value <code><phrase role="identifier">success</phrase></code>
8288                and <code><phrase role="identifier">va</phrase></code> contains dequeued
8289                value), or the channel gets <code><phrase role="identifier">close</phrase><phrase
8290                role="special">()</phrase></code>d (return value <code><phrase role="identifier">closed</phrase></code>),
8291                or the system time reaches the passed <code><phrase role="identifier">time_point</phrase></code>
8292                (return value <code><phrase role="identifier">timeout</phrase></code>).
8293              </para>
8294            </listitem>
8295          </varlistentry>
8296          <varlistentry>
8297            <term>Throws:</term>
8298            <listitem>
8299              <para>
8300                timeout-related exceptions or by copy- or move-operations.
8301              </para>
8302            </listitem>
8303          </varlistentry>
8304        </variablelist>
8305        <bridgehead renderas="sect5" id="fiber.synchronization.channels.unbuffered_channel.h1">
8306          <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
8307          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
8308          function <code><phrase role="identifier">begin</phrase><phrase role="special">(</phrase>
8309          <phrase role="identifier">unbuffered_channel</phrase><phrase role="special">&lt;</phrase>
8310          <phrase role="identifier">T</phrase> <phrase role="special">&gt;</phrase>
8311          <phrase role="special">&amp;)</phrase></code></link>
8312        </bridgehead>
8313<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>
8314<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>
8315</programlisting>
8316        <variablelist>
8317          <title></title>
8318          <varlistentry>
8319            <term>Returns:</term>
8320            <listitem>
8321              <para>
8322                Returns a range-iterator (input-iterator).
8323              </para>
8324            </listitem>
8325          </varlistentry>
8326        </variablelist>
8327        <bridgehead renderas="sect5" id="fiber.synchronization.channels.unbuffered_channel.h2">
8328          <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
8329          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
8330          function <code><phrase role="identifier">end</phrase><phrase role="special">(</phrase>
8331          <phrase role="identifier">unbuffered_channel</phrase><phrase role="special">&lt;</phrase>
8332          <phrase role="identifier">T</phrase> <phrase role="special">&gt;</phrase>
8333          <phrase role="special">&amp;)</phrase></code></link>
8334        </bridgehead>
8335<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>
8336<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>
8337</programlisting>
8338        <variablelist>
8339          <title></title>
8340          <varlistentry>
8341            <term>Returns:</term>
8342            <listitem>
8343              <para>
8344                Returns an end range-iterator (input-iterator).
8345              </para>
8346            </listitem>
8347          </varlistentry>
8348        </variablelist>
8349      </section>
8350    </section>
8351    <section id="fiber.synchronization.futures">
8352      <title><link linkend="fiber.synchronization.futures">Futures</link></title>
8353      <bridgehead renderas="sect4" id="fiber.synchronization.futures.h0">
8354        <phrase id="fiber.synchronization.futures.overview"/><link linkend="fiber.synchronization.futures.overview">Overview</link>
8355      </bridgehead>
8356      <para>
8357        The futures library provides a means of handling asynchronous future values,
8358        whether those values are generated by another fiber, or on a single fiber
8359        in response to external stimuli, or on-demand.
8360      </para>
8361      <para>
8362        This is done through the provision of four class templates: <link linkend="class_future"><code>future&lt;&gt;</code></link> and
8363        <link linkend="class_shared_future"><code>shared_future&lt;&gt;</code></link> which are used to retrieve the asynchronous
8364        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
8365        are used to generate the asynchronous results.
8366      </para>
8367      <para>
8368        An instance of <link linkend="class_future"><code>future&lt;&gt;</code></link> holds the one and only reference
8369        to a result. Ownership can be transferred between instances using the move
8370        constructor or move-assignment operator, but at most one instance holds a
8371        reference to a given asynchronous result. When the result is ready, it is
8372        returned from <link linkend="future_get"><code>future::get()</code></link> by rvalue-reference to allow the result
8373        to be moved or copied as appropriate for the type.
8374      </para>
8375      <para>
8376        On the other hand, many instances of <link linkend="class_shared_future"><code>shared_future&lt;&gt;</code></link> may
8377        reference the same result. Instances can be freely copied and assigned, and
8378        <link linkend="shared_future_get"><code>shared_future::get()</code></link>
8379returns a <code><phrase role="keyword">const</phrase></code>
8380        reference so that multiple calls to <link linkend="shared_future_get"><code>shared_future::get()</code></link>
8381are
8382        safe. You can move an instance of <link linkend="class_future"><code>future&lt;&gt;</code></link> into an instance
8383        of <link linkend="class_shared_future"><code>shared_future&lt;&gt;</code></link>, thus transferring ownership
8384        of the associated asynchronous result, but not vice-versa.
8385      </para>
8386      <para>
8387        <link linkend="fibers_async"><code>fibers::async()</code></link> is a simple way of running asynchronous tasks.
8388        A call to <code><phrase role="identifier">async</phrase><phrase role="special">()</phrase></code>
8389        spawns a fiber and returns a <link linkend="class_future"><code>future&lt;&gt;</code></link> that will deliver
8390        the result of the fiber function.
8391      </para>
8392      <bridgehead renderas="sect4" id="fiber.synchronization.futures.h1">
8393        <phrase id="fiber.synchronization.futures.creating_asynchronous_values"/><link
8394        linkend="fiber.synchronization.futures.creating_asynchronous_values">Creating
8395        asynchronous values</link>
8396      </bridgehead>
8397      <para>
8398        You can set the value in a future with either a <link linkend="class_promise"><code>promise&lt;&gt;</code></link> or
8399        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
8400        a callable object with <code><phrase role="keyword">void</phrase></code>
8401        return that wraps a function or callable object returning the specified type.
8402        When the <link linkend="class_packaged_task"><code>packaged_task&lt;&gt;</code></link> is invoked, it invokes the
8403        contained function in turn, and populates a future with the contained function's
8404        return value. This is an answer to the perennial question: <quote>How do
8405        I return a value from a fiber?</quote> Package the function you wish to run
8406        as a <link linkend="class_packaged_task"><code>packaged_task&lt;&gt;</code></link> and pass the packaged task to
8407        the fiber constructor. The future retrieved from the packaged task can then
8408        be used to obtain the return value. If the function throws an exception,
8409        that is stored in the future in place of the return value.
8410      </para>
8411<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>
8412    <phrase role="keyword">return</phrase> <phrase role="number">42</phrase><phrase role="special">;</phrase>
8413<phrase role="special">}</phrase>
8414
8415<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>
8416<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>
8417<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>
8418
8419<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>
8420
8421<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>
8422<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>
8423<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>
8424<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>
8425</programlisting>
8426      <para>
8427        A <link linkend="class_promise"><code>promise&lt;&gt;</code></link> is a bit more low level: it just provides explicit
8428        functions to store a value or an exception in the associated future. A promise
8429        can therefore be used where the value might come from more than one possible
8430        source.
8431      </para>
8432<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>
8433<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>
8434<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>
8435
8436<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>
8437
8438<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>
8439<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>
8440<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>
8441<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>
8442</programlisting>
8443      <section id="fiber.synchronization.futures.future">
8444        <title><link linkend="fiber.synchronization.futures.future">Future</link></title>
8445        <para>
8446          A future provides a mechanism to access the result of an asynchronous operation.
8447        </para>
8448        <anchor id="shared_state"/>
8449        <bridgehead renderas="sect5" id="fiber.synchronization.futures.future.h0">
8450          <phrase id="fiber.synchronization.futures.future.shared_state"/><link linkend="fiber.synchronization.futures.future.shared_state">shared
8451          state</link>
8452        </bridgehead>
8453        <para>
8454          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
8455          an unspecified object called their <emphasis>shared state</emphasis>. The
8456          shared state is what will actually hold the async result (or the exception).
8457        </para>
8458        <para>
8459          The shared state is instantiated along with the <link linkend="class_promise"><code>promise&lt;&gt;</code></link>.
8460        </para>
8461        <para>
8462          Aside from its originating <code><phrase role="identifier">promise</phrase><phrase
8463          role="special">&lt;&gt;</phrase></code>, a <link linkend="class_future"><code>future&lt;&gt;</code></link> holds
8464          a unique reference to a particular shared state. However, multiple <link linkend="class_shared_future"><code>shared_future&lt;&gt;</code></link> instances
8465          can reference the same underlying shared state.
8466        </para>
8467        <para>
8468          As <link linkend="class_packaged_task"><code>packaged_task&lt;&gt;</code></link> and <link linkend="fibers_async"><code>fibers::async()</code></link> are
8469          implemented using <link linkend="class_promise"><code>promise&lt;&gt;</code></link>, discussions of shared state
8470          apply to them as well.
8471        </para>
8472        <anchor id="class_future_status"/>
8473        <bridgehead renderas="sect5" id="fiber.synchronization.futures.future.h1">
8474          <phrase id="fiber.synchronization.futures.future.enumeration__code__phrase_role__identifier__future_status__phrase___code_"/><link
8475          linkend="fiber.synchronization.futures.future.enumeration__code__phrase_role__identifier__future_status__phrase___code_">Enumeration
8476          <code><phrase role="identifier">future_status</phrase></code></link>
8477        </bridgehead>
8478        <para>
8479          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>)
8480          return the state of the future.
8481        </para>
8482<programlisting><phrase role="keyword">enum</phrase> <phrase role="keyword">class</phrase> <phrase role="identifier">future_status</phrase> <phrase role="special">{</phrase>
8483    <phrase role="identifier">ready</phrase><phrase role="special">,</phrase>
8484    <phrase role="identifier">timeout</phrase><phrase role="special">,</phrase>
8485    <phrase role="identifier">deferred</phrase>  <phrase role="comment">// not supported yet</phrase>
8486<phrase role="special">};</phrase>
8487</programlisting>
8488        <bridgehead renderas="sect5" id="fiber.synchronization.futures.future.h2">
8489          <phrase id="fiber.synchronization.futures.future._code__phrase_role__identifier__ready__phrase___code_"/><link
8490          linkend="fiber.synchronization.futures.future._code__phrase_role__identifier__ready__phrase___code_"><code><phrase
8491          role="identifier">ready</phrase></code></link>
8492        </bridgehead>
8493        <variablelist>
8494          <title></title>
8495          <varlistentry>
8496            <term>Effects:</term>
8497            <listitem>
8498              <para>
8499                The <link linkend="shared_state">shared state</link> is ready.
8500              </para>
8501            </listitem>
8502          </varlistentry>
8503        </variablelist>
8504        <bridgehead renderas="sect5" id="fiber.synchronization.futures.future.h3">
8505          <phrase id="fiber.synchronization.futures.future._code__phrase_role__identifier__timeout__phrase___code_"/><link
8506          linkend="fiber.synchronization.futures.future._code__phrase_role__identifier__timeout__phrase___code_"><code><phrase
8507          role="identifier">timeout</phrase></code></link>
8508        </bridgehead>
8509        <variablelist>
8510          <title></title>
8511          <varlistentry>
8512            <term>Effects:</term>
8513            <listitem>
8514              <para>
8515                The <link linkend="shared_state">shared state</link> did not become
8516                ready before timeout has passed.
8517              </para>
8518            </listitem>
8519          </varlistentry>
8520        </variablelist>
8521        <note>
8522          <para>
8523            Deferred futures are not supported.
8524          </para>
8525        </note>
8526        <para>
8527          <bridgehead renderas="sect4" id="class_future_bridgehead">
8528  <phrase id="class_future"/>
8529  <link linkend="class_future">Template <code>future&lt;&gt;</code></link>
8530</bridgehead>
8531        </para>
8532        <para>
8533          A <link linkend="class_future"><code>future&lt;&gt;</code></link> contains a <link linkend="shared_state">shared
8534          state</link> which is not shared with any other future.
8535        </para>
8536<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>
8537
8538<phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase>
8539<phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase>
8540
8541<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>
8542<phrase role="keyword">class</phrase> <phrase role="identifier">future</phrase> <phrase role="special">{</phrase>
8543<phrase role="keyword">public</phrase><phrase role="special">:</phrase>
8544    <phrase role="identifier">future</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
8545
8546    <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>
8547
8548    <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>
8549
8550    <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>
8551
8552    <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>
8553
8554    <phrase role="special">~</phrase><phrase role="identifier">future</phrase><phrase role="special">();</phrase>
8555
8556    <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>
8557
8558    <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>
8559
8560    <phrase role="identifier">R</phrase> <phrase role="identifier">get</phrase><phrase role="special">();</phrase>    <phrase role="comment">// member only of generic future template</phrase>
8561    <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>
8562    <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>
8563
8564    <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>
8565
8566    <phrase role="keyword">void</phrase> <phrase role="identifier">wait</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
8567
8568    <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>
8569    <phrase role="identifier">future_status</phrase> <phrase role="identifier">wait_for</phrase><phrase role="special">(</phrase>
8570        <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>
8571
8572    <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>
8573    <phrase role="identifier">future_status</phrase> <phrase role="identifier">wait_until</phrase><phrase role="special">(</phrase>
8574        <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>
8575<phrase role="special">};</phrase>
8576
8577<phrase role="special">}}</phrase>
8578</programlisting>
8579        <bridgehead renderas="sect5" id="fiber.synchronization.futures.future.h4">
8580          <phrase id="fiber.synchronization.futures.future.default_constructor"/><link
8581          linkend="fiber.synchronization.futures.future.default_constructor">Default
8582          constructor</link>
8583        </bridgehead>
8584<programlisting><phrase role="identifier">future</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
8585</programlisting>
8586        <variablelist>
8587          <title></title>
8588          <varlistentry>
8589            <term>Effects:</term>
8590            <listitem>
8591              <para>
8592                Creates a future with no <link linkend="shared_state">shared state</link>.
8593                After construction <code><phrase role="keyword">false</phrase> <phrase
8594                role="special">==</phrase> <phrase role="identifier">valid</phrase><phrase
8595                role="special">()</phrase></code>.
8596              </para>
8597            </listitem>
8598          </varlistentry>
8599          <varlistentry>
8600            <term>Throws:</term>
8601            <listitem>
8602              <para>
8603                Nothing.
8604              </para>
8605            </listitem>
8606          </varlistentry>
8607        </variablelist>
8608        <bridgehead renderas="sect5" id="fiber.synchronization.futures.future.h5">
8609          <phrase id="fiber.synchronization.futures.future.move_constructor"/><link
8610          linkend="fiber.synchronization.futures.future.move_constructor">Move constructor</link>
8611        </bridgehead>
8612<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>
8613</programlisting>
8614        <variablelist>
8615          <title></title>
8616          <varlistentry>
8617            <term>Effects:</term>
8618            <listitem>
8619              <para>
8620                Constructs a future with the <link linkend="shared_state">shared
8621                state</link> of other. After construction <code><phrase role="keyword">false</phrase>
8622                <phrase role="special">==</phrase> <phrase role="identifier">other</phrase><phrase
8623                role="special">.</phrase><phrase role="identifier">valid</phrase><phrase
8624                role="special">()</phrase></code>.
8625              </para>
8626            </listitem>
8627          </varlistentry>
8628          <varlistentry>
8629            <term>Throws:</term>
8630            <listitem>
8631              <para>
8632                Nothing.
8633              </para>
8634            </listitem>
8635          </varlistentry>
8636        </variablelist>
8637        <bridgehead renderas="sect5" id="fiber.synchronization.futures.future.h6">
8638          <phrase id="fiber.synchronization.futures.future.destructor"/><link linkend="fiber.synchronization.futures.future.destructor">Destructor</link>
8639        </bridgehead>
8640<programlisting><phrase role="special">~</phrase><phrase role="identifier">future</phrase><phrase role="special">();</phrase>
8641</programlisting>
8642        <variablelist>
8643          <title></title>
8644          <varlistentry>
8645            <term>Effects:</term>
8646            <listitem>
8647              <para>
8648                Destroys the future; ownership is abandoned.
8649              </para>
8650            </listitem>
8651          </varlistentry>
8652          <varlistentry>
8653            <term>Note:</term>
8654            <listitem>
8655              <para>
8656                <code>~future()</code> does <emphasis>not</emphasis> block the calling fiber.
8657              </para>
8658            </listitem>
8659          </varlistentry>
8660        </variablelist>
8661        <para>
8662          Consider a sequence such as:
8663        </para>
8664        <orderedlist>
8665          <listitem>
8666            <simpara>
8667              instantiate <link linkend="class_promise"><code>promise&lt;&gt;</code></link>
8668            </simpara>
8669          </listitem>
8670          <listitem>
8671            <simpara>
8672              obtain its <code><phrase role="identifier">future</phrase><phrase role="special">&lt;&gt;</phrase></code>
8673              via <link linkend="promise_get_future"><code>promise::get_future()</code></link>
8674            </simpara>
8675          </listitem>
8676          <listitem>
8677            <simpara>
8678              launch <link linkend="class_fiber"><code>fiber</code></link>, capturing <code><phrase role="identifier">promise</phrase><phrase
8679              role="special">&lt;&gt;</phrase></code>
8680            </simpara>
8681          </listitem>
8682          <listitem>
8683            <simpara>
8684              destroy <code><phrase role="identifier">future</phrase><phrase role="special">&lt;&gt;</phrase></code>
8685            </simpara>
8686          </listitem>
8687          <listitem>
8688            <simpara>
8689              call <link linkend="promise_set_value"><code>promise::set_value()</code></link>
8690            </simpara>
8691          </listitem>
8692        </orderedlist>
8693        <para>
8694          The final <code><phrase role="identifier">set_value</phrase><phrase role="special">()</phrase></code>
8695          call succeeds, but the value is silently discarded: no additional <code><phrase
8696          role="identifier">future</phrase><phrase role="special">&lt;&gt;</phrase></code>
8697          can be obtained from that <code><phrase role="identifier">promise</phrase><phrase
8698          role="special">&lt;&gt;</phrase></code>.
8699        </para>
8700        <para>
8701          <bridgehead renderas="sect4" id="future_operator_assign_bridgehead">
8702  <phrase id="future_operator_assign"/>
8703  <link linkend="future_operator_assign">Member
8704          function <code>operator=</code>()</link>
8705</bridgehead>
8706        </para>
8707<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>
8708</programlisting>
8709        <variablelist>
8710          <title></title>
8711          <varlistentry>
8712            <term>Effects:</term>
8713            <listitem>
8714              <para>
8715                Moves the <link linkend="shared_state">shared state</link> of other
8716                to <code><phrase role="keyword">this</phrase></code>. After the assignment,
8717                <code><phrase role="keyword">false</phrase> <phrase role="special">==</phrase>
8718                <phrase role="identifier">other</phrase><phrase role="special">.</phrase><phrase
8719                role="identifier">valid</phrase><phrase role="special">()</phrase></code>.
8720              </para>
8721            </listitem>
8722          </varlistentry>
8723          <varlistentry>
8724            <term>Throws:</term>
8725            <listitem>
8726              <para>
8727                Nothing.
8728              </para>
8729            </listitem>
8730          </varlistentry>
8731        </variablelist>
8732        <para>
8733          <bridgehead renderas="sect4" id="future_valid_bridgehead">
8734  <phrase id="future_valid"/>
8735  <link linkend="future_valid">Member function <code>valid</code>()</link>
8736</bridgehead>
8737        </para>
8738<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>
8739</programlisting>
8740        <variablelist>
8741          <title></title>
8742          <varlistentry>
8743            <term>Effects:</term>
8744            <listitem>
8745              <para>
8746                Returns <code><phrase role="keyword">true</phrase></code> if future
8747                contains a <link linkend="shared_state">shared state</link>.
8748              </para>
8749            </listitem>
8750          </varlistentry>
8751          <varlistentry>
8752            <term>Throws:</term>
8753            <listitem>
8754              <para>
8755                Nothing.
8756              </para>
8757            </listitem>
8758          </varlistentry>
8759        </variablelist>
8760        <para>
8761          <bridgehead renderas="sect4" id="future_share_bridgehead">
8762  <phrase id="future_share"/>
8763  <link linkend="future_share">Member function <code>share</code>()</link>
8764</bridgehead>
8765        </para>
8766<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>
8767</programlisting>
8768        <variablelist>
8769          <title></title>
8770          <varlistentry>
8771            <term>Effects:</term>
8772            <listitem>
8773              <para>
8774                Move the state to a <link linkend="class_shared_future"><code>shared_future&lt;&gt;</code></link>.
8775              </para>
8776            </listitem>
8777          </varlistentry>
8778          <varlistentry>
8779            <term>Returns:</term>
8780            <listitem>
8781              <para>
8782                a <link linkend="class_shared_future"><code>shared_future&lt;&gt;</code></link> containing the <link linkend="shared_state">shared
8783                state</link> formerly belonging to <code><phrase role="special">*</phrase><phrase
8784                role="keyword">this</phrase></code>.
8785              </para>
8786            </listitem>
8787          </varlistentry>
8788          <varlistentry>
8789            <term>Postcondition:</term>
8790            <listitem>
8791              <para>
8792                <code><phrase role="keyword">false</phrase> <phrase role="special">==</phrase>
8793                <phrase role="identifier">valid</phrase><phrase role="special">()</phrase></code>
8794              </para>
8795            </listitem>
8796          </varlistentry>
8797          <varlistentry>
8798            <term>Throws:</term>
8799            <listitem>
8800              <para>
8801                <code><phrase role="identifier">future_error</phrase></code> with
8802                error condition <code><phrase role="identifier">future_errc</phrase><phrase
8803                role="special">::</phrase><phrase role="identifier">no_state</phrase></code>.
8804              </para>
8805            </listitem>
8806          </varlistentry>
8807        </variablelist>
8808        <para>
8809          <bridgehead renderas="sect4" id="future_get_bridgehead">
8810  <phrase id="future_get"/>
8811  <link linkend="future_get">Member function <code>get</code>()</link>
8812</bridgehead>
8813        </para>
8814<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>
8815<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>
8816<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>
8817</programlisting>
8818        <variablelist>
8819          <title></title>
8820          <varlistentry>
8821            <term>Precondition:</term>
8822            <listitem>
8823              <para>
8824                <code><phrase role="keyword">true</phrase> <phrase role="special">==</phrase>
8825                <phrase role="identifier">valid</phrase><phrase role="special">()</phrase></code>
8826              </para>
8827            </listitem>
8828          </varlistentry>
8829          <varlistentry>
8830            <term>Returns:</term>
8831            <listitem>
8832              <para>
8833                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
8834                called. If <link linkend="promise_set_value"><code>promise::set_value()</code></link> is called, returns
8835                the value. If <link linkend="promise_set_exception"><code>promise::set_exception()</code></link> is called,
8836                throws the indicated exception.
8837              </para>
8838            </listitem>
8839          </varlistentry>
8840          <varlistentry>
8841            <term>Postcondition:</term>
8842            <listitem>
8843              <para>
8844                <code><phrase role="keyword">false</phrase> <phrase role="special">==</phrase>
8845                <phrase role="identifier">valid</phrase><phrase role="special">()</phrase></code>
8846              </para>
8847            </listitem>
8848          </varlistentry>
8849          <varlistentry>
8850            <term>Throws:</term>
8851            <listitem>
8852              <para>
8853                <code><phrase role="identifier">future_error</phrase></code> with
8854                error condition <code><phrase role="identifier">future_errc</phrase><phrase
8855                role="special">::</phrase><phrase role="identifier">no_state</phrase></code>,
8856                <code><phrase role="identifier">future_errc</phrase><phrase role="special">::</phrase><phrase
8857                role="identifier">broken_promise</phrase></code>. Any exception passed
8858                to <code><phrase role="identifier">promise</phrase><phrase role="special">::</phrase><phrase
8859                role="identifier">set_exception</phrase><phrase role="special">()</phrase></code>.
8860              </para>
8861            </listitem>
8862          </varlistentry>
8863        </variablelist>
8864        <para>
8865          <bridgehead renderas="sect4" id="future_get_exception_ptr_bridgehead">
8866  <phrase id="future_get_exception_ptr"/>
8867  <link linkend="future_get_exception_ptr">Member
8868          function <code>get_exception_ptr</code>()</link>
8869</bridgehead>
8870        </para>
8871<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>
8872</programlisting>
8873        <variablelist>
8874          <title></title>
8875          <varlistentry>
8876            <term>Precondition:</term>
8877            <listitem>
8878              <para>
8879                <code><phrase role="keyword">true</phrase> <phrase role="special">==</phrase>
8880                <phrase role="identifier">valid</phrase><phrase role="special">()</phrase></code>
8881              </para>
8882            </listitem>
8883          </varlistentry>
8884          <varlistentry>
8885            <term>Returns:</term>
8886            <listitem>
8887              <para>
8888                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
8889                called. If <code><phrase role="identifier">set_value</phrase><phrase
8890                role="special">()</phrase></code> is called, returns a default-constructed
8891                <code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase
8892                role="identifier">exception_ptr</phrase></code>. If <code><phrase
8893                role="identifier">set_exception</phrase><phrase role="special">()</phrase></code>
8894                is called, returns the passed <code><phrase role="identifier">std</phrase><phrase
8895                role="special">::</phrase><phrase role="identifier">exception_ptr</phrase></code>.
8896              </para>
8897            </listitem>
8898          </varlistentry>
8899          <varlistentry>
8900            <term>Throws:</term>
8901            <listitem>
8902              <para>
8903                <code><phrase role="identifier">future_error</phrase></code> with
8904                error condition <code><phrase role="identifier">future_errc</phrase><phrase
8905                role="special">::</phrase><phrase role="identifier">no_state</phrase></code>.
8906              </para>
8907            </listitem>
8908          </varlistentry>
8909          <varlistentry>
8910            <term>Note:</term>
8911            <listitem>
8912              <para>
8913                <code><phrase role="identifier">get_exception_ptr</phrase><phrase
8914                role="special">()</phrase></code> does <emphasis>not</emphasis> invalidate
8915                the <code>future</code>. After calling <code><phrase role="identifier">get_exception_ptr</phrase><phrase
8916                role="special">()</phrase></code>, you may still call <link linkend="future_get"><code>future::get()</code></link>.
8917              </para>
8918            </listitem>
8919          </varlistentry>
8920        </variablelist>
8921        <para>
8922          <bridgehead renderas="sect4" id="future_wait_bridgehead">
8923  <phrase id="future_wait"/>
8924  <link linkend="future_wait">Member function <code>wait</code>()</link>
8925</bridgehead>
8926        </para>
8927<programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">wait</phrase><phrase role="special">();</phrase>
8928</programlisting>
8929        <variablelist>
8930          <title></title>
8931          <varlistentry>
8932            <term>Effects:</term>
8933            <listitem>
8934              <para>
8935                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
8936                called.
8937              </para>
8938            </listitem>
8939          </varlistentry>
8940          <varlistentry>
8941            <term>Throws:</term>
8942            <listitem>
8943              <para>
8944                <code><phrase role="identifier">future_error</phrase></code> with
8945                error condition <code><phrase role="identifier">future_errc</phrase><phrase
8946                role="special">::</phrase><phrase role="identifier">no_state</phrase></code>.
8947              </para>
8948            </listitem>
8949          </varlistentry>
8950        </variablelist>
8951        <para>
8952          <bridgehead renderas="sect4" id="future_wait_for_bridgehead">
8953  <phrase id="future_wait_for"/>
8954  <link linkend="future_wait_for">Templated member
8955          function <code>wait_for</code>()</link>
8956</bridgehead>
8957        </para>
8958<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>
8959<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>
8960</programlisting>
8961        <variablelist>
8962          <title></title>
8963          <varlistentry>
8964            <term>Effects:</term>
8965            <listitem>
8966              <para>
8967                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
8968                called, or <code><phrase role="identifier">timeout_duration</phrase></code>
8969                has passed.
8970              </para>
8971            </listitem>
8972          </varlistentry>
8973          <varlistentry>
8974            <term>Result:</term>
8975            <listitem>
8976              <para>
8977                A <code><phrase role="identifier">future_status</phrase></code> is
8978                returned indicating the reason for returning.
8979              </para>
8980            </listitem>
8981          </varlistentry>
8982          <varlistentry>
8983            <term>Throws:</term>
8984            <listitem>
8985              <para>
8986                <code><phrase role="identifier">future_error</phrase></code> with
8987                error condition <code><phrase role="identifier">future_errc</phrase><phrase
8988                role="special">::</phrase><phrase role="identifier">no_state</phrase></code>
8989                or timeout-related exceptions.
8990              </para>
8991            </listitem>
8992          </varlistentry>
8993        </variablelist>
8994        <para>
8995          <bridgehead renderas="sect4" id="future_wait_until_bridgehead">
8996  <phrase id="future_wait_until"/>
8997  <link linkend="future_wait_until">Templated
8998          member function <code>wait_until</code>()</link>
8999</bridgehead>
9000        </para>
9001<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>
9002<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>
9003</programlisting>
9004        <variablelist>
9005          <title></title>
9006          <varlistentry>
9007            <term>Effects:</term>
9008            <listitem>
9009              <para>
9010                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
9011                called, or <code><phrase role="identifier">timeout_time</phrase></code>
9012                has passed.
9013              </para>
9014            </listitem>
9015          </varlistentry>
9016          <varlistentry>
9017            <term>Result:</term>
9018            <listitem>
9019              <para>
9020                A <code><phrase role="identifier">future_status</phrase></code> is
9021                returned indicating the reason for returning.
9022              </para>
9023            </listitem>
9024          </varlistentry>
9025          <varlistentry>
9026            <term>Throws:</term>
9027            <listitem>
9028              <para>
9029                <code><phrase role="identifier">future_error</phrase></code> with
9030                error condition <code><phrase role="identifier">future_errc</phrase><phrase
9031                role="special">::</phrase><phrase role="identifier">no_state</phrase></code>
9032                or timeout-related exceptions.
9033              </para>
9034            </listitem>
9035          </varlistentry>
9036        </variablelist>
9037        <para>
9038          <bridgehead renderas="sect4" id="class_shared_future_bridgehead">
9039  <phrase id="class_shared_future"/>
9040  <link linkend="class_shared_future">Template
9041          <code>shared_future&lt;&gt;</code></link>
9042</bridgehead>
9043        </para>
9044        <para>
9045          A <link linkend="class_shared_future"><code>shared_future&lt;&gt;</code></link> contains a <link linkend="shared_state">shared
9046          state</link> which might be shared with other <link linkend="class_shared_future"><code>shared_future&lt;&gt;</code></link> instances.
9047        </para>
9048<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>
9049
9050<phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase>
9051<phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase>
9052
9053<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>
9054<phrase role="keyword">class</phrase> <phrase role="identifier">shared_future</phrase> <phrase role="special">{</phrase>
9055<phrase role="keyword">public</phrase><phrase role="special">:</phrase>
9056    <phrase role="identifier">shared_future</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
9057
9058    <phrase role="special">~</phrase><phrase role="identifier">shared_future</phrase><phrase role="special">();</phrase>
9059
9060    <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>
9061
9062    <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>
9063
9064    <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>
9065
9066    <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>
9067
9068    <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>
9069
9070    <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>
9071
9072    <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>
9073
9074    <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>
9075    <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>
9076    <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>
9077
9078    <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>
9079
9080    <phrase role="keyword">void</phrase> <phrase role="identifier">wait</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
9081
9082    <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>
9083    <phrase role="identifier">future_status</phrase> <phrase role="identifier">wait_for</phrase><phrase role="special">(</phrase>
9084        <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>
9085
9086    <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>
9087    <phrase role="identifier">future_status</phrase> <phrase role="identifier">wait_until</phrase><phrase role="special">(</phrase>
9088        <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>
9089<phrase role="special">};</phrase>
9090
9091<phrase role="special">}}</phrase>
9092</programlisting>
9093        <bridgehead renderas="sect5" id="fiber.synchronization.futures.future.h7">
9094          <phrase id="fiber.synchronization.futures.future.default_constructor0"/><link
9095          linkend="fiber.synchronization.futures.future.default_constructor0">Default
9096          constructor</link>
9097        </bridgehead>
9098<programlisting><phrase role="identifier">shared_future</phrase><phrase role="special">();</phrase>
9099</programlisting>
9100        <variablelist>
9101          <title></title>
9102          <varlistentry>
9103            <term>Effects:</term>
9104            <listitem>
9105              <para>
9106                Creates a shared_future with no <link linkend="shared_state">shared
9107                state</link>. After construction <code><phrase role="keyword">false</phrase>
9108                <phrase role="special">==</phrase> <phrase role="identifier">valid</phrase><phrase
9109                role="special">()</phrase></code>.
9110              </para>
9111            </listitem>
9112          </varlistentry>
9113          <varlistentry>
9114            <term>Throws:</term>
9115            <listitem>
9116              <para>
9117                Nothing.
9118              </para>
9119            </listitem>
9120          </varlistentry>
9121        </variablelist>
9122        <bridgehead renderas="sect5" id="fiber.synchronization.futures.future.h8">
9123          <phrase id="fiber.synchronization.futures.future.move_constructor0"/><link
9124          linkend="fiber.synchronization.futures.future.move_constructor0">Move constructor</link>
9125        </bridgehead>
9126<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>
9127<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>
9128</programlisting>
9129        <variablelist>
9130          <title></title>
9131          <varlistentry>
9132            <term>Effects:</term>
9133            <listitem>
9134              <para>
9135                Constructs a shared_future with the <link linkend="shared_state">shared
9136                state</link> of other. After construction <code><phrase role="keyword">false</phrase>
9137                <phrase role="special">==</phrase> <phrase role="identifier">other</phrase><phrase
9138                role="special">.</phrase><phrase role="identifier">valid</phrase><phrase
9139                role="special">()</phrase></code>.
9140              </para>
9141            </listitem>
9142          </varlistentry>
9143          <varlistentry>
9144            <term>Throws:</term>
9145            <listitem>
9146              <para>
9147                Nothing.
9148              </para>
9149            </listitem>
9150          </varlistentry>
9151        </variablelist>
9152        <bridgehead renderas="sect5" id="fiber.synchronization.futures.future.h9">
9153          <phrase id="fiber.synchronization.futures.future.copy_constructor"/><link
9154          linkend="fiber.synchronization.futures.future.copy_constructor">Copy constructor</link>
9155        </bridgehead>
9156<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>
9157</programlisting>
9158        <variablelist>
9159          <title></title>
9160          <varlistentry>
9161            <term>Effects:</term>
9162            <listitem>
9163              <para>
9164                Constructs a shared_future with the <link linkend="shared_state">shared
9165                state</link> of other. After construction <code><phrase role="identifier">other</phrase><phrase
9166                role="special">.</phrase><phrase role="identifier">valid</phrase><phrase
9167                role="special">()</phrase></code> is unchanged.
9168              </para>
9169            </listitem>
9170          </varlistentry>
9171          <varlistentry>
9172            <term>Throws:</term>
9173            <listitem>
9174              <para>
9175                Nothing.
9176              </para>
9177            </listitem>
9178          </varlistentry>
9179        </variablelist>
9180        <bridgehead renderas="sect5" id="fiber.synchronization.futures.future.h10">
9181          <phrase id="fiber.synchronization.futures.future.destructor0"/><link linkend="fiber.synchronization.futures.future.destructor0">Destructor</link>
9182        </bridgehead>
9183<programlisting><phrase role="special">~</phrase><phrase role="identifier">shared_future</phrase><phrase role="special">();</phrase>
9184</programlisting>
9185        <variablelist>
9186          <title></title>
9187          <varlistentry>
9188            <term>Effects:</term>
9189            <listitem>
9190              <para>
9191                Destroys the shared_future; ownership is abandoned if not shared.
9192              </para>
9193            </listitem>
9194          </varlistentry>
9195          <varlistentry>
9196            <term>Note:</term>
9197            <listitem>
9198              <para>
9199                <code>~shared_future()</code> does <emphasis>not</emphasis> block the calling fiber.
9200              </para>
9201            </listitem>
9202          </varlistentry>
9203        </variablelist>
9204        <para>
9205          <bridgehead renderas="sect4" id="shared_future_operator_assign_bridgehead">
9206  <phrase id="shared_future_operator_assign"/>
9207  <link linkend="shared_future_operator_assign">Member
9208          function <code>operator=</code>()</link>
9209</bridgehead>
9210        </para>
9211<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>
9212<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>
9213<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>
9214</programlisting>
9215        <variablelist>
9216          <title></title>
9217          <varlistentry>
9218            <term>Effects:</term>
9219            <listitem>
9220              <para>
9221                Moves or copies the <link linkend="shared_state">shared state</link>
9222                of other to <code><phrase role="keyword">this</phrase></code>. After
9223                the assignment, the state of <code><phrase role="identifier">other</phrase><phrase
9224                role="special">.</phrase><phrase role="identifier">valid</phrase><phrase
9225                role="special">()</phrase></code> depends on which overload was invoked:
9226                unchanged for the overload accepting <code><phrase role="identifier">shared_future</phrase>
9227                <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase></code>,
9228                otherwise <code><phrase role="keyword">false</phrase></code>.
9229              </para>
9230            </listitem>
9231          </varlistentry>
9232          <varlistentry>
9233            <term>Throws:</term>
9234            <listitem>
9235              <para>
9236                Nothing.
9237              </para>
9238            </listitem>
9239          </varlistentry>
9240        </variablelist>
9241        <para>
9242          <bridgehead renderas="sect4" id="shared_future_valid_bridgehead">
9243  <phrase id="shared_future_valid"/>
9244  <link linkend="shared_future_valid">Member
9245          function <code>valid</code>()</link>
9246</bridgehead>
9247        </para>
9248<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>
9249</programlisting>
9250        <variablelist>
9251          <title></title>
9252          <varlistentry>
9253            <term>Effects:</term>
9254            <listitem>
9255              <para>
9256                Returns <code><phrase role="keyword">true</phrase></code> if shared_future
9257                contains a <link linkend="shared_state">shared state</link>.
9258              </para>
9259            </listitem>
9260          </varlistentry>
9261          <varlistentry>
9262            <term>Throws:</term>
9263            <listitem>
9264              <para>
9265                Nothing.
9266              </para>
9267            </listitem>
9268          </varlistentry>
9269        </variablelist>
9270        <para>
9271          <bridgehead renderas="sect4" id="shared_future_get_bridgehead">
9272  <phrase id="shared_future_get"/>
9273  <link linkend="shared_future_get">Member function
9274          <code>get</code>()</link>
9275</bridgehead>
9276        </para>
9277<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>
9278<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>
9279<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>
9280</programlisting>
9281        <variablelist>
9282          <title></title>
9283          <varlistentry>
9284            <term>Precondition:</term>
9285            <listitem>
9286              <para>
9287                <code><phrase role="keyword">true</phrase> <phrase role="special">==</phrase>
9288                <phrase role="identifier">valid</phrase><phrase role="special">()</phrase></code>
9289              </para>
9290            </listitem>
9291          </varlistentry>
9292          <varlistentry>
9293            <term>Returns:</term>
9294            <listitem>
9295              <para>
9296                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
9297                called. If <link linkend="promise_set_value"><code>promise::set_value()</code></link> is called, returns
9298                the value. If <link linkend="promise_set_exception"><code>promise::set_exception()</code></link> is called,
9299                throws the indicated exception.
9300              </para>
9301            </listitem>
9302          </varlistentry>
9303          <varlistentry>
9304            <term>Postcondition:</term>
9305            <listitem>
9306              <para>
9307                <code><phrase role="keyword">false</phrase> <phrase role="special">==</phrase>
9308                <phrase role="identifier">valid</phrase><phrase role="special">()</phrase></code>
9309              </para>
9310            </listitem>
9311          </varlistentry>
9312          <varlistentry>
9313            <term>Throws:</term>
9314            <listitem>
9315              <para>
9316                <code><phrase role="identifier">future_error</phrase></code> with
9317                error condition <code><phrase role="identifier">future_errc</phrase><phrase
9318                role="special">::</phrase><phrase role="identifier">no_state</phrase></code>,
9319                <code><phrase role="identifier">future_errc</phrase><phrase role="special">::</phrase><phrase
9320                role="identifier">broken_promise</phrase></code>. Any exception passed
9321                to <code><phrase role="identifier">promise</phrase><phrase role="special">::</phrase><phrase
9322                role="identifier">set_exception</phrase><phrase role="special">()</phrase></code>.
9323              </para>
9324            </listitem>
9325          </varlistentry>
9326        </variablelist>
9327        <para>
9328          <bridgehead renderas="sect4" id="shared_future_get_exception_ptr_bridgehead">
9329  <phrase id="shared_future_get_exception_ptr"/>
9330  <link linkend="shared_future_get_exception_ptr">Member
9331          function <code>get_exception_ptr</code>()</link>
9332</bridgehead>
9333        </para>
9334<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>
9335</programlisting>
9336        <variablelist>
9337          <title></title>
9338          <varlistentry>
9339            <term>Precondition:</term>
9340            <listitem>
9341              <para>
9342                <code><phrase role="keyword">true</phrase> <phrase role="special">==</phrase>
9343                <phrase role="identifier">valid</phrase><phrase role="special">()</phrase></code>
9344              </para>
9345            </listitem>
9346          </varlistentry>
9347          <varlistentry>
9348            <term>Returns:</term>
9349            <listitem>
9350              <para>
9351                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
9352                called. If <code><phrase role="identifier">set_value</phrase><phrase
9353                role="special">()</phrase></code> is called, returns a default-constructed
9354                <code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase
9355                role="identifier">exception_ptr</phrase></code>. If <code><phrase
9356                role="identifier">set_exception</phrase><phrase role="special">()</phrase></code>
9357                is called, returns the passed <code><phrase role="identifier">std</phrase><phrase
9358                role="special">::</phrase><phrase role="identifier">exception_ptr</phrase></code>.
9359              </para>
9360            </listitem>
9361          </varlistentry>
9362          <varlistentry>
9363            <term>Throws:</term>
9364            <listitem>
9365              <para>
9366                <code><phrase role="identifier">future_error</phrase></code> with
9367                error condition <code><phrase role="identifier">future_errc</phrase><phrase
9368                role="special">::</phrase><phrase role="identifier">no_state</phrase></code>.
9369              </para>
9370            </listitem>
9371          </varlistentry>
9372          <varlistentry>
9373            <term>Note:</term>
9374            <listitem>
9375              <para>
9376                <code><phrase role="identifier">get_exception_ptr</phrase><phrase
9377                role="special">()</phrase></code> does <emphasis>not</emphasis> invalidate
9378                the <code>shared_future</code>. After calling <code><phrase role="identifier">get_exception_ptr</phrase><phrase
9379                role="special">()</phrase></code>, you may still call <link linkend="shared_future_get"><code>shared_future::get()</code></link>.
9380              </para>
9381            </listitem>
9382          </varlistentry>
9383        </variablelist>
9384        <para>
9385          <bridgehead renderas="sect4" id="shared_future_wait_bridgehead">
9386  <phrase id="shared_future_wait"/>
9387  <link linkend="shared_future_wait">Member
9388          function <code>wait</code>()</link>
9389</bridgehead>
9390        </para>
9391<programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">wait</phrase><phrase role="special">();</phrase>
9392</programlisting>
9393        <variablelist>
9394          <title></title>
9395          <varlistentry>
9396            <term>Effects:</term>
9397            <listitem>
9398              <para>
9399                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
9400                called.
9401              </para>
9402            </listitem>
9403          </varlistentry>
9404          <varlistentry>
9405            <term>Throws:</term>
9406            <listitem>
9407              <para>
9408                <code><phrase role="identifier">future_error</phrase></code> with
9409                error condition <code><phrase role="identifier">future_errc</phrase><phrase
9410                role="special">::</phrase><phrase role="identifier">no_state</phrase></code>.
9411              </para>
9412            </listitem>
9413          </varlistentry>
9414        </variablelist>
9415        <para>
9416          <bridgehead renderas="sect4" id="shared_future_wait_for_bridgehead">
9417  <phrase id="shared_future_wait_for"/>
9418  <link linkend="shared_future_wait_for">Templated
9419          member function <code>wait_for</code>()</link>
9420</bridgehead>
9421        </para>
9422<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>
9423<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>
9424</programlisting>
9425        <variablelist>
9426          <title></title>
9427          <varlistentry>
9428            <term>Effects:</term>
9429            <listitem>
9430              <para>
9431                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
9432                called, or <code><phrase role="identifier">timeout_duration</phrase></code>
9433                has passed.
9434              </para>
9435            </listitem>
9436          </varlistentry>
9437          <varlistentry>
9438            <term>Result:</term>
9439            <listitem>
9440              <para>
9441                A <code><phrase role="identifier">future_status</phrase></code> is
9442                returned indicating the reason for returning.
9443              </para>
9444            </listitem>
9445          </varlistentry>
9446          <varlistentry>
9447            <term>Throws:</term>
9448            <listitem>
9449              <para>
9450                <code><phrase role="identifier">future_error</phrase></code> with
9451                error condition <code><phrase role="identifier">future_errc</phrase><phrase
9452                role="special">::</phrase><phrase role="identifier">no_state</phrase></code>
9453                or timeout-related exceptions.
9454              </para>
9455            </listitem>
9456          </varlistentry>
9457        </variablelist>
9458        <para>
9459          <bridgehead renderas="sect4" id="shared_future_wait_until_bridgehead">
9460  <phrase id="shared_future_wait_until"/>
9461  <link linkend="shared_future_wait_until">Templated
9462          member function <code>wait_until</code>()</link>
9463</bridgehead>
9464        </para>
9465<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>
9466<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>
9467</programlisting>
9468        <variablelist>
9469          <title></title>
9470          <varlistentry>
9471            <term>Effects:</term>
9472            <listitem>
9473              <para>
9474                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
9475                called, or <code><phrase role="identifier">timeout_time</phrase></code>
9476                has passed.
9477              </para>
9478            </listitem>
9479          </varlistentry>
9480          <varlistentry>
9481            <term>Result:</term>
9482            <listitem>
9483              <para>
9484                A <code><phrase role="identifier">future_status</phrase></code> is
9485                returned indicating the reason for returning.
9486              </para>
9487            </listitem>
9488          </varlistentry>
9489          <varlistentry>
9490            <term>Throws:</term>
9491            <listitem>
9492              <para>
9493                <code><phrase role="identifier">future_error</phrase></code> with
9494                error condition <code><phrase role="identifier">future_errc</phrase><phrase
9495                role="special">::</phrase><phrase role="identifier">no_state</phrase></code>
9496                or timeout-related exceptions.
9497              </para>
9498            </listitem>
9499          </varlistentry>
9500        </variablelist>
9501        <para>
9502          <bridgehead renderas="sect4" id="fibers_async_bridgehead">
9503  <phrase id="fibers_async"/>
9504  <link linkend="fibers_async">Non-member function <code>fibers::async()</code></link>
9505</bridgehead>
9506        </para>
9507<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>
9508
9509<phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase>
9510<phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase>
9511
9512<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>
9513<phrase role="identifier">future</phrase><phrase role="special">&lt;</phrase>
9514    <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">result_of_t</phrase><phrase role="special">&lt;</phrase>
9515        <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>
9516    <phrase role="special">&gt;</phrase>
9517<phrase role="special">&gt;</phrase>
9518<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>
9519
9520<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>
9521<phrase role="identifier">future</phrase><phrase role="special">&lt;</phrase>
9522    <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">result_of_t</phrase><phrase role="special">&lt;</phrase>
9523        <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>
9524    <phrase role="special">&gt;</phrase>
9525<phrase role="special">&gt;</phrase>
9526<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>
9527
9528<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>
9529<phrase role="identifier">future</phrase><phrase role="special">&lt;</phrase>
9530    <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">result_of_t</phrase><phrase role="special">&lt;</phrase>
9531        <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>
9532    <phrase role="special">&gt;</phrase>
9533<phrase role="special">&gt;</phrase>
9534<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>
9535       <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>
9536
9537<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>
9538<phrase role="identifier">future</phrase><phrase role="special">&lt;</phrase>
9539    <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">result_of_t</phrase><phrase role="special">&lt;</phrase>
9540        <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>
9541    <phrase role="special">&gt;</phrase>
9542<phrase role="special">&gt;</phrase>
9543<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>
9544       <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>
9545
9546<phrase role="special">}}</phrase>
9547</programlisting>
9548        <variablelist>
9549          <title></title>
9550          <varlistentry>
9551            <term>Effects:</term>
9552            <listitem>
9553              <para>
9554                Executes <code><phrase role="identifier">fn</phrase></code> in a
9555                <link linkend="class_fiber"><code>fiber</code></link> and returns an associated <link linkend="class_future"><code>future&lt;&gt;</code></link>.
9556              </para>
9557            </listitem>
9558          </varlistentry>
9559          <varlistentry>
9560            <term>Result:</term>
9561            <listitem>
9562              <para>
9563<programlisting><phrase role="identifier">future</phrase><phrase role="special">&lt;</phrase>
9564    <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">result_of_t</phrase><phrase role="special">&lt;</phrase>
9565        <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>
9566    <phrase role="special">&gt;</phrase>
9567<phrase role="special">&gt;</phrase></programlisting>
9568                representing the <link linkend="shared_state">shared state</link>
9569                associated with the asynchronous execution of <code><phrase role="identifier">fn</phrase></code>.
9570              </para>
9571            </listitem>
9572          </varlistentry>
9573          <varlistentry>
9574            <term>Throws:</term>
9575            <listitem>
9576              <para>
9577                <code><phrase role="identifier">fiber_error</phrase></code> or <code><phrase
9578                role="identifier">future_error</phrase></code> if an error occurs.
9579              </para>
9580            </listitem>
9581          </varlistentry>
9582          <varlistentry>
9583            <term>Notes:</term>
9584            <listitem>
9585              <para>
9586                The overloads accepting <ulink url="http://en.cppreference.com/w/cpp/memory/allocator_arg_t"><code><phrase
9587                role="identifier">std</phrase><phrase role="special">::</phrase><phrase
9588                role="identifier">allocator_arg_t</phrase></code></ulink> use the
9589                passed <link linkend="stack_allocator_concept"><code><phrase role="identifier">StackAllocator</phrase></code></link>
9590                when constructing the launched <code><phrase role="identifier">fiber</phrase></code>.
9591                The overloads accepting <link linkend="class_launch"><code>launch</code></link> use the passed <code><phrase
9592                role="identifier">launch</phrase></code> when constructing the launched
9593                <code><phrase role="identifier">fiber</phrase></code>. The default
9594                <code><phrase role="identifier">launch</phrase></code> is <code><phrase
9595                role="identifier">post</phrase></code>, as for the <code><phrase
9596                role="identifier">fiber</phrase></code> constructor.
9597              </para>
9598            </listitem>
9599          </varlistentry>
9600        </variablelist>
9601        <note>
9602          <para>
9603            Deferred futures are not supported.
9604          </para>
9605        </note>
9606      </section>
9607      <section id="fiber.synchronization.futures.promise">
9608        <title><anchor id="class_promise"/><link linkend="fiber.synchronization.futures.promise">Template
9609        <code><phrase role="identifier">promise</phrase><phrase role="special">&lt;&gt;</phrase></code></link></title>
9610        <para>
9611          A <link linkend="class_promise"><code>promise&lt;&gt;</code></link> provides a mechanism to store a value (or
9612          exception) that can later be retrieved from the corresponding <link linkend="class_future"><code>future&lt;&gt;</code></link> object.
9613          <code><phrase role="identifier">promise</phrase><phrase role="special">&lt;&gt;</phrase></code>
9614          and <code><phrase role="identifier">future</phrase><phrase role="special">&lt;&gt;</phrase></code>
9615          communicate via their underlying <link linkend="shared_state">shared state</link>.
9616        </para>
9617<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>
9618
9619<phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase>
9620<phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase>
9621
9622<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>
9623<phrase role="keyword">class</phrase> <phrase role="identifier">promise</phrase> <phrase role="special">{</phrase>
9624<phrase role="keyword">public</phrase><phrase role="special">:</phrase>
9625    <phrase role="identifier">promise</phrase><phrase role="special">();</phrase>
9626
9627    <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>
9628    <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>
9629
9630    <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>
9631
9632    <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>
9633
9634    <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>
9635
9636    <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>
9637
9638    <phrase role="special">~</phrase><phrase role="identifier">promise</phrase><phrase role="special">();</phrase>
9639
9640    <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>
9641
9642    <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>
9643
9644    <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>
9645    <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>
9646    <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>
9647    <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>
9648
9649    <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>
9650<phrase role="special">};</phrase>
9651
9652<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>
9653<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>
9654
9655<phrase role="special">}</phrase>
9656</programlisting>
9657        <bridgehead renderas="sect5" id="fiber.synchronization.futures.promise.h0">
9658          <phrase id="fiber.synchronization.futures.promise.default_constructor"/><link
9659          linkend="fiber.synchronization.futures.promise.default_constructor">Default
9660          constructor</link>
9661        </bridgehead>
9662<programlisting><phrase role="identifier">promise</phrase><phrase role="special">();</phrase>
9663</programlisting>
9664        <variablelist>
9665          <title></title>
9666          <varlistentry>
9667            <term>Effects:</term>
9668            <listitem>
9669              <para>
9670                Creates a promise with an empty <link linkend="shared_state">shared
9671                state</link>.
9672              </para>
9673            </listitem>
9674          </varlistentry>
9675          <varlistentry>
9676            <term>Throws:</term>
9677            <listitem>
9678              <para>
9679                Exceptions caused by memory allocation.
9680              </para>
9681            </listitem>
9682          </varlistentry>
9683        </variablelist>
9684        <bridgehead renderas="sect5" id="fiber.synchronization.futures.promise.h1">
9685          <phrase id="fiber.synchronization.futures.promise.constructor"/><link linkend="fiber.synchronization.futures.promise.constructor">Constructor</link>
9686        </bridgehead>
9687<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>
9688<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>
9689</programlisting>
9690        <variablelist>
9691          <title></title>
9692          <varlistentry>
9693            <term>Effects:</term>
9694            <listitem>
9695              <para>
9696                Creates a promise with an empty <link linkend="shared_state">shared
9697                state</link> by using <code><phrase role="identifier">alloc</phrase></code>.
9698              </para>
9699            </listitem>
9700          </varlistentry>
9701          <varlistentry>
9702            <term>Throws:</term>
9703            <listitem>
9704              <para>
9705                Exceptions caused by memory allocation.
9706              </para>
9707            </listitem>
9708          </varlistentry>
9709          <varlistentry>
9710            <term>See also:</term>
9711            <listitem>
9712              <para>
9713                <ulink url="http://en.cppreference.com/w/cpp/memory/allocator_arg_t"><code><phrase
9714                role="identifier">std</phrase><phrase role="special">::</phrase><phrase
9715                role="identifier">allocator_arg_t</phrase></code></ulink>
9716              </para>
9717            </listitem>
9718          </varlistentry>
9719        </variablelist>
9720        <bridgehead renderas="sect5" id="fiber.synchronization.futures.promise.h2">
9721          <phrase id="fiber.synchronization.futures.promise.move_constructor"/><link
9722          linkend="fiber.synchronization.futures.promise.move_constructor">Move constructor</link>
9723        </bridgehead>
9724<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>
9725</programlisting>
9726        <variablelist>
9727          <title></title>
9728          <varlistentry>
9729            <term>Effects:</term>
9730            <listitem>
9731              <para>
9732                Creates a promise by moving the <link linkend="shared_state">shared
9733                state</link> from <code><phrase role="identifier">other</phrase></code>.
9734              </para>
9735            </listitem>
9736          </varlistentry>
9737          <varlistentry>
9738            <term>Postcondition:</term>
9739            <listitem>
9740              <para>
9741                <code><phrase role="identifier">other</phrase></code> contains no
9742                valid shared state.
9743              </para>
9744            </listitem>
9745          </varlistentry>
9746          <varlistentry>
9747            <term>Throws:</term>
9748            <listitem>
9749              <para>
9750                Nothing.
9751              </para>
9752            </listitem>
9753          </varlistentry>
9754        </variablelist>
9755        <bridgehead renderas="sect5" id="fiber.synchronization.futures.promise.h3">
9756          <phrase id="fiber.synchronization.futures.promise.destructor"/><link linkend="fiber.synchronization.futures.promise.destructor">Destructor</link>
9757        </bridgehead>
9758<programlisting><phrase role="special">~</phrase><phrase role="identifier">promise</phrase><phrase role="special">();</phrase>
9759</programlisting>
9760        <variablelist>
9761          <title></title>
9762          <varlistentry>
9763            <term>Effects:</term>
9764            <listitem>
9765              <para>
9766                Destroys <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>
9767                and abandons the <link linkend="shared_state">shared state</link>
9768                if shared state is ready; otherwise stores <code><phrase role="identifier">future_error</phrase></code>
9769                with error condition <code><phrase role="identifier">future_errc</phrase><phrase
9770                role="special">::</phrase><phrase role="identifier">broken_promise</phrase></code>
9771                as if by <link linkend="promise_set_exception"><code>promise::set_exception()</code></link>: the shared
9772                state is set ready.
9773              </para>
9774            </listitem>
9775          </varlistentry>
9776        </variablelist>
9777        <para>
9778          <bridgehead renderas="sect4" id="promise_operator_assign_bridgehead">
9779  <phrase id="promise_operator_assign"/>
9780  <link linkend="promise_operator_assign">Member
9781          function <code>operator=</code>()</link>
9782</bridgehead>
9783        </para>
9784<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>
9785</programlisting>
9786        <variablelist>
9787          <title></title>
9788          <varlistentry>
9789            <term>Effects:</term>
9790            <listitem>
9791              <para>
9792                Transfers the ownership of <link linkend="shared_state">shared state</link>
9793                to <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>.
9794              </para>
9795            </listitem>
9796          </varlistentry>
9797          <varlistentry>
9798            <term>Postcondition:</term>
9799            <listitem>
9800              <para>
9801                <code><phrase role="identifier">other</phrase></code> contains no
9802                valid shared state.
9803              </para>
9804            </listitem>
9805          </varlistentry>
9806          <varlistentry>
9807            <term>Throws:</term>
9808            <listitem>
9809              <para>
9810                Nothing.
9811              </para>
9812            </listitem>
9813          </varlistentry>
9814        </variablelist>
9815        <para>
9816          <bridgehead renderas="sect4" id="promise_swap_bridgehead">
9817  <phrase id="promise_swap"/>
9818  <link linkend="promise_swap">Member function <code>swap</code>()</link>
9819</bridgehead>
9820        </para>
9821<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>
9822</programlisting>
9823        <variablelist>
9824          <title></title>
9825          <varlistentry>
9826            <term>Effects:</term>
9827            <listitem>
9828              <para>
9829                Swaps the <link linkend="shared_state">shared state</link> between
9830                other and <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>.
9831              </para>
9832            </listitem>
9833          </varlistentry>
9834          <varlistentry>
9835            <term>Throws:</term>
9836            <listitem>
9837              <para>
9838                Nothing.
9839              </para>
9840            </listitem>
9841          </varlistentry>
9842        </variablelist>
9843        <para>
9844          <bridgehead renderas="sect4" id="promise_get_future_bridgehead">
9845  <phrase id="promise_get_future"/>
9846  <link linkend="promise_get_future">Member
9847          function <code>get_future</code>()</link>
9848</bridgehead>
9849        </para>
9850<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>
9851</programlisting>
9852        <variablelist>
9853          <title></title>
9854          <varlistentry>
9855            <term>Returns:</term>
9856            <listitem>
9857              <para>
9858                A <link linkend="class_future"><code>future&lt;&gt;</code></link> with the same <link linkend="shared_state">shared
9859                state</link>.
9860              </para>
9861            </listitem>
9862          </varlistentry>
9863          <varlistentry>
9864            <term>Throws:</term>
9865            <listitem>
9866              <para>
9867                <code><phrase role="identifier">future_error</phrase></code> with
9868                <code><phrase role="identifier">future_errc</phrase><phrase role="special">::</phrase><phrase
9869                role="identifier">future_already_retrieved</phrase></code> or <code><phrase
9870                role="identifier">future_errc</phrase><phrase role="special">::</phrase><phrase
9871                role="identifier">no_state</phrase></code>.
9872              </para>
9873            </listitem>
9874          </varlistentry>
9875        </variablelist>
9876        <para>
9877          <bridgehead renderas="sect4" id="promise_set_value_bridgehead">
9878  <phrase id="promise_set_value"/>
9879  <link linkend="promise_set_value">Member function
9880          <code>set_value</code>()</link>
9881</bridgehead>
9882        </para>
9883<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>
9884<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>
9885<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>
9886<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>
9887</programlisting>
9888        <variablelist>
9889          <title></title>
9890          <varlistentry>
9891            <term>Effects:</term>
9892            <listitem>
9893              <para>
9894                Store the result in the <link linkend="shared_state">shared state</link>
9895                and marks the state as ready.
9896              </para>
9897            </listitem>
9898          </varlistentry>
9899          <varlistentry>
9900            <term>Throws:</term>
9901            <listitem>
9902              <para>
9903                <code><phrase role="identifier">future_error</phrase></code> with
9904                <code><phrase role="identifier">future_errc</phrase><phrase role="special">::</phrase><phrase
9905                role="identifier">future_already_satisfied</phrase></code> or <code><phrase
9906                role="identifier">future_errc</phrase><phrase role="special">::</phrase><phrase
9907                role="identifier">no_state</phrase></code>.
9908              </para>
9909            </listitem>
9910          </varlistentry>
9911        </variablelist>
9912        <para>
9913          <bridgehead renderas="sect4" id="promise_set_exception_bridgehead">
9914  <phrase id="promise_set_exception"/>
9915  <link linkend="promise_set_exception">Member
9916          function <code>set_exception</code>()</link>
9917</bridgehead>
9918        </para>
9919<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>
9920</programlisting>
9921        <variablelist>
9922          <title></title>
9923          <varlistentry>
9924            <term>Effects:</term>
9925            <listitem>
9926              <para>
9927                Store an exception pointer in the <link linkend="shared_state">shared
9928                state</link> and marks the state as ready.
9929              </para>
9930            </listitem>
9931          </varlistentry>
9932          <varlistentry>
9933            <term>Throws:</term>
9934            <listitem>
9935              <para>
9936                <code><phrase role="identifier">future_error</phrase></code> with
9937                <code><phrase role="identifier">future_errc</phrase><phrase role="special">::</phrase><phrase
9938                role="identifier">future_already_satisfied</phrase></code> or <code><phrase
9939                role="identifier">future_errc</phrase><phrase role="special">::</phrase><phrase
9940                role="identifier">no_state</phrase></code>.
9941              </para>
9942            </listitem>
9943          </varlistentry>
9944        </variablelist>
9945        <para>
9946          <bridgehead renderas="sect4" id="swap_for_promise_bridgehead">
9947  <phrase id="swap_for_promise"/>
9948  <link linkend="swap_for_promise">Non-member function
9949          <code>swap()</code></link>
9950</bridgehead>
9951        </para>
9952<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>
9953<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>
9954</programlisting>
9955        <variablelist>
9956          <title></title>
9957          <varlistentry>
9958            <term>Effects:</term>
9959            <listitem>
9960              <para>
9961                Same as <code><phrase role="identifier">l</phrase><phrase role="special">.</phrase><phrase
9962                role="identifier">swap</phrase><phrase role="special">(</phrase>
9963                <phrase role="identifier">r</phrase><phrase role="special">)</phrase></code>.
9964              </para>
9965            </listitem>
9966          </varlistentry>
9967        </variablelist>
9968      </section>
9969      <section id="fiber.synchronization.futures.packaged_task">
9970        <title><anchor id="class_packaged_task"/><link linkend="fiber.synchronization.futures.packaged_task">Template
9971        <code><phrase role="identifier">packaged_task</phrase><phrase role="special">&lt;&gt;</phrase></code></link></title>
9972        <para>
9973          A <link linkend="class_packaged_task"><code>packaged_task&lt;&gt;</code></link> wraps a callable target that
9974          returns a value so that the return value can be computed asynchronously.
9975        </para>
9976        <para>
9977          Conventional usage of <code><phrase role="identifier">packaged_task</phrase><phrase
9978          role="special">&lt;&gt;</phrase></code> is like this:
9979        </para>
9980        <orderedlist>
9981          <listitem>
9982            <simpara>
9983              Instantiate <code><phrase role="identifier">packaged_task</phrase><phrase
9984              role="special">&lt;&gt;</phrase></code> with template arguments matching
9985              the signature of the callable. Pass the callable to the <link linkend="packaged_task_packaged_task">constructor</link>.
9986            </simpara>
9987          </listitem>
9988          <listitem>
9989            <simpara>
9990              Call <link linkend="packaged_task_get_future"><code>packaged_task::get_future()</code></link> and capture
9991              the returned <link linkend="class_future"><code>future&lt;&gt;</code></link> instance.
9992            </simpara>
9993          </listitem>
9994          <listitem>
9995            <simpara>
9996              Launch a <link linkend="class_fiber"><code>fiber</code></link> to run the new <code><phrase role="identifier">packaged_task</phrase><phrase
9997              role="special">&lt;&gt;</phrase></code>, passing any arguments required
9998              by the original callable.
9999            </simpara>
10000          </listitem>
10001          <listitem>
10002            <simpara>
10003              Call <link linkend="fiber_detach"><code>fiber::detach()</code></link> on the newly-launched <code><phrase
10004              role="identifier">fiber</phrase></code>.
10005            </simpara>
10006          </listitem>
10007          <listitem>
10008            <simpara>
10009              At some later point, retrieve the result from the <code><phrase role="identifier">future</phrase><phrase
10010              role="special">&lt;&gt;</phrase></code>.
10011            </simpara>
10012          </listitem>
10013        </orderedlist>
10014        <para>
10015          This is, in fact, pretty much what <link linkend="fibers_async"><code>fibers::async()</code></link>
10016encapsulates.
10017        </para>
10018<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>
10019
10020<phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase>
10021<phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase>
10022
10023<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>
10024<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>
10025<phrase role="keyword">public</phrase><phrase role="special">:</phrase>
10026    <phrase role="identifier">packaged_task</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
10027
10028    <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>
10029    <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>
10030
10031    <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>
10032    <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>
10033
10034    <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>
10035
10036    <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>
10037
10038    <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>
10039
10040    <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>
10041
10042    <phrase role="special">~</phrase><phrase role="identifier">packaged_task</phrase><phrase role="special">();</phrase>
10043
10044    <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>
10045
10046    <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>
10047
10048    <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>
10049
10050    <phrase role="keyword">void</phrase> <phrase role="keyword">operator</phrase><phrase role="special">()(</phrase> <phrase role="identifier">Args</phrase> <phrase role="special">...);</phrase>
10051
10052    <phrase role="keyword">void</phrase> <phrase role="identifier">reset</phrase><phrase role="special">();</phrase>
10053<phrase role="special">};</phrase>
10054
10055<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>
10056<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>
10057
10058<phrase role="special">}}</phrase>
10059</programlisting>
10060        <bridgehead renderas="sect5" id="fiber.synchronization.futures.packaged_task.h0">
10061          <phrase id="fiber.synchronization.futures.packaged_task.default_constructor__code__phrase_role__identifier__packaged_task__phrase__phrase_role__special______phrase___code_"/><link
10062          linkend="fiber.synchronization.futures.packaged_task.default_constructor__code__phrase_role__identifier__packaged_task__phrase__phrase_role__special______phrase___code_">Default
10063          constructor <code><phrase role="identifier">packaged_task</phrase><phrase
10064          role="special">()</phrase></code></link>
10065        </bridgehead>
10066<programlisting><phrase role="identifier">packaged_task</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
10067</programlisting>
10068        <variablelist>
10069          <title></title>
10070          <varlistentry>
10071            <term>Effects:</term>
10072            <listitem>
10073              <para>
10074                Constructs an object of class <code><phrase role="identifier">packaged_task</phrase></code>
10075                with no <link linkend="shared_state">shared state</link>.
10076              </para>
10077            </listitem>
10078          </varlistentry>
10079          <varlistentry>
10080            <term>Throws:</term>
10081            <listitem>
10082              <para>
10083                Nothing.
10084              </para>
10085            </listitem>
10086          </varlistentry>
10087        </variablelist>
10088        <anchor id="packaged_task_packaged_task"/>
10089        <bridgehead renderas="sect5" id="fiber.synchronization.futures.packaged_task.h1">
10090          <phrase id="fiber.synchronization.futures.packaged_task.templated_constructor__code__phrase_role__identifier__packaged_task__phrase__phrase_role__special______phrase___code_"/><link
10091          linkend="fiber.synchronization.futures.packaged_task.templated_constructor__code__phrase_role__identifier__packaged_task__phrase__phrase_role__special______phrase___code_">Templated
10092          constructor <code><phrase role="identifier">packaged_task</phrase><phrase
10093          role="special">()</phrase></code></link>
10094        </bridgehead>
10095<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>
10096<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>
10097
10098<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>
10099<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>
10100</programlisting>
10101        <variablelist>
10102          <title></title>
10103          <varlistentry>
10104            <term>Effects:</term>
10105            <listitem>
10106              <para>
10107                Constructs an object of class <code><phrase role="identifier">packaged_task</phrase></code>
10108                with a <link linkend="shared_state">shared state</link> and copies
10109                or moves the callable target <code><phrase role="identifier">fn</phrase></code>
10110                to internal storage.
10111              </para>
10112            </listitem>
10113          </varlistentry>
10114          <varlistentry>
10115            <term>Throws:</term>
10116            <listitem>
10117              <para>
10118                Exceptions caused by memory allocation.
10119              </para>
10120            </listitem>
10121          </varlistentry>
10122          <varlistentry>
10123            <term>Note:</term>
10124            <listitem>
10125              <para>
10126                The signature of <code><phrase role="identifier">Fn</phrase></code>
10127                should have a return type convertible to <code><phrase role="identifier">R</phrase></code>.
10128              </para>
10129            </listitem>
10130          </varlistentry>
10131          <varlistentry>
10132            <term>See also:</term>
10133            <listitem>
10134              <para>
10135                <ulink url="http://en.cppreference.com/w/cpp/memory/allocator_arg_t"><code><phrase
10136                role="identifier">std</phrase><phrase role="special">::</phrase><phrase
10137                role="identifier">allocator_arg_t</phrase></code></ulink>
10138              </para>
10139            </listitem>
10140          </varlistentry>
10141        </variablelist>
10142        <bridgehead renderas="sect5" id="fiber.synchronization.futures.packaged_task.h2">
10143          <phrase id="fiber.synchronization.futures.packaged_task.move_constructor"/><link
10144          linkend="fiber.synchronization.futures.packaged_task.move_constructor">Move
10145          constructor</link>
10146        </bridgehead>
10147<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>
10148</programlisting>
10149        <variablelist>
10150          <title></title>
10151          <varlistentry>
10152            <term>Effects:</term>
10153            <listitem>
10154              <para>
10155                Creates a packaged_task by moving the <link linkend="shared_state">shared
10156                state</link> from <code><phrase role="identifier">other</phrase></code>.
10157              </para>
10158            </listitem>
10159          </varlistentry>
10160          <varlistentry>
10161            <term>Postcondition:</term>
10162            <listitem>
10163              <para>
10164                <code><phrase role="identifier">other</phrase></code> contains no
10165                valid shared state.
10166              </para>
10167            </listitem>
10168          </varlistentry>
10169          <varlistentry>
10170            <term>Throws:</term>
10171            <listitem>
10172              <para>
10173                Nothing.
10174              </para>
10175            </listitem>
10176          </varlistentry>
10177        </variablelist>
10178        <bridgehead renderas="sect5" id="fiber.synchronization.futures.packaged_task.h3">
10179          <phrase id="fiber.synchronization.futures.packaged_task.destructor"/><link
10180          linkend="fiber.synchronization.futures.packaged_task.destructor">Destructor</link>
10181        </bridgehead>
10182<programlisting><phrase role="special">~</phrase><phrase role="identifier">packaged_task</phrase><phrase role="special">();</phrase>
10183</programlisting>
10184        <variablelist>
10185          <title></title>
10186          <varlistentry>
10187            <term>Effects:</term>
10188            <listitem>
10189              <para>
10190                Destroys <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>
10191                and abandons the <link linkend="shared_state">shared state</link>
10192                if shared state is ready; otherwise stores <code><phrase role="identifier">future_error</phrase></code>
10193                with error condition <code><phrase role="identifier">future_errc</phrase><phrase
10194                role="special">::</phrase><phrase role="identifier">broken_promise</phrase></code>
10195                as if by <link linkend="promise_set_exception"><code>promise::set_exception()</code></link>: the shared
10196                state is set ready.
10197              </para>
10198            </listitem>
10199          </varlistentry>
10200        </variablelist>
10201        <para>
10202          <bridgehead renderas="sect4" id="packaged_task_operator_assign_bridgehead">
10203  <phrase id="packaged_task_operator_assign"/>
10204  <link linkend="packaged_task_operator_assign">Member
10205          function <code>operator=</code>()</link>
10206</bridgehead>
10207        </para>
10208<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>
10209</programlisting>
10210        <variablelist>
10211          <title></title>
10212          <varlistentry>
10213            <term>Effects:</term>
10214            <listitem>
10215              <para>
10216                Transfers the ownership of <link linkend="shared_state">shared state</link>
10217                to <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>.
10218              </para>
10219            </listitem>
10220          </varlistentry>
10221          <varlistentry>
10222            <term>Postcondition:</term>
10223            <listitem>
10224              <para>
10225                <code><phrase role="identifier">other</phrase></code> contains no
10226                valid shared state.
10227              </para>
10228            </listitem>
10229          </varlistentry>
10230          <varlistentry>
10231            <term>Throws:</term>
10232            <listitem>
10233              <para>
10234                Nothing.
10235              </para>
10236            </listitem>
10237          </varlistentry>
10238        </variablelist>
10239        <para>
10240          <bridgehead renderas="sect4" id="packaged_task_swap_bridgehead">
10241  <phrase id="packaged_task_swap"/>
10242  <link linkend="packaged_task_swap">Member
10243          function <code>swap</code>()</link>
10244</bridgehead>
10245        </para>
10246<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>
10247</programlisting>
10248        <variablelist>
10249          <title></title>
10250          <varlistentry>
10251            <term>Effects:</term>
10252            <listitem>
10253              <para>
10254                Swaps the <link linkend="shared_state">shared state</link> between
10255                other and <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>.
10256              </para>
10257            </listitem>
10258          </varlistentry>
10259          <varlistentry>
10260            <term>Throws:</term>
10261            <listitem>
10262              <para>
10263                Nothing.
10264              </para>
10265            </listitem>
10266          </varlistentry>
10267        </variablelist>
10268        <para>
10269          <bridgehead renderas="sect4" id="packaged_task_valid_bridgehead">
10270  <phrase id="packaged_task_valid"/>
10271  <link linkend="packaged_task_valid">Member
10272          function <code>valid</code>()</link>
10273</bridgehead>
10274        </para>
10275<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>
10276</programlisting>
10277        <variablelist>
10278          <title></title>
10279          <varlistentry>
10280            <term>Effects:</term>
10281            <listitem>
10282              <para>
10283                Returns <code><phrase role="keyword">true</phrase></code> if <code><phrase
10284                role="special">*</phrase><phrase role="keyword">this</phrase></code>
10285                contains a <link linkend="shared_state">shared state</link>.
10286              </para>
10287            </listitem>
10288          </varlistentry>
10289          <varlistentry>
10290            <term>Throws:</term>
10291            <listitem>
10292              <para>
10293                Nothing.
10294              </para>
10295            </listitem>
10296          </varlistentry>
10297        </variablelist>
10298        <para>
10299          <bridgehead renderas="sect4" id="packaged_task_get_future_bridgehead">
10300  <phrase id="packaged_task_get_future"/>
10301  <link linkend="packaged_task_get_future">Member
10302          function <code>get_future</code>()</link>
10303</bridgehead>
10304        </para>
10305<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>
10306</programlisting>
10307        <variablelist>
10308          <title></title>
10309          <varlistentry>
10310            <term>Returns:</term>
10311            <listitem>
10312              <para>
10313                A <link linkend="class_future"><code>future&lt;&gt;</code></link> with the same <link linkend="shared_state">shared
10314                state</link>.
10315              </para>
10316            </listitem>
10317          </varlistentry>
10318          <varlistentry>
10319            <term>Throws:</term>
10320            <listitem>
10321              <para>
10322                <code><phrase role="identifier">future_error</phrase></code> with
10323                <code><phrase role="identifier">future_errc</phrase><phrase role="special">::</phrase><phrase
10324                role="identifier">future_already_retrieved</phrase></code> or <code><phrase
10325                role="identifier">future_errc</phrase><phrase role="special">::</phrase><phrase
10326                role="identifier">no_state</phrase></code>.
10327              </para>
10328            </listitem>
10329          </varlistentry>
10330        </variablelist>
10331        <para>
10332          <bridgehead renderas="sect4" id="packaged_task_operator_apply_bridgehead">
10333  <phrase id="packaged_task_operator_apply"/>
10334  <link linkend="packaged_task_operator_apply">Member
10335          function <code>operator()</code>()</link>
10336</bridgehead>
10337        </para>
10338<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>
10339</programlisting>
10340        <variablelist>
10341          <title></title>
10342          <varlistentry>
10343            <term>Effects:</term>
10344            <listitem>
10345              <para>
10346                Invokes the stored callable target. Any exception thrown by the callable
10347                target <code><phrase role="identifier">fn</phrase></code> is stored
10348                in the <link linkend="shared_state">shared state</link> as if by
10349                <link linkend="promise_set_exception"><code>promise::set_exception()</code></link>. Otherwise, the value
10350                returned by <code><phrase role="identifier">fn</phrase></code> is
10351                stored in the shared state as if by <link linkend="promise_set_value"><code>promise::set_value()</code></link>.
10352              </para>
10353            </listitem>
10354          </varlistentry>
10355          <varlistentry>
10356            <term>Throws:</term>
10357            <listitem>
10358              <para>
10359                <code><phrase role="identifier">future_error</phrase></code> with
10360                <code><phrase role="identifier">future_errc</phrase><phrase role="special">::</phrase><phrase
10361                role="identifier">no_state</phrase></code>.
10362              </para>
10363            </listitem>
10364          </varlistentry>
10365        </variablelist>
10366        <para>
10367          <bridgehead renderas="sect4" id="packaged_task_reset_bridgehead">
10368  <phrase id="packaged_task_reset"/>
10369  <link linkend="packaged_task_reset">Member
10370          function <code>reset</code>()</link>
10371</bridgehead>
10372        </para>
10373<programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">reset</phrase><phrase role="special">();</phrase>
10374</programlisting>
10375        <variablelist>
10376          <title></title>
10377          <varlistentry>
10378            <term>Effects:</term>
10379            <listitem>
10380              <para>
10381                Resets the <link linkend="shared_state">shared state</link> and abandons
10382                the result of previous executions. A new shared state is constructed.
10383              </para>
10384            </listitem>
10385          </varlistentry>
10386          <varlistentry>
10387            <term>Throws:</term>
10388            <listitem>
10389              <para>
10390                <code><phrase role="identifier">future_error</phrase></code> with
10391                <code><phrase role="identifier">future_errc</phrase><phrase role="special">::</phrase><phrase
10392                role="identifier">no_state</phrase></code>.
10393              </para>
10394            </listitem>
10395          </varlistentry>
10396        </variablelist>
10397        <para>
10398          <bridgehead renderas="sect4" id="swap_for_packaged_task_bridgehead">
10399  <phrase id="swap_for_packaged_task"/>
10400  <link linkend="swap_for_packaged_task">Non-member
10401          function <code>swap()</code></link>
10402</bridgehead>
10403        </para>
10404<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>
10405<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>
10406</programlisting>
10407        <variablelist>
10408          <title></title>
10409          <varlistentry>
10410            <term>Effects:</term>
10411            <listitem>
10412              <para>
10413                Same as <code><phrase role="identifier">l</phrase><phrase role="special">.</phrase><phrase
10414                role="identifier">swap</phrase><phrase role="special">(</phrase>
10415                <phrase role="identifier">r</phrase><phrase role="special">)</phrase></code>.
10416              </para>
10417            </listitem>
10418          </varlistentry>
10419        </variablelist>
10420      </section>
10421    </section>
10422  </section>
10423  <section id="fiber.fls">
10424    <title><link linkend="fiber.fls">Fiber local storage</link></title>
10425    <bridgehead renderas="sect3" id="fiber.fls.h0">
10426      <phrase id="fiber.fls.synopsis"/><link linkend="fiber.fls.synopsis">Synopsis</link>
10427    </bridgehead>
10428    <para>
10429      Fiber local storage allows a separate instance of a given data item for each
10430      fiber.
10431    </para>
10432    <bridgehead renderas="sect3" id="fiber.fls.h1">
10433      <phrase id="fiber.fls.cleanup_at_fiber_exit"/><link linkend="fiber.fls.cleanup_at_fiber_exit">Cleanup
10434      at fiber exit</link>
10435    </bridgehead>
10436    <para>
10437      When a fiber exits, the objects associated with each <link linkend="class_fiber_specific_ptr"><code>fiber_specific_ptr</code></link> instance
10438      are destroyed. By default, the object pointed to by a pointer <code><phrase
10439      role="identifier">p</phrase></code> is destroyed by invoking <code><phrase
10440      role="keyword">delete</phrase> <phrase role="identifier">p</phrase></code>,
10441      but this can be overridden for a specific instance of <link linkend="class_fiber_specific_ptr"><code>fiber_specific_ptr</code></link> by
10442      providing a cleanup routine <code><phrase role="identifier">func</phrase></code>
10443      to the constructor. In this case, the object is destroyed by invoking <code><phrase
10444      role="identifier">func</phrase><phrase role="special">(</phrase><phrase role="identifier">p</phrase><phrase
10445      role="special">)</phrase></code>. The cleanup functions are called in an unspecified
10446      order.
10447    </para>
10448    <para>
10449      <bridgehead renderas="sect4" id="class_fiber_specific_ptr_bridgehead">
10450  <phrase id="class_fiber_specific_ptr"/>
10451  <link linkend="class_fiber_specific_ptr">Class
10452      <code>fiber_specific_ptr</code></link>
10453</bridgehead>
10454    </para>
10455<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>
10456
10457<phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase>
10458<phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase>
10459
10460<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>
10461<phrase role="keyword">class</phrase> <phrase role="identifier">fiber_specific_ptr</phrase> <phrase role="special">{</phrase>
10462<phrase role="keyword">public</phrase><phrase role="special">:</phrase>
10463    <phrase role="keyword">typedef</phrase> <phrase role="identifier">T</phrase>   <phrase role="identifier">element_type</phrase><phrase role="special">;</phrase>
10464
10465    <phrase role="identifier">fiber_specific_ptr</phrase><phrase role="special">();</phrase>
10466
10467    <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>
10468
10469    <phrase role="special">~</phrase><phrase role="identifier">fiber_specific_ptr</phrase><phrase role="special">();</phrase>
10470
10471    <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>
10472    <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>
10473
10474    <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>
10475
10476    <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>
10477
10478    <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>
10479
10480    <phrase role="identifier">T</phrase> <phrase role="special">*</phrase> <phrase role="identifier">release</phrase><phrase role="special">();</phrase>
10481
10482    <phrase role="keyword">void</phrase> <phrase role="identifier">reset</phrase><phrase role="special">(</phrase> <phrase role="identifier">T</phrase> <phrase role="special">*);</phrase>
10483<phrase role="special">};</phrase>
10484
10485<phrase role="special">}}</phrase>
10486</programlisting>
10487    <bridgehead renderas="sect3" id="fiber.fls.h2">
10488      <phrase id="fiber.fls.constructor"/><link linkend="fiber.fls.constructor">Constructor</link>
10489    </bridgehead>
10490<programlisting><phrase role="identifier">fiber_specific_ptr</phrase><phrase role="special">();</phrase>
10491<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>
10492</programlisting>
10493    <variablelist>
10494      <title></title>
10495      <varlistentry>
10496        <term>Requires:</term>
10497        <listitem>
10498          <para>
10499            <code><phrase role="keyword">delete</phrase> <phrase role="keyword">this</phrase><phrase
10500            role="special">-&gt;</phrase><phrase role="identifier">get</phrase><phrase
10501            role="special">()</phrase></code> is well-formed; <code><phrase role="identifier">fn</phrase><phrase
10502            role="special">(</phrase><phrase role="keyword">this</phrase><phrase
10503            role="special">-&gt;</phrase><phrase role="identifier">get</phrase><phrase
10504            role="special">())</phrase></code> does not throw
10505          </para>
10506        </listitem>
10507      </varlistentry>
10508      <varlistentry>
10509        <term>Effects:</term>
10510        <listitem>
10511          <para>
10512            Construct a <link linkend="class_fiber_specific_ptr"><code>fiber_specific_ptr</code></link> object for storing
10513            a pointer to an object of type <code><phrase role="identifier">T</phrase></code>
10514            specific to each fiber. When <code><phrase role="identifier">reset</phrase><phrase
10515            role="special">()</phrase></code> is called, or the fiber exits, <link linkend="class_fiber_specific_ptr"><code>fiber_specific_ptr</code></link> calls
10516            <code><phrase role="identifier">fn</phrase><phrase role="special">(</phrase><phrase
10517            role="keyword">this</phrase><phrase role="special">-&gt;</phrase><phrase
10518            role="identifier">get</phrase><phrase role="special">())</phrase></code>.
10519            If the no-arguments constructor is used, the default <code><phrase role="keyword">delete</phrase></code>-based
10520            cleanup function will be used to destroy the fiber-local objects.
10521          </para>
10522        </listitem>
10523      </varlistentry>
10524      <varlistentry>
10525        <term>Throws:</term>
10526        <listitem>
10527          <para>
10528            <code><phrase role="identifier">fiber_error</phrase></code> if an error
10529            occurs.
10530          </para>
10531        </listitem>
10532      </varlistentry>
10533    </variablelist>
10534    <bridgehead renderas="sect3" id="fiber.fls.h3">
10535      <phrase id="fiber.fls.destructor"/><link linkend="fiber.fls.destructor">Destructor</link>
10536    </bridgehead>
10537<programlisting><phrase role="special">~</phrase><phrase role="identifier">fiber_specific_ptr</phrase><phrase role="special">();</phrase>
10538</programlisting>
10539    <variablelist>
10540      <title></title>
10541      <varlistentry>
10542        <term>Requires:</term>
10543        <listitem>
10544          <para>
10545            All the fiber specific instances associated to this <link linkend="class_fiber_specific_ptr"><code>fiber_specific_ptr</code></link>
10546(except
10547            maybe the one associated to this fiber) must be nullptr.
10548          </para>
10549        </listitem>
10550      </varlistentry>
10551      <varlistentry>
10552        <term>Effects:</term>
10553        <listitem>
10554          <para>
10555            Calls <code><phrase role="keyword">this</phrase><phrase role="special">-&gt;</phrase><phrase
10556            role="identifier">reset</phrase><phrase role="special">()</phrase></code>
10557            to clean up the associated value for the current fiber, and destroys
10558            <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>.
10559          </para>
10560        </listitem>
10561      </varlistentry>
10562      <varlistentry>
10563        <term>Remarks:</term>
10564        <listitem>
10565          <para>
10566            The requirement is an implementation restriction. If the destructor promised
10567            to delete instances for all fibers, the implementation would be forced
10568            to maintain a list of all the fibers having an associated specific ptr,
10569            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
10570            outlive the fibers that use it.
10571          </para>
10572        </listitem>
10573      </varlistentry>
10574    </variablelist>
10575    <note>
10576      <para>
10577        Care needs to be taken to ensure that any fibers still running after an instance
10578        of <link linkend="class_fiber_specific_ptr"><code>fiber_specific_ptr</code></link> has been destroyed do not call
10579        any member functions on that instance.
10580      </para>
10581    </note>
10582    <para>
10583      <bridgehead renderas="sect4" id="fiber_specific_ptr_get_bridgehead">
10584  <phrase id="fiber_specific_ptr_get"/>
10585  <link linkend="fiber_specific_ptr_get">Member
10586      function <code>get</code>()</link>
10587</bridgehead>
10588    </para>
10589<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>
10590</programlisting>
10591    <variablelist>
10592      <title></title>
10593      <varlistentry>
10594        <term>Returns:</term>
10595        <listitem>
10596          <para>
10597            The pointer associated with the current fiber.
10598          </para>
10599        </listitem>
10600      </varlistentry>
10601      <varlistentry>
10602        <term>Throws:</term>
10603        <listitem>
10604          <para>
10605            Nothing.
10606          </para>
10607        </listitem>
10608      </varlistentry>
10609    </variablelist>
10610    <note>
10611      <para>
10612        The initial value associated with an instance of <link linkend="class_fiber_specific_ptr"><code>fiber_specific_ptr</code></link> is
10613        <code><phrase role="keyword">nullptr</phrase></code> for each fiber.
10614      </para>
10615    </note>
10616    <para>
10617      <bridgehead renderas="sect4" id="fiber_specific_ptr_operator_arrow_bridgehead">
10618  <phrase id="fiber_specific_ptr_operator_arrow"/>
10619  <link linkend="fiber_specific_ptr_operator_arrow">Member
10620      function <code>operator-&gt;</code>()</link>
10621</bridgehead>
10622    </para>
10623<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>
10624</programlisting>
10625    <variablelist>
10626      <title></title>
10627      <varlistentry>
10628        <term>Requires:</term>
10629        <listitem>
10630          <para>
10631            <code><phrase role="keyword">this</phrase><phrase role="special">-&gt;</phrase><phrase
10632            role="identifier">get</phrase><phrase role="special">()</phrase></code>
10633            is not <code><phrase role="keyword">nullptr</phrase></code>.
10634          </para>
10635        </listitem>
10636      </varlistentry>
10637      <varlistentry>
10638        <term>Returns:</term>
10639        <listitem>
10640          <para>
10641            <code><phrase role="keyword">this</phrase><phrase role="special">-&gt;</phrase><phrase
10642            role="identifier">get</phrase><phrase role="special">()</phrase></code>
10643          </para>
10644        </listitem>
10645      </varlistentry>
10646      <varlistentry>
10647        <term>Throws:</term>
10648        <listitem>
10649          <para>
10650            Nothing.
10651          </para>
10652        </listitem>
10653      </varlistentry>
10654    </variablelist>
10655    <para>
10656      <bridgehead renderas="sect4" id="fiber_specific_ptr_operator_star_bridgehead">
10657  <phrase id="fiber_specific_ptr_operator_star"/>
10658  <link linkend="fiber_specific_ptr_operator_star">Member
10659      function <code>operator*</code>()</link>
10660</bridgehead>
10661    </para>
10662<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>
10663</programlisting>
10664    <variablelist>
10665      <title></title>
10666      <varlistentry>
10667        <term>Requires:</term>
10668        <listitem>
10669          <para>
10670            <code><phrase role="keyword">this</phrase><phrase role="special">-&gt;</phrase><phrase
10671            role="identifier">get</phrase><phrase role="special">()</phrase></code>
10672            is not <code><phrase role="keyword">nullptr</phrase></code>.
10673          </para>
10674        </listitem>
10675      </varlistentry>
10676      <varlistentry>
10677        <term>Returns:</term>
10678        <listitem>
10679          <para>
10680            <code><phrase role="special">*(</phrase><phrase role="keyword">this</phrase><phrase
10681            role="special">-&gt;</phrase><phrase role="identifier">get</phrase><phrase
10682            role="special">())</phrase></code>
10683          </para>
10684        </listitem>
10685      </varlistentry>
10686      <varlistentry>
10687        <term>Throws:</term>
10688        <listitem>
10689          <para>
10690            Nothing.
10691          </para>
10692        </listitem>
10693      </varlistentry>
10694    </variablelist>
10695    <para>
10696      <bridgehead renderas="sect4" id="fiber_specific_ptr_release_bridgehead">
10697  <phrase id="fiber_specific_ptr_release"/>
10698  <link linkend="fiber_specific_ptr_release">Member
10699      function <code>release</code>()</link>
10700</bridgehead>
10701    </para>
10702<programlisting><phrase role="identifier">T</phrase> <phrase role="special">*</phrase> <phrase role="identifier">release</phrase><phrase role="special">();</phrase>
10703</programlisting>
10704    <variablelist>
10705      <title></title>
10706      <varlistentry>
10707        <term>Effects:</term>
10708        <listitem>
10709          <para>
10710            Return <code><phrase role="keyword">this</phrase><phrase role="special">-&gt;</phrase><phrase
10711            role="identifier">get</phrase><phrase role="special">()</phrase></code>
10712            and store <code><phrase role="keyword">nullptr</phrase></code> as the
10713            pointer associated with the current fiber without invoking the cleanup
10714            function.
10715          </para>
10716        </listitem>
10717      </varlistentry>
10718      <varlistentry>
10719        <term>Postcondition:</term>
10720        <listitem>
10721          <para>
10722            <code><phrase role="keyword">this</phrase><phrase role="special">-&gt;</phrase><phrase
10723            role="identifier">get</phrase><phrase role="special">()==</phrase><phrase
10724            role="keyword">nullptr</phrase></code>
10725          </para>
10726        </listitem>
10727      </varlistentry>
10728      <varlistentry>
10729        <term>Throws:</term>
10730        <listitem>
10731          <para>
10732            Nothing.
10733          </para>
10734        </listitem>
10735      </varlistentry>
10736    </variablelist>
10737    <para>
10738      <bridgehead renderas="sect4" id="fiber_specific_ptr_reset_bridgehead">
10739  <phrase id="fiber_specific_ptr_reset"/>
10740  <link linkend="fiber_specific_ptr_reset">Member
10741      function <code>reset</code>()</link>
10742</bridgehead>
10743    </para>
10744<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>
10745</programlisting>
10746    <variablelist>
10747      <title></title>
10748      <varlistentry>
10749        <term>Effects:</term>
10750        <listitem>
10751          <para>
10752            If <code><phrase role="keyword">this</phrase><phrase role="special">-&gt;</phrase><phrase
10753            role="identifier">get</phrase><phrase role="special">()!=</phrase><phrase
10754            role="identifier">new_value</phrase></code> and <code><phrase role="keyword">this</phrase><phrase
10755            role="special">-&gt;</phrase><phrase role="identifier">get</phrase><phrase
10756            role="special">()</phrase></code> is not <code><phrase role="keyword">nullptr</phrase></code>,
10757            invoke <code><phrase role="keyword">delete</phrase> <phrase role="keyword">this</phrase><phrase
10758            role="special">-&gt;</phrase><phrase role="identifier">get</phrase><phrase
10759            role="special">()</phrase></code> or <code><phrase role="identifier">fn</phrase><phrase
10760            role="special">(</phrase><phrase role="keyword">this</phrase><phrase
10761            role="special">-&gt;</phrase><phrase role="identifier">get</phrase><phrase
10762            role="special">())</phrase></code> as appropriate. Store <code><phrase
10763            role="identifier">new_value</phrase></code> as the pointer associated
10764            with the current fiber.
10765          </para>
10766        </listitem>
10767      </varlistentry>
10768      <varlistentry>
10769        <term>Postcondition:</term>
10770        <listitem>
10771          <para>
10772            <code><phrase role="keyword">this</phrase><phrase role="special">-&gt;</phrase><phrase
10773            role="identifier">get</phrase><phrase role="special">()==</phrase><phrase
10774            role="identifier">new_value</phrase></code>
10775          </para>
10776        </listitem>
10777      </varlistentry>
10778      <varlistentry>
10779        <term>Throws:</term>
10780        <listitem>
10781          <para>
10782            Exception raised during cleanup of previous value.
10783          </para>
10784        </listitem>
10785      </varlistentry>
10786    </variablelist>
10787  </section>
10788  <section id="fiber.migration">
10789    <title><anchor id="migration"/><link linkend="fiber.migration">Migrating fibers
10790    between threads</link></title>
10791    <bridgehead renderas="sect3" id="fiber.migration.h0">
10792      <phrase id="fiber.migration.overview"/><link linkend="fiber.migration.overview">Overview</link>
10793    </bridgehead>
10794    <para>
10795      Each fiber owns a stack and manages its execution state, including all registers
10796      and CPU flags, the instruction pointer and the stack pointer. That means, in
10797      general, a fiber is not bound to a specific thread.<footnote id="fiber.migration.f0">
10798      <para>
10799        The <quote>main</quote> fiber on each thread, that is, the fiber on which
10800        the thread is launched, cannot migrate to any other thread. Also <emphasis
10801        role="bold">Boost.Fiber</emphasis> implicitly creates a dispatcher fiber
10802        for each thread &mdash; this cannot migrate either.
10803      </para>
10804      </footnote><superscript>,</superscript><footnote id="fiber.migration.f1">
10805      <para>
10806        Of course it would be problematic to migrate a fiber that relies on <link
10807        linkend="thread_local_storage">thread-local storage</link>.
10808      </para>
10809      </footnote>
10810    </para>
10811    <para>
10812      Migrating a fiber from a logical CPU with heavy workload to another logical
10813      CPU with a lighter workload might speed up the overall execution. Note that
10814      in the case of NUMA-architectures, it is not always advisable to migrate data
10815      between threads. Suppose fiber <emphasis>f</emphasis> is running on logical
10816      CPU <emphasis>cpu0</emphasis> which belongs to NUMA node <emphasis>node0</emphasis>.
10817      The data of <emphasis>f</emphasis> are allocated on the physical memory located
10818      at <emphasis>node0</emphasis>. Migrating the fiber from <emphasis>cpu0</emphasis>
10819      to another logical CPU <emphasis>cpuX</emphasis> which is part of a different
10820      NUMA node <emphasis>nodeX</emphasis> might reduce the performance of the application
10821      due to increased latency of memory access.
10822    </para>
10823    <para>
10824      Only fibers that are contained in <link linkend="class_algorithm"><code>algorithm</code></link>&#8217;s ready queue can
10825      migrate between threads. You cannot migrate a running fiber, nor one that is
10826      <link linkend="blocking"><emphasis>blocked</emphasis></link>. You cannot migrate
10827      a fiber if its <link linkend="context_is_context"><code>context::is_context()</code></link> method returns <code><phrase
10828      role="keyword">true</phrase></code> for <code><phrase role="identifier">pinned_context</phrase></code>.
10829    </para>
10830    <para>
10831      In <emphasis role="bold">Boost.Fiber</emphasis> a fiber is migrated by invoking
10832      <link linkend="context_detach"><code>context::detach()</code></link> on the thread from which the fiber migrates
10833      and <link linkend="context_attach"><code>context::attach()</code></link> on the thread to which the fiber migrates.
10834    </para>
10835    <para>
10836      Thus, fiber migration is accomplished by sharing state between instances of
10837      a user-coded <link linkend="class_algorithm"><code>algorithm</code></link> implementation running on different threads.
10838      The fiber&#8217;s original thread calls <link linkend="algorithm_awakened"><code>algorithm::awakened()</code></link>, passing
10839      the fiber&#8217;s <link linkend="class_context"><code>context</code></link><literal>*</literal>. The <code><phrase role="identifier">awakened</phrase><phrase
10840      role="special">()</phrase></code> implementation calls <link linkend="context_detach"><code>context::detach()</code></link>.
10841    </para>
10842    <para>
10843      At some later point, when the same or a different thread calls <link linkend="algorithm_pick_next"><code>algorithm::pick_next()</code></link>,
10844      the <code><phrase role="identifier">pick_next</phrase><phrase role="special">()</phrase></code>
10845      implementation selects a ready fiber and calls <link linkend="context_attach"><code>context::attach()</code></link> on
10846      it before returning it.
10847    </para>
10848    <para>
10849      As stated above, a <code><phrase role="identifier">context</phrase></code>
10850      for which <code><phrase role="identifier">is_context</phrase><phrase role="special">(</phrase><phrase
10851      role="identifier">pinned_context</phrase><phrase role="special">)</phrase>
10852      <phrase role="special">==</phrase> <phrase role="keyword">true</phrase></code>
10853      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>.
10854      It may only be returned from <code><phrase role="identifier">pick_next</phrase><phrase
10855      role="special">()</phrase></code> called by the <emphasis>same</emphasis> thread
10856      that passed that context to <code><phrase role="identifier">awakened</phrase><phrase
10857      role="special">()</phrase></code>.
10858    </para>
10859    <bridgehead renderas="sect3" id="fiber.migration.h1">
10860      <phrase id="fiber.migration.example_of_work_sharing"/><link linkend="fiber.migration.example_of_work_sharing">Example
10861      of work sharing</link>
10862    </bridgehead>
10863    <para>
10864      In the example <ulink url="../../examples/work_sharing.cpp">work_sharing.cpp</ulink>
10865      multiple worker fibers are created on the main thread. Each fiber gets a character
10866      as parameter at construction. This character is printed out ten times. Between
10867      each iteration the fiber calls <link linkend="this_fiber_yield"><code>this_fiber::yield()</code></link>. That puts
10868      the fiber in the ready queue of the fiber-scheduler <emphasis>shared_ready_queue</emphasis>,
10869      running in the current thread. The next fiber ready to be executed is dequeued
10870      from the shared ready queue and resumed by <emphasis>shared_ready_queue</emphasis>
10871      running on <emphasis>any participating thread</emphasis>.
10872    </para>
10873    <para>
10874      All instances of <emphasis>shared_ready_queue</emphasis> share one global concurrent
10875      queue, used as ready queue. This mechanism shares all worker fibers between
10876      all instances of <emphasis>shared_ready_queue</emphasis>, thus between all
10877      participating threads.
10878    </para>
10879    <bridgehead renderas="sect3" id="fiber.migration.h2">
10880      <phrase id="fiber.migration.setup_of_threads_and_fibers"/><link linkend="fiber.migration.setup_of_threads_and_fibers">Setup
10881      of threads and fibers</link>
10882    </bridgehead>
10883    <para>
10884      In <code><phrase role="identifier">main</phrase><phrase role="special">()</phrase></code>
10885      the fiber-scheduler is installed and the worker fibers and the threads are
10886      launched.
10887    </para>
10888    <para>
10889<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" />
10890
10891<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" />
10892    <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>
10893    <phrase role="special">++</phrase><phrase role="identifier">fiber_count</phrase><phrase role="special">;</phrase> <co id="fiber.migration.c4" linkends="fiber.migration.c5" />
10894<phrase role="special">}</phrase>
10895<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>
10896<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" />
10897    <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>
10898    <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>
10899    <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>
10900<phrase role="special">};</phrase>
10901<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" />
10902<phrase role="special">{</phrase>
10903    <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>
10904    <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" />
10905<phrase role="special">}</phrase> <co id="fiber.migration.c14" linkends="fiber.migration.c15" />
10906<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>
10907<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" />
10908    <phrase role="identifier">t</phrase><phrase role="special">.</phrase><phrase role="identifier">join</phrase><phrase role="special">();</phrase>
10909<phrase role="special">}</phrase>
10910</programlisting>
10911    </para>
10912    <calloutlist>
10913      <callout arearefs="fiber.migration.c0" id="fiber.migration.c1">
10914        <para>
10915          Install the scheduling algorithm <code><phrase role="identifier">boost</phrase><phrase
10916          role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase
10917          role="special">::</phrase><phrase role="identifier">algo</phrase><phrase
10918          role="special">::</phrase><phrase role="identifier">shared_work</phrase></code>
10919          in the main thread too, so each new fiber gets launched into the shared
10920          pool.
10921        </para>
10922      </callout>
10923      <callout arearefs="fiber.migration.c2" id="fiber.migration.c3">
10924        <para>
10925          Launch a number of worker fibers; each worker fiber picks up a character
10926          that is passed as parameter to fiber-function <code><phrase role="identifier">whatevah</phrase></code>.
10927          Each worker fiber gets detached.
10928        </para>
10929      </callout>
10930      <callout arearefs="fiber.migration.c4" id="fiber.migration.c5">
10931        <para>
10932          Increment fiber counter for each new fiber.
10933        </para>
10934      </callout>
10935      <callout arearefs="fiber.migration.c6" id="fiber.migration.c7">
10936        <para>
10937          Launch a couple of threads that join the work sharing.
10938        </para>
10939      </callout>
10940      <callout arearefs="fiber.migration.c8" id="fiber.migration.c9">
10941        <para>
10942          sync with other threads: allow them to start processing
10943        </para>
10944      </callout>
10945      <callout arearefs="fiber.migration.c10" id="fiber.migration.c11">
10946        <para>
10947          <code><phrase role="identifier">lock_type</phrase></code> is typedef'ed
10948          as <ulink url="http://en.cppreference.com/w/cpp/thread/unique_lock"><code><phrase
10949          role="identifier">std</phrase><phrase role="special">::</phrase><phrase
10950          role="identifier">unique_lock</phrase></code></ulink>&lt; <ulink url="http://en.cppreference.com/w/cpp/thread/mutex"><code><phrase
10951          role="identifier">std</phrase><phrase role="special">::</phrase><phrase
10952          role="identifier">mutex</phrase></code></ulink> &gt;
10953        </para>
10954      </callout>
10955      <callout arearefs="fiber.migration.c12" id="fiber.migration.c13">
10956        <para>
10957          Suspend main fiber and resume worker fibers in the meanwhile. Main fiber
10958          gets resumed (e.g returns from <code><phrase role="identifier">condition_variable_any</phrase><phrase
10959          role="special">::</phrase><phrase role="identifier">wait</phrase><phrase
10960          role="special">()</phrase></code>) if all worker fibers are complete.
10961        </para>
10962      </callout>
10963      <callout arearefs="fiber.migration.c14" id="fiber.migration.c15">
10964        <para>
10965          Releasing lock of mtx_count is required before joining the threads, otherwise
10966          the other threads would be blocked inside condition_variable::wait() and
10967          would never return (deadlock).
10968        </para>
10969      </callout>
10970      <callout arearefs="fiber.migration.c16" id="fiber.migration.c17">
10971        <para>
10972          wait for threads to terminate
10973        </para>
10974      </callout>
10975    </calloutlist>
10976    <para>
10977      The start of the threads is synchronized with a barrier. The main fiber of
10978      each thread (including main thread) is suspended until all worker fibers are
10979      complete. When the main fiber returns from <link linkend="condition_variable_wait"><code>condition_variable::wait()</code></link>,
10980      the thread terminates: the main thread joins all other threads.
10981    </para>
10982    <para>
10983<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>
10984    <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">ostringstream</phrase> <phrase role="identifier">buffer</phrase><phrase role="special">;</phrase>
10985    <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>
10986    <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>
10987    <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" />
10988    <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" />
10989    <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>
10990    <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" />
10991    <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>
10992<phrase role="special">}</phrase>
10993</programlisting>
10994    </para>
10995    <calloutlist>
10996      <callout arearefs="fiber.migration.c18" id="fiber.migration.c19">
10997        <para>
10998          Install the scheduling algorithm <code><phrase role="identifier">boost</phrase><phrase
10999          role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase
11000          role="special">::</phrase><phrase role="identifier">algo</phrase><phrase
11001          role="special">::</phrase><phrase role="identifier">shared_work</phrase></code>
11002          in order to join the work sharing.
11003        </para>
11004      </callout>
11005      <callout arearefs="fiber.migration.c20" id="fiber.migration.c21">
11006        <para>
11007          sync with other threads: allow them to start processing
11008        </para>
11009      </callout>
11010      <callout arearefs="fiber.migration.c22" id="fiber.migration.c23">
11011        <para>
11012          Suspend main fiber and resume worker fibers in the meanwhile. Main fiber
11013          gets resumed (e.g returns from <code><phrase role="identifier">condition_variable_any</phrase><phrase
11014          role="special">::</phrase><phrase role="identifier">wait</phrase><phrase
11015          role="special">()</phrase></code>) if all worker fibers are complete.
11016        </para>
11017      </callout>
11018    </calloutlist>
11019    <para>
11020      Each worker fiber executes function <code><phrase role="identifier">whatevah</phrase><phrase
11021      role="special">()</phrase></code> with character <code><phrase role="identifier">me</phrase></code>
11022      as parameter. The fiber yields in a loop and prints out a message if it was
11023      migrated to another thread.
11024    </para>
11025    <para>
11026<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>
11027    <phrase role="keyword">try</phrase> <phrase role="special">{</phrase>
11028        <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" />
11029        <phrase role="special">{</phrase>
11030            <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">ostringstream</phrase> <phrase role="identifier">buffer</phrase><phrase role="special">;</phrase>
11031            <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>
11032            <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>
11033        <phrase role="special">}</phrase>
11034        <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" />
11035            <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" />
11036            <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" />
11037            <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" />
11038                <phrase role="identifier">my_thread</phrase> <phrase role="special">=</phrase> <phrase role="identifier">new_thread</phrase><phrase role="special">;</phrase>
11039                <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">ostringstream</phrase> <phrase role="identifier">buffer</phrase><phrase role="special">;</phrase>
11040                <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>
11041                <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>
11042            <phrase role="special">}</phrase>
11043        <phrase role="special">}</phrase>
11044    <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>
11045    <phrase role="special">}</phrase>
11046    <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>
11047    <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" />
11048        <phrase role="identifier">lk</phrase><phrase role="special">.</phrase><phrase role="identifier">unlock</phrase><phrase role="special">();</phrase>
11049        <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" />
11050    <phrase role="special">}</phrase>
11051<phrase role="special">}</phrase>
11052</programlisting>
11053    </para>
11054    <calloutlist>
11055      <callout arearefs="fiber.migration.c24" id="fiber.migration.c25">
11056        <para>
11057          get ID of initial thread
11058        </para>
11059      </callout>
11060      <callout arearefs="fiber.migration.c26" id="fiber.migration.c27">
11061        <para>
11062          loop ten times
11063        </para>
11064      </callout>
11065      <callout arearefs="fiber.migration.c28" id="fiber.migration.c29">
11066        <para>
11067          yield to other fibers
11068        </para>
11069      </callout>
11070      <callout arearefs="fiber.migration.c30" id="fiber.migration.c31">
11071        <para>
11072          get ID of current thread
11073        </para>
11074      </callout>
11075      <callout arearefs="fiber.migration.c32" id="fiber.migration.c33">
11076        <para>
11077          test if fiber was migrated to another thread
11078        </para>
11079      </callout>
11080      <callout arearefs="fiber.migration.c34" id="fiber.migration.c35">
11081        <para>
11082          Decrement fiber counter for each completed fiber.
11083        </para>
11084      </callout>
11085      <callout arearefs="fiber.migration.c36" id="fiber.migration.c37">
11086        <para>
11087          Notify all fibers waiting on <code><phrase role="identifier">cnd_count</phrase></code>.
11088        </para>
11089      </callout>
11090    </calloutlist>
11091    <bridgehead renderas="sect3" id="fiber.migration.h3">
11092      <phrase id="fiber.migration.scheduling_fibers"/><link linkend="fiber.migration.scheduling_fibers">Scheduling
11093      fibers</link>
11094    </bridgehead>
11095    <para>
11096      The fiber scheduler <code><phrase role="identifier">shared_ready_queue</phrase></code>
11097      is like <code><phrase role="identifier">round_robin</phrase></code>, except
11098      that it shares a common ready queue among all participating threads. A thread
11099      participates in this pool by executing <link linkend="use_scheduling_algorithm"><code>use_scheduling_algorithm()</code></link>
11100before
11101      any other <emphasis role="bold">Boost.Fiber</emphasis> operation.
11102    </para>
11103    <para>
11104      The important point about the ready queue is that it&#8217;s a class static, common
11105      to all instances of shared_ready_queue. Fibers that are enqueued via <link linkend="algorithm_awakened"><code>algorithm::awakened()</code></link> (fibers
11106      that are ready to be resumed) are thus available to all threads. It is required
11107      to reserve a separate, scheduler-specific queue for the thread&#8217;s main fiber
11108      and dispatcher fibers: these may <emphasis>not</emphasis> be shared between
11109      threads! When we&#8217;re passed either of these fibers, push it there instead of
11110      in the shared queue: it would be Bad News for thread B to retrieve and attempt
11111      to execute thread A&#8217;s main fiber.
11112    </para>
11113    <para>
11114      [awakened_ws]
11115    </para>
11116    <para>
11117      When <link linkend="algorithm_pick_next"><code>algorithm::pick_next()</code></link> gets called inside one thread,
11118      a fiber is dequeued from <emphasis>rqueue_</emphasis> and will be resumed in
11119      that thread.
11120    </para>
11121    <para>
11122      [pick_next_ws]
11123    </para>
11124    <para>
11125      The source code above is found in <ulink url="../../examples/work_sharing.cpp">work_sharing.cpp</ulink>.
11126    </para>
11127  </section>
11128  <section id="fiber.callbacks">
11129    <title><anchor id="callbacks"/><link linkend="fiber.callbacks">Integrating Fibers
11130    with Asynchronous Callbacks</link></title>
11131    <section id="fiber.callbacks.overview">
11132      <title><link linkend="fiber.callbacks.overview">Overview</link></title>
11133      <para>
11134        One of the primary benefits of <emphasis role="bold">Boost.Fiber</emphasis>
11135        is the ability to use asynchronous operations for efficiency, while at the
11136        same time structuring the calling code <emphasis>as if</emphasis> the operations
11137        were synchronous. Asynchronous operations provide completion notification
11138        in a variety of ways, but most involve a callback function of some kind.
11139        This section discusses tactics for interfacing <emphasis role="bold">Boost.Fiber</emphasis>
11140        with an arbitrary async operation.
11141      </para>
11142      <para>
11143        For purposes of illustration, consider the following hypothetical API:
11144      </para>
11145      <para>
11146<programlisting><phrase role="keyword">class</phrase> <phrase role="identifier">AsyncAPI</phrase> <phrase role="special">{</phrase>
11147<phrase role="keyword">public</phrase><phrase role="special">:</phrase>
11148    <phrase role="comment">// constructor acquires some resource that can be read and written</phrase>
11149    <phrase role="identifier">AsyncAPI</phrase><phrase role="special">();</phrase>
11150
11151    <phrase role="comment">// callbacks accept an int error code; 0 == success</phrase>
11152    <phrase role="keyword">typedef</phrase> <phrase role="keyword">int</phrase> <phrase role="identifier">errorcode</phrase><phrase role="special">;</phrase>
11153
11154    <phrase role="comment">// write callback only needs to indicate success or failure</phrase>
11155    <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>
11156    <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>
11157
11158    <phrase role="comment">// read callback needs to accept both errorcode and data</phrase>
11159    <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>
11160    <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>
11161
11162    <phrase role="comment">// ... other operations ...</phrase>
11163<phrase role="special">};</phrase>
11164</programlisting>
11165      </para>
11166      <para>
11167        The significant points about each of <code><phrase role="identifier">init_write</phrase><phrase
11168        role="special">()</phrase></code> and <code><phrase role="identifier">init_read</phrase><phrase
11169        role="special">()</phrase></code> are:
11170      </para>
11171      <itemizedlist>
11172        <listitem>
11173          <simpara>
11174            The <code><phrase role="identifier">AsyncAPI</phrase></code> method only
11175            initiates the operation. It returns immediately, while the requested
11176            operation is still pending.
11177          </simpara>
11178        </listitem>
11179        <listitem>
11180          <simpara>
11181            The method accepts a callback. When the operation completes, the callback
11182            is called with relevant parameters (error code, data if applicable).
11183          </simpara>
11184        </listitem>
11185      </itemizedlist>
11186      <para>
11187        We would like to wrap these asynchronous methods in functions that appear
11188        synchronous by blocking the calling fiber until the operation completes.
11189        This lets us use the wrapper function&#8217;s return value to deliver relevant data.
11190      </para>
11191      <tip>
11192        <para>
11193          <link linkend="class_promise"><code>promise&lt;&gt;</code></link> and <link linkend="class_future"><code>future&lt;&gt;</code></link> are your friends
11194          here.
11195        </para>
11196      </tip>
11197    </section>
11198    <section id="fiber.callbacks.return_errorcode">
11199      <title><link linkend="fiber.callbacks.return_errorcode">Return Errorcode</link></title>
11200      <para>
11201        The <code><phrase role="identifier">AsyncAPI</phrase><phrase role="special">::</phrase><phrase
11202        role="identifier">init_write</phrase><phrase role="special">()</phrase></code>
11203        callback passes only an <code><phrase role="identifier">errorcode</phrase></code>.
11204        If we simply want the blocking wrapper to return that <code><phrase role="identifier">errorcode</phrase></code>,
11205        this is an extremely straightforward use of <link linkend="class_promise"><code>promise&lt;&gt;</code></link> and
11206        <link linkend="class_future"><code>future&lt;&gt;</code></link>:
11207      </para>
11208      <para>
11209<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>
11210    <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>
11211    <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>
11212    <phrase role="comment">// In general, even though we block waiting for future::get() and therefore</phrase>
11213    <phrase role="comment">// won't destroy 'promise' until promise::set_value() has been called, we</phrase>
11214    <phrase role="comment">// are advised that with threads it's possible for ~promise() to be</phrase>
11215    <phrase role="comment">// entered before promise::set_value() has returned. While that shouldn't</phrase>
11216    <phrase role="comment">// happen with fibers::promise, a robust way to deal with the lifespan</phrase>
11217    <phrase role="comment">// issue is to bind 'promise' into our lambda. Since promise is move-only,</phrase>
11218    <phrase role="comment">// use initialization capture.</phrase>
11219<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>
11220    <phrase role="identifier">api</phrase><phrase role="special">.</phrase><phrase role="identifier">init_write</phrase><phrase role="special">(</phrase>
11221        <phrase role="identifier">data</phrase><phrase role="special">,</phrase>
11222        <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>
11223                            <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>
11224                  <phrase role="special">});</phrase>
11225
11226<phrase role="preprocessor">#else</phrase> <phrase role="comment">// defined(BOOST_NO_CXX14_INITIALIZED_LAMBDA_CAPTURES)</phrase>
11227    <phrase role="identifier">api</phrase><phrase role="special">.</phrase><phrase role="identifier">init_write</phrase><phrase role="special">(</phrase>
11228        <phrase role="identifier">data</phrase><phrase role="special">,</phrase>
11229        <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>
11230                     <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>
11231            <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>
11232        <phrase role="special">},</phrase>
11233        <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>
11234        <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>
11235<phrase role="preprocessor">#endif</phrase> <phrase role="comment">// BOOST_NO_CXX14_INITIALIZED_LAMBDA_CAPTURES</phrase>
11236
11237    <phrase role="keyword">return</phrase> <phrase role="identifier">future</phrase><phrase role="special">.</phrase><phrase role="identifier">get</phrase><phrase role="special">();</phrase>
11238<phrase role="special">}</phrase>
11239</programlisting>
11240      </para>
11241      <para>
11242        All we have to do is:
11243      </para>
11244      <orderedlist>
11245        <listitem>
11246          <simpara>
11247            Instantiate a <code><phrase role="identifier">promise</phrase><phrase
11248            role="special">&lt;&gt;</phrase></code> of correct type.
11249          </simpara>
11250        </listitem>
11251        <listitem>
11252          <simpara>
11253            Obtain its <code><phrase role="identifier">future</phrase><phrase role="special">&lt;&gt;</phrase></code>.
11254          </simpara>
11255        </listitem>
11256        <listitem>
11257          <simpara>
11258            Arrange for the callback to call <link linkend="promise_set_value"><code>promise::set_value()</code></link>.
11259          </simpara>
11260        </listitem>
11261        <listitem>
11262          <simpara>
11263            Block on <link linkend="future_get"><code>future::get()</code></link>.
11264          </simpara>
11265        </listitem>
11266      </orderedlist>
11267      <note>
11268        <para>
11269          This tactic for resuming a pending fiber works even if the callback is
11270          called on a different thread than the one on which the initiating fiber
11271          is running. In fact, <ulink url="../../examples/adapt_callbacks.cpp">the
11272          example program&#8217;s</ulink> dummy <code><phrase role="identifier">AsyncAPI</phrase></code>
11273          implementation illustrates that: it simulates async I/O by launching a
11274          new thread that sleeps briefly and then calls the relevant callback.
11275        </para>
11276      </note>
11277    </section>
11278    <section id="fiber.callbacks.success_or_exception">
11279      <title><link linkend="fiber.callbacks.success_or_exception">Success or Exception</link></title>
11280      <para>
11281        A wrapper more aligned with modern C++ practice would use an exception, rather
11282        than an <code><phrase role="identifier">errorcode</phrase></code>, to communicate
11283        failure to its caller. This is straightforward to code in terms of <code><phrase
11284        role="identifier">write_ec</phrase><phrase role="special">()</phrase></code>:
11285      </para>
11286      <para>
11287<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>
11288    <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>
11289    <phrase role="keyword">if</phrase> <phrase role="special">(</phrase> <phrase role="identifier">ec</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
11290        <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>
11291    <phrase role="special">}</phrase>
11292<phrase role="special">}</phrase>
11293</programlisting>
11294      </para>
11295      <para>
11296        The point is that since each fiber has its own stack, you need not repeat
11297        messy boilerplate: normal encapsulation works.
11298      </para>
11299    </section>
11300    <section id="fiber.callbacks.return_errorcode_or_data">
11301      <title><link linkend="fiber.callbacks.return_errorcode_or_data">Return Errorcode
11302      or Data</link></title>
11303      <para>
11304        Things get a bit more interesting when the async operation&#8217;s callback passes
11305        multiple data items of interest. One approach would be to use <code><phrase
11306        role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">pair</phrase><phrase
11307        role="special">&lt;&gt;</phrase></code> to capture both:
11308      </para>
11309      <para>
11310<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>
11311    <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>
11312    <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>
11313    <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>
11314    <phrase role="comment">// We promise that both 'promise' and 'future' will survive until our</phrase>
11315    <phrase role="comment">// lambda has been called.</phrase>
11316<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>
11317    <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>
11318                            <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>
11319                  <phrase role="special">});</phrase>
11320<phrase role="preprocessor">#else</phrase> <phrase role="comment">// defined(BOOST_NO_CXX14_INITIALIZED_LAMBDA_CAPTURES)</phrase>
11321    <phrase role="identifier">api</phrase><phrase role="special">.</phrase><phrase role="identifier">init_read</phrase><phrase role="special">(</phrase>
11322            <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>
11323                          <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>
11324                            <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>
11325                  <phrase role="special">},</phrase>
11326                  <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>
11327                  <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>
11328                  <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>
11329<phrase role="preprocessor">#endif</phrase> <phrase role="comment">// BOOST_NO_CXX14_INITIALIZED_LAMBDA_CAPTURES</phrase>
11330    <phrase role="keyword">return</phrase> <phrase role="identifier">future</phrase><phrase role="special">.</phrase><phrase role="identifier">get</phrase><phrase role="special">();</phrase>
11331<phrase role="special">}</phrase>
11332</programlisting>
11333      </para>
11334      <para>
11335        Once you bundle the interesting data in <code><phrase role="identifier">std</phrase><phrase
11336        role="special">::</phrase><phrase role="identifier">pair</phrase><phrase
11337        role="special">&lt;&gt;</phrase></code>, the code is effectively identical
11338        to <code><phrase role="identifier">write_ec</phrase><phrase role="special">()</phrase></code>.
11339        You can call it like this:
11340      </para>
11341      <para>
11342<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>
11343</programlisting>
11344      </para>
11345    </section>
11346    <section id="fiber.callbacks.data_or_exception">
11347      <title><anchor id="Data_or_Exception"/><link linkend="fiber.callbacks.data_or_exception">Data
11348      or Exception</link></title>
11349      <para>
11350        But a more natural API for a function that obtains data is to return only
11351        the data on success, throwing an exception on error.
11352      </para>
11353      <para>
11354        As with <code><phrase role="identifier">write</phrase><phrase role="special">()</phrase></code>
11355        above, it&#8217;s certainly possible to code a <code><phrase role="identifier">read</phrase><phrase
11356        role="special">()</phrase></code> wrapper in terms of <code><phrase role="identifier">read_ec</phrase><phrase
11357        role="special">()</phrase></code>. But since a given application is unlikely
11358        to need both, let&#8217;s code <code><phrase role="identifier">read</phrase><phrase
11359        role="special">()</phrase></code> from scratch, leveraging <link linkend="promise_set_exception"><code>promise::set_exception()</code></link>:
11360      </para>
11361      <para>
11362<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>
11363    <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>
11364    <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>
11365    <phrase role="comment">// Both 'promise' and 'future' will survive until our lambda has been</phrase>
11366    <phrase role="comment">// called.</phrase>
11367<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>
11368    <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>
11369                           <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>
11370                               <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>
11371                           <phrase role="special">}</phrase> <phrase role="keyword">else</phrase> <phrase role="special">{</phrase>
11372                               <phrase role="identifier">promise</phrase><phrase role="special">.</phrase><phrase role="identifier">set_exception</phrase><phrase role="special">(</phrase>
11373                                       <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">make_exception_ptr</phrase><phrase role="special">(</phrase>
11374                                           <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>
11375                           <phrase role="special">}</phrase>
11376                  <phrase role="special">});</phrase>
11377<phrase role="preprocessor">#else</phrase> <phrase role="comment">// defined(BOOST_NO_CXX14_INITIALIZED_LAMBDA_CAPTURES)</phrase>
11378    <phrase role="identifier">api</phrase><phrase role="special">.</phrase><phrase role="identifier">init_read</phrase><phrase role="special">(</phrase>
11379            <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>
11380                          <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>
11381                           <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>
11382                               <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>
11383                           <phrase role="special">}</phrase> <phrase role="keyword">else</phrase> <phrase role="special">{</phrase>
11384                               <phrase role="identifier">promise</phrase><phrase role="special">.</phrase><phrase role="identifier">set_exception</phrase><phrase role="special">(</phrase>
11385                                       <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">make_exception_ptr</phrase><phrase role="special">(</phrase>
11386                                           <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>
11387                           <phrase role="special">}</phrase>
11388                  <phrase role="special">},</phrase>
11389                  <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>
11390                  <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>
11391                  <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>
11392<phrase role="preprocessor">#endif</phrase> <phrase role="comment">// BOOST_NO_CXX14_INITIALIZED_LAMBDA_CAPTURES</phrase>
11393    <phrase role="keyword">return</phrase> <phrase role="identifier">future</phrase><phrase role="special">.</phrase><phrase role="identifier">get</phrase><phrase role="special">();</phrase>
11394<phrase role="special">}</phrase>
11395</programlisting>
11396      </para>
11397      <para>
11398        <link linkend="future_get"><code>future::get()</code></link> will do the right thing, either returning <code><phrase
11399        role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase></code>
11400        or throwing an exception.
11401      </para>
11402    </section>
11403    <section id="fiber.callbacks.success_error_virtual_methods">
11404      <title><link linkend="fiber.callbacks.success_error_virtual_methods">Success/Error
11405      Virtual Methods</link></title>
11406      <para>
11407        One classic approach to completion notification is to define an abstract
11408        base class with <code><phrase role="identifier">success</phrase><phrase role="special">()</phrase></code>
11409        and <code><phrase role="identifier">error</phrase><phrase role="special">()</phrase></code>
11410        methods. Code wishing to perform async I/O must derive a subclass, override
11411        each of these methods and pass the async operation a pointer to a subclass
11412        instance. The abstract base class might look like this:
11413      </para>
11414      <para>
11415<programlisting><phrase role="comment">// every async operation receives a subclass instance of this abstract base</phrase>
11416<phrase role="comment">// class through which to communicate its result</phrase>
11417<phrase role="keyword">struct</phrase> <phrase role="identifier">Response</phrase> <phrase role="special">{</phrase>
11418    <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>
11419
11420    <phrase role="comment">// called if the operation succeeds</phrase>
11421    <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>
11422
11423    <phrase role="comment">// called if the operation fails</phrase>
11424    <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>
11425<phrase role="special">};</phrase>
11426</programlisting>
11427      </para>
11428      <para>
11429        Now the <code><phrase role="identifier">AsyncAPI</phrase></code> operation
11430        might look more like this:
11431      </para>
11432      <para>
11433<programlisting><phrase role="comment">// derive Response subclass, instantiate, pass Response::ptr</phrase>
11434<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>
11435</programlisting>
11436      </para>
11437      <para>
11438        We can address this by writing a one-size-fits-all <code><phrase role="identifier">PromiseResponse</phrase></code>:
11439      </para>
11440      <para>
11441<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>
11442<phrase role="keyword">public</phrase><phrase role="special">:</phrase>
11443    <phrase role="comment">// called if the operation succeeds</phrase>
11444    <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>
11445        <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>
11446    <phrase role="special">}</phrase>
11447
11448    <phrase role="comment">// called if the operation fails</phrase>
11449    <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>
11450        <phrase role="identifier">promise_</phrase><phrase role="special">.</phrase><phrase role="identifier">set_exception</phrase><phrase role="special">(</phrase>
11451                <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">make_exception_ptr</phrase><phrase role="special">(</phrase>
11452                    <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>
11453    <phrase role="special">}</phrase>
11454
11455    <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>
11456        <phrase role="keyword">return</phrase> <phrase role="identifier">promise_</phrase><phrase role="special">.</phrase><phrase role="identifier">get_future</phrase><phrase role="special">();</phrase>
11457    <phrase role="special">}</phrase>
11458
11459<phrase role="keyword">private</phrase><phrase role="special">:</phrase>
11460    <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>
11461<phrase role="special">};</phrase>
11462</programlisting>
11463      </para>
11464      <para>
11465        Now we can simply obtain the <code><phrase role="identifier">future</phrase><phrase
11466        role="special">&lt;&gt;</phrase></code> from that <code><phrase role="identifier">PromiseResponse</phrase></code>
11467        and wait on its <code><phrase role="identifier">get</phrase><phrase role="special">()</phrase></code>:
11468      </para>
11469      <para>
11470<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>
11471    <phrase role="comment">// Because init_read() requires a shared_ptr, we must allocate our</phrase>
11472    <phrase role="comment">// ResponsePromise on the heap, even though we know its lifespan.</phrase>
11473    <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>
11474    <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>
11475    <phrase role="comment">// Both 'promisep' and 'future' will survive until our lambda has been</phrase>
11476    <phrase role="comment">// called.</phrase>
11477    <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>
11478    <phrase role="keyword">return</phrase> <phrase role="identifier">future</phrase><phrase role="special">.</phrase><phrase role="identifier">get</phrase><phrase role="special">();</phrase>
11479<phrase role="special">}</phrase>
11480</programlisting>
11481      </para>
11482      <para>
11483        The source code above is found in <ulink url="../../examples/adapt_callbacks.cpp">adapt_callbacks.cpp</ulink>
11484        and <ulink url="../../examples/adapt_method_calls.cpp">adapt_method_calls.cpp</ulink>.
11485      </para>
11486    </section>
11487    <section id="fiber.callbacks.then_there_s____boost_asio__">
11488      <title><anchor id="callbacks_asio"/><link linkend="fiber.callbacks.then_there_s____boost_asio__">Then
11489      There&#8217;s <ulink url="http://www.boost.org/doc/libs/release/libs/asio/index.html">Boost.Asio</ulink></link></title>
11490      <para>
11491        Since the simplest form of Boost.Asio asynchronous operation completion token
11492        is a callback function, we could apply the same tactics for Asio as for our
11493        hypothetical <code><phrase role="identifier">AsyncAPI</phrase></code> asynchronous
11494        operations.
11495      </para>
11496      <para>
11497        Fortunately we need not. Boost.Asio incorporates a mechanism<footnote id="fiber.callbacks.then_there_s____boost_asio__.f0">
11498        <para>
11499          This mechanism has been proposed as a conventional way to allow the caller
11500          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>.
11501        </para>
11502        </footnote> by which the caller can customize the notification behavior of
11503        any async operation. Therefore we can construct a <emphasis>completion token</emphasis>
11504        which, when passed to a <ulink url="http://www.boost.org/doc/libs/release/libs/asio/index.html">Boost.Asio</ulink>
11505        async operation, requests blocking for the calling fiber.
11506      </para>
11507      <para>
11508        A typical Asio async function might look something like this:<footnote id="fiber.callbacks.then_there_s____boost_asio__.f1">
11509        <para>
11510          per <ulink url="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4045.pdf">N4045</ulink>
11511        </para>
11512        </footnote>
11513      </para>
11514<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>
11515<emphasis>deduced_return_type</emphasis>
11516<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>
11517<phrase role="special">{</phrase>
11518    <phrase role="comment">// construct handler_type instance from CompletionToken</phrase>
11519    <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>
11520    <phrase role="comment">// construct async_result instance from handler_type</phrase>
11521    <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>
11522
11523    <phrase role="comment">// ... arrange to call handler on completion ...</phrase>
11524    <phrase role="comment">// ... initiate actual I/O operation ...</phrase>
11525
11526    <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>
11527<phrase role="special">}</phrase>
11528</programlisting>
11529      <para>
11530        We will engage that mechanism, which is based on specializing Asio&#8217;s <code><phrase
11531        role="identifier">handler_type</phrase><phrase role="special">&lt;&gt;</phrase></code>
11532        template for the <code><phrase role="identifier">CompletionToken</phrase></code>
11533        type and the signature of the specific callback. The remainder of this discussion
11534        will refer back to <code><phrase role="identifier">async_something</phrase><phrase
11535        role="special">()</phrase></code> as the Asio async function under consideration.
11536      </para>
11537      <para>
11538        The implementation described below uses lower-level facilities than <code><phrase
11539        role="identifier">promise</phrase></code> and <code><phrase role="identifier">future</phrase></code>
11540        because the <code><phrase role="identifier">promise</phrase></code> mechanism
11541        interacts badly with <ulink url="http://www.boost.org/doc/libs/release/doc/html/boost_asio/reference/io_service/stop.html"><code><phrase
11542        role="identifier">io_service</phrase><phrase role="special">::</phrase><phrase
11543        role="identifier">stop</phrase><phrase role="special">()</phrase></code></ulink>.
11544        It produces <code><phrase role="identifier">broken_promise</phrase></code>
11545        exceptions.
11546      </para>
11547      <para>
11548        <code><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase
11549        role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase
11550        role="identifier">asio</phrase><phrase role="special">::</phrase><phrase
11551        role="identifier">yield</phrase></code> is a completion token of this kind.
11552        <code><phrase role="identifier">yield</phrase></code> is an instance of
11553        <code><phrase role="identifier">yield_t</phrase></code>:
11554      </para>
11555      <para>
11556<programlisting><phrase role="keyword">class</phrase> <phrase role="identifier">yield_t</phrase> <phrase role="special">{</phrase>
11557<phrase role="keyword">public</phrase><phrase role="special">:</phrase>
11558    <phrase role="identifier">yield_t</phrase><phrase role="special">()</phrase> <phrase role="special">=</phrase> <phrase role="keyword">default</phrase><phrase role="special">;</phrase>
11559
11560    <phrase role="comment">/**
11561     * @code
11562     * static yield_t yield;
11563     * boost::system::error_code myec;
11564     * func(yield[myec]);
11565     * @endcode
11566     * @c yield[myec] returns an instance of @c yield_t whose @c ec_ points
11567     * to @c myec. The expression @c yield[myec] &quot;binds&quot; @c myec to that
11568     * (anonymous) @c yield_t instance, instructing @c func() to store any
11569     * @c error_code it might produce into @c myec rather than throwing @c
11570     * boost::system::system_error.
11571     */</phrase>
11572    <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>
11573        <phrase role="identifier">yield_t</phrase> <phrase role="identifier">tmp</phrase><phrase role="special">;</phrase>
11574        <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>
11575        <phrase role="keyword">return</phrase> <phrase role="identifier">tmp</phrase><phrase role="special">;</phrase>
11576    <phrase role="special">}</phrase>
11577
11578<phrase role="comment">//private:</phrase>
11579    <phrase role="comment">// ptr to bound error_code instance if any</phrase>
11580    <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>
11581<phrase role="special">};</phrase>
11582</programlisting>
11583      </para>
11584      <para>
11585        <code><phrase role="identifier">yield_t</phrase></code> is in fact only a
11586        placeholder, a way to trigger Boost.Asio customization. It can bind a <ulink
11587        url="http://www.boost.org/doc/libs/release/libs/system/doc/reference.html#Class-error_code"><code><phrase
11588        role="identifier">boost</phrase><phrase role="special">::</phrase><phrase
11589        role="identifier">system</phrase><phrase role="special">::</phrase><phrase
11590        role="identifier">error_code</phrase></code></ulink> for use by the actual
11591        handler.
11592      </para>
11593      <para>
11594        <code><phrase role="identifier">yield</phrase></code> is declared as:
11595      </para>
11596      <para>
11597<programlisting><phrase role="comment">// canonical instance</phrase>
11598<phrase role="keyword">thread_local</phrase> <phrase role="identifier">yield_t</phrase> <phrase role="identifier">yield</phrase><phrase role="special">{};</phrase>
11599</programlisting>
11600      </para>
11601      <para>
11602        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
11603        role="identifier">boost</phrase><phrase role="special">::</phrase><phrase
11604        role="identifier">asio</phrase><phrase role="special">::</phrase><phrase
11605        role="identifier">handler_type</phrase><phrase role="special">&lt;&gt;</phrase></code></ulink>
11606        for <code><phrase role="identifier">yield_t</phrase></code>:
11607      </para>
11608      <para>
11609<programlisting><phrase role="comment">// Handler type specialisation for fibers::asio::yield.</phrase>
11610<phrase role="comment">// When 'yield' is passed as a completion handler which accepts only</phrase>
11611<phrase role="comment">// error_code, use yield_handler&lt;void&gt;. yield_handler will take care of the</phrase>
11612<phrase role="comment">// error_code one way or another.</phrase>
11613<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>
11614<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>
11615<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>
11616</programlisting>
11617      </para>
11618      <para>
11619        (There are actually four different specializations in <ulink url="../../examples/asio/detail/yield.hpp">detail/yield.hpp</ulink>,
11620        one for each of the four Asio async callback signatures we expect.)
11621      </para>
11622      <para>
11623        The above directs Asio to use <code><phrase role="identifier">yield_handler</phrase></code>
11624        as the actual handler for an async operation to which <code><phrase role="identifier">yield</phrase></code>
11625        is passed. There&#8217;s a generic <code><phrase role="identifier">yield_handler</phrase><phrase
11626        role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase></code>
11627        implementation and a <code><phrase role="identifier">yield_handler</phrase><phrase
11628        role="special">&lt;</phrase><phrase role="keyword">void</phrase><phrase role="special">&gt;</phrase></code>
11629        specialization. Let&#8217;s start with the <code><phrase role="special">&lt;</phrase><phrase
11630        role="keyword">void</phrase><phrase role="special">&gt;</phrase></code> specialization:
11631      </para>
11632      <para>
11633<programlisting><phrase role="comment">// yield_handler&lt;void&gt; is like yield_handler&lt;T&gt; without value_. In fact it's</phrase>
11634<phrase role="comment">// just like yield_handler_base.</phrase>
11635<phrase role="keyword">template</phrase><phrase role="special">&lt;&gt;</phrase>
11636<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>
11637<phrase role="keyword">public</phrase><phrase role="special">:</phrase>
11638    <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>
11639        <phrase role="identifier">yield_handler_base</phrase><phrase role="special">{</phrase> <phrase role="identifier">y</phrase> <phrase role="special">}</phrase> <phrase role="special">{</phrase>
11640    <phrase role="special">}</phrase>
11641
11642    <phrase role="comment">// nullary completion callback</phrase>
11643    <phrase role="keyword">void</phrase> <phrase role="keyword">operator</phrase><phrase role="special">()()</phrase> <phrase role="special">{</phrase>
11644        <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>
11645    <phrase role="special">}</phrase>
11646
11647    <phrase role="comment">// inherit operator()(error_code) overload from base class</phrase>
11648    <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>
11649<phrase role="special">};</phrase>
11650</programlisting>
11651      </para>
11652      <para>
11653        <code><phrase role="identifier">async_something</phrase><phrase role="special">()</phrase></code>,
11654        having consulted the <code><phrase role="identifier">handler_type</phrase><phrase
11655        role="special">&lt;&gt;</phrase></code> traits specialization, instantiates
11656        a <code><phrase role="identifier">yield_handler</phrase><phrase role="special">&lt;</phrase><phrase
11657        role="keyword">void</phrase><phrase role="special">&gt;</phrase></code> to
11658        be passed as the actual callback for the async operation. <code><phrase role="identifier">yield_handler</phrase></code>&#8217;s
11659        constructor accepts the <code><phrase role="identifier">yield_t</phrase></code>
11660        instance (the <code><phrase role="identifier">yield</phrase></code> object
11661        passed to the async function) and passes it along to <code><phrase role="identifier">yield_handler_base</phrase></code>:
11662      </para>
11663      <para>
11664<programlisting><phrase role="comment">// This class encapsulates common elements between yield_handler&lt;T&gt; (capturing</phrase>
11665<phrase role="comment">// a value to return from asio async function) and yield_handler&lt;void&gt; (no</phrase>
11666<phrase role="comment">// such value). See yield_handler&lt;T&gt; and its &lt;void&gt; specialization below. Both</phrase>
11667<phrase role="comment">// yield_handler&lt;T&gt; and yield_handler&lt;void&gt; are passed by value through</phrase>
11668<phrase role="comment">// various layers of asio functions. In other words, they're potentially</phrase>
11669<phrase role="comment">// copied multiple times. So key data such as the yield_completion instance</phrase>
11670<phrase role="comment">// must be stored in our async_result&lt;yield_handler&lt;&gt;&gt; specialization, which</phrase>
11671<phrase role="comment">// should be instantiated only once.</phrase>
11672<phrase role="keyword">class</phrase> <phrase role="identifier">yield_handler_base</phrase> <phrase role="special">{</phrase>
11673<phrase role="keyword">public</phrase><phrase role="special">:</phrase>
11674    <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>
11675        <phrase role="comment">// capture the context* associated with the running fiber</phrase>
11676        <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>
11677        <phrase role="comment">// capture the passed yield_t</phrase>
11678        <phrase role="identifier">yt_</phrase><phrase role="special">(</phrase> <phrase role="identifier">y</phrase> <phrase role="special">)</phrase> <phrase role="special">{</phrase>
11679    <phrase role="special">}</phrase>
11680
11681    <phrase role="comment">// completion callback passing only (error_code)</phrase>
11682    <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>
11683        <phrase role="identifier">BOOST_ASSERT_MSG</phrase><phrase role="special">(</phrase> <phrase role="identifier">ycomp_</phrase><phrase role="special">,</phrase>
11684                          <phrase role="string">&quot;Must inject yield_completion* &quot;</phrase>
11685                          <phrase role="string">&quot;before calling yield_handler_base::operator()()&quot;</phrase><phrase role="special">);</phrase>
11686        <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>
11687                          <phrase role="string">&quot;Must inject boost::system::error_code* &quot;</phrase>
11688                          <phrase role="string">&quot;before calling yield_handler_base::operator()()&quot;</phrase><phrase role="special">);</phrase>
11689        <phrase role="comment">// If originating fiber is busy testing state_ flag, wait until it</phrase>
11690        <phrase role="comment">// has observed (completed != state_).</phrase>
11691        <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>
11692        <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>
11693        <phrase role="comment">// Notify a subsequent yield_completion::wait() call that it need not</phrase>
11694        <phrase role="comment">// suspend.</phrase>
11695        <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>
11696        <phrase role="comment">// set the error_code bound by yield_t</phrase>
11697        <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>
11698        <phrase role="comment">// unlock the lock that protects state_</phrase>
11699        <phrase role="identifier">lk</phrase><phrase role="special">.</phrase><phrase role="identifier">unlock</phrase><phrase role="special">();</phrase>
11700        <phrase role="comment">// If ctx_ is still active, e.g. because the async operation</phrase>
11701        <phrase role="comment">// immediately called its callback (this method!) before the asio</phrase>
11702        <phrase role="comment">// async function called async_result_base::get(), we must not set it</phrase>
11703        <phrase role="comment">// ready.</phrase>
11704        <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>
11705            <phrase role="comment">// wake the fiber</phrase>
11706            <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>
11707        <phrase role="special">}</phrase>
11708    <phrase role="special">}</phrase>
11709
11710<phrase role="comment">//private:</phrase>
11711    <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>
11712    <phrase role="identifier">yield_t</phrase>                         <phrase role="identifier">yt_</phrase><phrase role="special">;</phrase>
11713    <phrase role="comment">// We depend on this pointer to yield_completion, which will be injected</phrase>
11714    <phrase role="comment">// by async_result.</phrase>
11715    <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>
11716<phrase role="special">};</phrase>
11717</programlisting>
11718      </para>
11719      <para>
11720        <code><phrase role="identifier">yield_handler_base</phrase></code> stores
11721        a copy of the <code><phrase role="identifier">yield_t</phrase></code> instance
11722        &mdash; which, as shown above, contains only an <code><phrase role="identifier">error_code</phrase><phrase
11723        role="special">*</phrase></code>. It also captures the <link linkend="class_context"><code>context</code></link>*
11724        for the currently-running fiber by calling <link linkend="context_active"><code>context::active()</code></link>.
11725      </para>
11726      <para>
11727        You will notice that <code><phrase role="identifier">yield_handler_base</phrase></code>
11728        has one more data member (<code><phrase role="identifier">ycomp_</phrase></code>)
11729        that is initialized to <code><phrase role="keyword">nullptr</phrase></code>
11730        by its constructor &mdash; though its <code><phrase role="keyword">operator</phrase><phrase
11731        role="special">()()</phrase></code> method relies on <code><phrase role="identifier">ycomp_</phrase></code>
11732        being non-null. More on this in a moment.
11733      </para>
11734      <para>
11735        Having constructed the <code><phrase role="identifier">yield_handler</phrase><phrase
11736        role="special">&lt;</phrase><phrase role="keyword">void</phrase><phrase role="special">&gt;</phrase></code>
11737        instance, <code><phrase role="identifier">async_something</phrase><phrase
11738        role="special">()</phrase></code> goes on to construct an <code><phrase role="identifier">async_result</phrase></code>
11739        specialized for the <code><phrase role="identifier">handler_type</phrase><phrase
11740        role="special">&lt;&gt;::</phrase><phrase role="identifier">type</phrase></code>:
11741        in this case, <code><phrase role="identifier">async_result</phrase><phrase
11742        role="special">&lt;</phrase><phrase role="identifier">yield_handler</phrase><phrase
11743        role="special">&lt;</phrase><phrase role="keyword">void</phrase><phrase role="special">&gt;&gt;</phrase></code>.
11744        It passes the <code><phrase role="identifier">yield_handler</phrase><phrase
11745        role="special">&lt;</phrase><phrase role="keyword">void</phrase><phrase role="special">&gt;</phrase></code>
11746        instance to the new <code><phrase role="identifier">async_result</phrase></code>
11747        instance.
11748      </para>
11749      <para>
11750<programlisting><phrase role="comment">// Without the need to handle a passed value, our yield_handler&lt;void&gt;</phrase>
11751<phrase role="comment">// specialization is just like async_result_base.</phrase>
11752<phrase role="keyword">template</phrase><phrase role="special">&lt;&gt;</phrase>
11753<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>
11754    <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>
11755<phrase role="keyword">public</phrase><phrase role="special">:</phrase>
11756    <phrase role="keyword">typedef</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">type</phrase><phrase role="special">;</phrase>
11757
11758    <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>
11759        <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>
11760    <phrase role="special">}</phrase>
11761<phrase role="special">};</phrase>
11762</programlisting>
11763      </para>
11764      <para>
11765        Naturally that leads us straight to <code><phrase role="identifier">async_result_base</phrase></code>:
11766      </para>
11767      <para>
11768<programlisting><phrase role="comment">// Factor out commonality between async_result&lt;yield_handler&lt;T&gt;&gt; and</phrase>
11769<phrase role="comment">// async_result&lt;yield_handler&lt;void&gt;&gt;</phrase>
11770<phrase role="keyword">class</phrase> <phrase role="identifier">async_result_base</phrase> <phrase role="special">{</phrase>
11771<phrase role="keyword">public</phrase><phrase role="special">:</phrase>
11772    <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>
11773            <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>
11774        <phrase role="comment">// Inject ptr to our yield_completion instance into this</phrase>
11775        <phrase role="comment">// yield_handler&lt;&gt;.</phrase>
11776        <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>
11777        <phrase role="comment">// if yield_t didn't bind an error_code, make yield_handler_base's</phrase>
11778        <phrase role="comment">// error_code* point to an error_code local to this object so</phrase>
11779        <phrase role="comment">// yield_handler_base::operator() can unconditionally store through</phrase>
11780        <phrase role="comment">// its error_code*</phrase>
11781        <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>
11782            <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>
11783        <phrase role="special">}</phrase>
11784    <phrase role="special">}</phrase>
11785
11786    <phrase role="keyword">void</phrase> <phrase role="identifier">get</phrase><phrase role="special">()</phrase> <phrase role="special">{</phrase>
11787        <phrase role="comment">// Unless yield_handler_base::operator() has already been called,</phrase>
11788        <phrase role="comment">// suspend the calling fiber until that call.</phrase>
11789        <phrase role="identifier">ycomp_</phrase><phrase role="special">-&gt;</phrase><phrase role="identifier">wait</phrase><phrase role="special">();</phrase>
11790        <phrase role="comment">// The only way our own ec_ member could have a non-default value is</phrase>
11791        <phrase role="comment">// if our yield_handler did not have a bound error_code AND the</phrase>
11792        <phrase role="comment">// completion callback passed a non-default error_code.</phrase>
11793        <phrase role="keyword">if</phrase> <phrase role="special">(</phrase> <phrase role="identifier">ec_</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
11794            <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>
11795        <phrase role="special">}</phrase>
11796    <phrase role="special">}</phrase>
11797
11798<phrase role="keyword">private</phrase><phrase role="special">:</phrase>
11799    <phrase role="comment">// If yield_t does not bind an error_code instance, store into here.</phrase>
11800    <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>
11801    <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>
11802<phrase role="special">};</phrase>
11803</programlisting>
11804      </para>
11805      <para>
11806        This is how <code><phrase role="identifier">yield_handler_base</phrase><phrase
11807        role="special">::</phrase><phrase role="identifier">ycomp_</phrase></code>
11808        becomes non-null: <code><phrase role="identifier">async_result_base</phrase></code>&#8217;s
11809        constructor injects a pointer back to its own <code><phrase role="identifier">yield_completion</phrase></code>
11810        member.
11811      </para>
11812      <para>
11813        Recall that the canonical <code><phrase role="identifier">yield_t</phrase></code>
11814        instance <code><phrase role="identifier">yield</phrase></code> initializes
11815        its <code><phrase role="identifier">error_code</phrase><phrase role="special">*</phrase></code>
11816        member <code><phrase role="identifier">ec_</phrase></code> to <code><phrase
11817        role="keyword">nullptr</phrase></code>. If this instance is passed to <code><phrase
11818        role="identifier">async_something</phrase><phrase role="special">()</phrase></code>
11819        (<code><phrase role="identifier">ec_</phrase></code> is still <code><phrase
11820        role="keyword">nullptr</phrase></code>), the copy stored in <code><phrase
11821        role="identifier">yield_handler_base</phrase></code> will likewise have null
11822        <code><phrase role="identifier">ec_</phrase></code>. <code><phrase role="identifier">async_result_base</phrase></code>&#8217;s
11823        constructor sets <code><phrase role="identifier">yield_handler_base</phrase></code>&#8217;s
11824        <code><phrase role="identifier">yield_t</phrase></code>&#8217;s <code><phrase role="identifier">ec_</phrase></code>
11825        member to point to its own <code><phrase role="identifier">error_code</phrase></code>
11826        member.
11827      </para>
11828      <para>
11829        The stage is now set. <code><phrase role="identifier">async_something</phrase><phrase
11830        role="special">()</phrase></code> initiates the actual async operation, arranging
11831        to call its <code><phrase role="identifier">yield_handler</phrase><phrase
11832        role="special">&lt;</phrase><phrase role="keyword">void</phrase><phrase role="special">&gt;</phrase></code>
11833        instance on completion. Let&#8217;s say, for the sake of argument, that the actual
11834        async operation&#8217;s callback has signature <code><phrase role="keyword">void</phrase><phrase
11835        role="special">(</phrase><phrase role="identifier">error_code</phrase><phrase
11836        role="special">)</phrase></code>.
11837      </para>
11838      <para>
11839        But since it&#8217;s an async operation, control returns at once to <code><phrase
11840        role="identifier">async_something</phrase><phrase role="special">()</phrase></code>.
11841        <code><phrase role="identifier">async_something</phrase><phrase role="special">()</phrase></code>
11842        calls <code><phrase role="identifier">async_result</phrase><phrase role="special">&lt;</phrase><phrase
11843        role="identifier">yield_handler</phrase><phrase role="special">&lt;</phrase><phrase
11844        role="keyword">void</phrase><phrase role="special">&gt;&gt;::</phrase><phrase
11845        role="identifier">get</phrase><phrase role="special">()</phrase></code>,
11846        and will return its return value.
11847      </para>
11848      <para>
11849        <code><phrase role="identifier">async_result</phrase><phrase role="special">&lt;</phrase><phrase
11850        role="identifier">yield_handler</phrase><phrase role="special">&lt;</phrase><phrase
11851        role="keyword">void</phrase><phrase role="special">&gt;&gt;::</phrase><phrase
11852        role="identifier">get</phrase><phrase role="special">()</phrase></code> inherits
11853        <code><phrase role="identifier">async_result_base</phrase><phrase role="special">::</phrase><phrase
11854        role="identifier">get</phrase><phrase role="special">()</phrase></code>.
11855      </para>
11856      <para>
11857        <code><phrase role="identifier">async_result_base</phrase><phrase role="special">::</phrase><phrase
11858        role="identifier">get</phrase><phrase role="special">()</phrase></code> immediately
11859        calls <code><phrase role="identifier">yield_completion</phrase><phrase role="special">::</phrase><phrase
11860        role="identifier">wait</phrase><phrase role="special">()</phrase></code>.
11861      </para>
11862      <para>
11863<programlisting><phrase role="comment">// Bundle a completion bool flag with a spinlock to protect it.</phrase>
11864<phrase role="keyword">struct</phrase> <phrase role="identifier">yield_completion</phrase> <phrase role="special">{</phrase>
11865    <phrase role="keyword">enum</phrase> <phrase role="identifier">state_t</phrase> <phrase role="special">{</phrase>
11866        <phrase role="identifier">init</phrase><phrase role="special">,</phrase>
11867        <phrase role="identifier">waiting</phrase><phrase role="special">,</phrase>
11868        <phrase role="identifier">complete</phrase>
11869    <phrase role="special">};</phrase>
11870
11871    <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>
11872    <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>
11873    <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>
11874
11875    <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>
11876    <phrase role="identifier">mutex_t</phrase>                     <phrase role="identifier">mtx_</phrase><phrase role="special">{};</phrase>
11877    <phrase role="identifier">state_t</phrase>                     <phrase role="identifier">state_</phrase><phrase role="special">{</phrase> <phrase role="identifier">init</phrase> <phrase role="special">};</phrase>
11878
11879    <phrase role="keyword">void</phrase> <phrase role="identifier">wait</phrase><phrase role="special">()</phrase> <phrase role="special">{</phrase>
11880        <phrase role="comment">// yield_handler_base::operator()() will set state_ `complete` and</phrase>
11881        <phrase role="comment">// attempt to wake a suspended fiber. It would be Bad if that call</phrase>
11882        <phrase role="comment">// happened between our detecting (complete != state_) and suspending.</phrase>
11883        <phrase role="identifier">lock_t</phrase> <phrase role="identifier">lk</phrase><phrase role="special">{</phrase> <phrase role="identifier">mtx_</phrase> <phrase role="special">};</phrase>
11884        <phrase role="comment">// If state_ is already set, we're done here: don't suspend.</phrase>
11885        <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>
11886            <phrase role="identifier">state_</phrase> <phrase role="special">=</phrase> <phrase role="identifier">waiting</phrase><phrase role="special">;</phrase>
11887            <phrase role="comment">// suspend(unique_lock&lt;spinlock&gt;) unlocks the lock in the act of</phrase>
11888            <phrase role="comment">// resuming another fiber</phrase>
11889            <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>
11890        <phrase role="special">}</phrase>
11891    <phrase role="special">}</phrase>
11892
11893    <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>
11894        <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>
11895        <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>
11896    <phrase role="special">}</phrase>
11897
11898    <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>
11899        <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>
11900        <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>
11901            <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>
11902            <phrase role="keyword">delete</phrase> <phrase role="identifier">yc</phrase><phrase role="special">;</phrase>
11903        <phrase role="special">}</phrase>
11904    <phrase role="special">}</phrase>
11905<phrase role="special">};</phrase>
11906</programlisting>
11907      </para>
11908      <para>
11909        Supposing that the pending async operation has not yet completed, <code><phrase
11910        role="identifier">yield_completion</phrase><phrase role="special">::</phrase><phrase
11911        role="identifier">completed_</phrase></code> will still be <code><phrase
11912        role="keyword">false</phrase></code>, and <code><phrase role="identifier">wait</phrase><phrase
11913        role="special">()</phrase></code> will call <link linkend="context_suspend"><code>context::suspend()</code></link> on
11914        the currently-running fiber.
11915      </para>
11916      <para>
11917        Other fibers will now have a chance to run.
11918      </para>
11919      <para>
11920        Some time later, the async operation completes. It calls <code><phrase role="identifier">yield_handler</phrase><phrase
11921        role="special">&lt;</phrase><phrase role="keyword">void</phrase><phrase role="special">&gt;::</phrase><phrase
11922        role="keyword">operator</phrase><phrase role="special">()(</phrase><phrase
11923        role="identifier">error_code</phrase> <phrase role="keyword">const</phrase><phrase
11924        role="special">&amp;)</phrase></code> with an <code><phrase role="identifier">error_code</phrase></code>
11925        indicating either success or failure. We&#8217;ll consider both cases.
11926      </para>
11927      <para>
11928        <code><phrase role="identifier">yield_handler</phrase><phrase role="special">&lt;</phrase><phrase
11929        role="keyword">void</phrase><phrase role="special">&gt;</phrase></code> explicitly
11930        inherits <code><phrase role="keyword">operator</phrase><phrase role="special">()(</phrase><phrase
11931        role="identifier">error_code</phrase> <phrase role="keyword">const</phrase><phrase
11932        role="special">&amp;)</phrase></code> from <code><phrase role="identifier">yield_handler_base</phrase></code>.
11933      </para>
11934      <para>
11935        <code><phrase role="identifier">yield_handler_base</phrase><phrase role="special">::</phrase><phrase
11936        role="keyword">operator</phrase><phrase role="special">()(</phrase><phrase
11937        role="identifier">error_code</phrase> <phrase role="keyword">const</phrase><phrase
11938        role="special">&amp;)</phrase></code> first sets <code><phrase role="identifier">yield_completion</phrase><phrase
11939        role="special">::</phrase><phrase role="identifier">completed_</phrase></code>
11940        <code><phrase role="keyword">true</phrase></code>. This way, if <code><phrase
11941        role="identifier">async_something</phrase><phrase role="special">()</phrase></code>&#8217;s
11942        async operation completes immediately &mdash; if <code><phrase role="identifier">yield_handler_base</phrase><phrase
11943        role="special">::</phrase><phrase role="keyword">operator</phrase><phrase
11944        role="special">()</phrase></code> is called even before <code><phrase role="identifier">async_result_base</phrase><phrase
11945        role="special">::</phrase><phrase role="identifier">get</phrase><phrase role="special">()</phrase></code>
11946        &mdash; the calling fiber will <emphasis>not</emphasis> suspend.
11947      </para>
11948      <para>
11949        The actual <code><phrase role="identifier">error_code</phrase></code> produced
11950        by the async operation is then stored through the stored <code><phrase role="identifier">yield_t</phrase><phrase
11951        role="special">::</phrase><phrase role="identifier">ec_</phrase></code> pointer.
11952        If <code><phrase role="identifier">async_something</phrase><phrase role="special">()</phrase></code>&#8217;s
11953        caller used (e.g.) <code><phrase role="identifier">yield</phrase><phrase
11954        role="special">[</phrase><phrase role="identifier">my_ec</phrase><phrase
11955        role="special">]</phrase></code> to bind a local <code><phrase role="identifier">error_code</phrase></code>
11956        instance, the actual <code><phrase role="identifier">error_code</phrase></code>
11957        value is stored into the caller&#8217;s variable. Otherwise, it is stored into
11958        <code><phrase role="identifier">async_result_base</phrase><phrase role="special">::</phrase><phrase
11959        role="identifier">ec_</phrase></code>.
11960      </para>
11961      <para>
11962        If the stored fiber context <code><phrase role="identifier">yield_handler_base</phrase><phrase
11963        role="special">::</phrase><phrase role="identifier">ctx_</phrase></code>
11964        is not already running, it is marked as ready to run by passing it to <link linkend="context_schedule"><code>context::schedule()</code></link>.
11965        Control then returns from <code><phrase role="identifier">yield_handler_base</phrase><phrase
11966        role="special">::</phrase><phrase role="keyword">operator</phrase><phrase
11967        role="special">()</phrase></code>: the callback is done.
11968      </para>
11969      <para>
11970        In due course, that fiber is resumed. Control returns from <link linkend="context_suspend"><code>context::suspend()</code></link> to
11971        <code><phrase role="identifier">yield_completion</phrase><phrase role="special">::</phrase><phrase
11972        role="identifier">wait</phrase><phrase role="special">()</phrase></code>,
11973        which returns to <code><phrase role="identifier">async_result_base</phrase><phrase
11974        role="special">::</phrase><phrase role="identifier">get</phrase><phrase role="special">()</phrase></code>.
11975      </para>
11976      <itemizedlist>
11977        <listitem>
11978          <simpara>
11979            If the original caller passed <code><phrase role="identifier">yield</phrase><phrase
11980            role="special">[</phrase><phrase role="identifier">my_ec</phrase><phrase
11981            role="special">]</phrase></code> to <code><phrase role="identifier">async_something</phrase><phrase
11982            role="special">()</phrase></code> to bind a local <code><phrase role="identifier">error_code</phrase></code>
11983            instance, then <code><phrase role="identifier">yield_handler_base</phrase><phrase
11984            role="special">::</phrase><phrase role="keyword">operator</phrase><phrase
11985            role="special">()</phrase></code> stored its <code><phrase role="identifier">error_code</phrase></code>
11986            to the caller&#8217;s <code><phrase role="identifier">my_ec</phrase></code>
11987            instance, leaving <code><phrase role="identifier">async_result_base</phrase><phrase
11988            role="special">::</phrase><phrase role="identifier">ec_</phrase></code>
11989            initialized to success.
11990          </simpara>
11991        </listitem>
11992        <listitem>
11993          <simpara>
11994            If the original caller passed <code><phrase role="identifier">yield</phrase></code>
11995            to <code><phrase role="identifier">async_something</phrase><phrase role="special">()</phrase></code>
11996            without binding a local <code><phrase role="identifier">error_code</phrase></code>
11997            variable, then <code><phrase role="identifier">yield_handler_base</phrase><phrase
11998            role="special">::</phrase><phrase role="keyword">operator</phrase><phrase
11999            role="special">()</phrase></code> stored its <code><phrase role="identifier">error_code</phrase></code>
12000            into <code><phrase role="identifier">async_result_base</phrase><phrase
12001            role="special">::</phrase><phrase role="identifier">ec_</phrase></code>.
12002            If in fact that <code><phrase role="identifier">error_code</phrase></code>
12003            is success, then all is well.
12004          </simpara>
12005        </listitem>
12006        <listitem>
12007          <simpara>
12008            Otherwise &mdash; the original caller did not bind a local <code><phrase role="identifier">error_code</phrase></code>
12009            and <code><phrase role="identifier">yield_handler_base</phrase><phrase
12010            role="special">::</phrase><phrase role="keyword">operator</phrase><phrase
12011            role="special">()</phrase></code> was called with an <code><phrase role="identifier">error_code</phrase></code>
12012            indicating error &mdash; <code><phrase role="identifier">async_result_base</phrase><phrase
12013            role="special">::</phrase><phrase role="identifier">get</phrase><phrase
12014            role="special">()</phrase></code> throws <code><phrase role="identifier">system_error</phrase></code>
12015            with that <code><phrase role="identifier">error_code</phrase></code>.
12016          </simpara>
12017        </listitem>
12018      </itemizedlist>
12019      <para>
12020        The case in which <code><phrase role="identifier">async_something</phrase><phrase
12021        role="special">()</phrase></code>&#8217;s completion callback has signature <code><phrase
12022        role="keyword">void</phrase><phrase role="special">()</phrase></code> is
12023        similar. <code><phrase role="identifier">yield_handler</phrase><phrase role="special">&lt;</phrase><phrase
12024        role="keyword">void</phrase><phrase role="special">&gt;::</phrase><phrase
12025        role="keyword">operator</phrase><phrase role="special">()()</phrase></code>
12026        invokes the machinery above with a <quote>success</quote> <code><phrase role="identifier">error_code</phrase></code>.
12027      </para>
12028      <para>
12029        A completion callback with signature <code><phrase role="keyword">void</phrase><phrase
12030        role="special">(</phrase><phrase role="identifier">error_code</phrase><phrase
12031        role="special">,</phrase> <phrase role="identifier">T</phrase><phrase role="special">)</phrase></code>
12032        (that is: in addition to <code><phrase role="identifier">error_code</phrase></code>,
12033        callback receives some data item) is handled somewhat differently. For this
12034        kind of signature, <code><phrase role="identifier">handler_type</phrase><phrase
12035        role="special">&lt;&gt;::</phrase><phrase role="identifier">type</phrase></code>
12036        specifies <code><phrase role="identifier">yield_handler</phrase><phrase role="special">&lt;</phrase><phrase
12037        role="identifier">T</phrase><phrase role="special">&gt;</phrase></code> (for
12038        <code><phrase role="identifier">T</phrase></code> other than <code><phrase
12039        role="keyword">void</phrase></code>).
12040      </para>
12041      <para>
12042        A <code><phrase role="identifier">yield_handler</phrase><phrase role="special">&lt;</phrase><phrase
12043        role="identifier">T</phrase><phrase role="special">&gt;</phrase></code> reserves
12044        a <code><phrase role="identifier">value_</phrase></code> pointer to a value
12045        of type <code><phrase role="identifier">T</phrase></code>:
12046      </para>
12047      <para>
12048<programlisting><phrase role="comment">// asio uses handler_type&lt;completion token type, signature&gt;::type to decide</phrase>
12049<phrase role="comment">// what to instantiate as the actual handler. Below, we specialize</phrase>
12050<phrase role="comment">// handler_type&lt; yield_t, ... &gt; to indicate yield_handler&lt;&gt;. So when you pass</phrase>
12051<phrase role="comment">// an instance of yield_t as an asio completion token, asio selects</phrase>
12052<phrase role="comment">// yield_handler&lt;&gt; as the actual handler class.</phrase>
12053<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>
12054<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>
12055<phrase role="keyword">public</phrase><phrase role="special">:</phrase>
12056    <phrase role="comment">// asio passes the completion token to the handler constructor</phrase>
12057    <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>
12058        <phrase role="identifier">yield_handler_base</phrase><phrase role="special">{</phrase> <phrase role="identifier">y</phrase> <phrase role="special">}</phrase> <phrase role="special">{</phrase>
12059    <phrase role="special">}</phrase>
12060
12061    <phrase role="comment">// completion callback passing only value (T)</phrase>
12062    <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>
12063        <phrase role="comment">// just like callback passing success error_code</phrase>
12064        <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>
12065    <phrase role="special">}</phrase>
12066
12067    <phrase role="comment">// completion callback passing (error_code, T)</phrase>
12068    <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>
12069        <phrase role="identifier">BOOST_ASSERT_MSG</phrase><phrase role="special">(</phrase> <phrase role="identifier">value_</phrase><phrase role="special">,</phrase>
12070                          <phrase role="string">&quot;Must inject value ptr &quot;</phrase>
12071                          <phrase role="string">&quot;before caling yield_handler&lt;T&gt;::operator()()&quot;</phrase><phrase role="special">);</phrase>
12072        <phrase role="comment">// move the value to async_result&lt;&gt; instance BEFORE waking up a</phrase>
12073        <phrase role="comment">// suspended fiber</phrase>
12074        <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>
12075        <phrase role="comment">// forward the call to base-class completion handler</phrase>
12076        <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>
12077    <phrase role="special">}</phrase>
12078
12079<phrase role="comment">//private:</phrase>
12080    <phrase role="comment">// pointer to destination for eventual value</phrase>
12081    <phrase role="comment">// this must be injected by async_result before operator()() is called</phrase>
12082    <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>
12083<phrase role="special">};</phrase>
12084</programlisting>
12085      </para>
12086      <para>
12087        This pointer is initialized to <code><phrase role="keyword">nullptr</phrase></code>.
12088      </para>
12089      <para>
12090        When <code><phrase role="identifier">async_something</phrase><phrase role="special">()</phrase></code>
12091        instantiates <code><phrase role="identifier">async_result</phrase><phrase
12092        role="special">&lt;</phrase><phrase role="identifier">yield_handler</phrase><phrase
12093        role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;&gt;</phrase></code>:
12094      </para>
12095      <para>
12096<programlisting><phrase role="comment">// asio constructs an async_result&lt;&gt; instance from the yield_handler specified</phrase>
12097<phrase role="comment">// by handler_type&lt;&gt;::type. A particular asio async method constructs the</phrase>
12098<phrase role="comment">// yield_handler, constructs this async_result specialization from it, then</phrase>
12099<phrase role="comment">// returns the result of calling its get() method.</phrase>
12100<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>
12101<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>
12102    <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>
12103<phrase role="keyword">public</phrase><phrase role="special">:</phrase>
12104    <phrase role="comment">// type returned by get()</phrase>
12105    <phrase role="keyword">typedef</phrase> <phrase role="identifier">T</phrase> <phrase role="identifier">type</phrase><phrase role="special">;</phrase>
12106
12107    <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>
12108        <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>
12109        <phrase role="comment">// Inject ptr to our value_ member into yield_handler&lt;&gt;: result will</phrase>
12110        <phrase role="comment">// be stored here.</phrase>
12111        <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>
12112    <phrase role="special">}</phrase>
12113
12114    <phrase role="comment">// asio async method returns result of calling get()</phrase>
12115    <phrase role="identifier">type</phrase> <phrase role="identifier">get</phrase><phrase role="special">()</phrase> <phrase role="special">{</phrase>
12116        <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>
12117        <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>
12118    <phrase role="special">}</phrase>
12119
12120<phrase role="keyword">private</phrase><phrase role="special">:</phrase>
12121    <phrase role="identifier">type</phrase>                            <phrase role="identifier">value_</phrase><phrase role="special">{};</phrase>
12122<phrase role="special">};</phrase>
12123</programlisting>
12124      </para>
12125      <para>
12126        this <code><phrase role="identifier">async_result</phrase><phrase role="special">&lt;&gt;</phrase></code>
12127        specialization reserves a member of type <code><phrase role="identifier">T</phrase></code>
12128        to receive the passed data item, and sets <code><phrase role="identifier">yield_handler</phrase><phrase
12129        role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase
12130        role="identifier">value_</phrase></code> to point to its own data member.
12131      </para>
12132      <para>
12133        <code><phrase role="identifier">async_result</phrase><phrase role="special">&lt;</phrase><phrase
12134        role="identifier">yield_handler</phrase><phrase role="special">&lt;</phrase><phrase
12135        role="identifier">T</phrase><phrase role="special">&gt;&gt;</phrase></code>
12136        overrides <code><phrase role="identifier">get</phrase><phrase role="special">()</phrase></code>.
12137        The override calls <code><phrase role="identifier">async_result_base</phrase><phrase
12138        role="special">::</phrase><phrase role="identifier">get</phrase><phrase role="special">()</phrase></code>,
12139        so the calling fiber suspends as described above.
12140      </para>
12141      <para>
12142        <code><phrase role="identifier">yield_handler</phrase><phrase role="special">&lt;</phrase><phrase
12143        role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase
12144        role="keyword">operator</phrase><phrase role="special">()(</phrase><phrase
12145        role="identifier">error_code</phrase><phrase role="special">,</phrase> <phrase
12146        role="identifier">T</phrase><phrase role="special">)</phrase></code> stores
12147        its passed <code><phrase role="identifier">T</phrase></code> value into
12148        <code><phrase role="identifier">async_result</phrase><phrase role="special">&lt;</phrase><phrase
12149        role="identifier">yield_handler</phrase><phrase role="special">&lt;</phrase><phrase
12150        role="identifier">T</phrase><phrase role="special">&gt;&gt;::</phrase><phrase
12151        role="identifier">value_</phrase></code>.
12152      </para>
12153      <para>
12154        Then it passes control to <code><phrase role="identifier">yield_handler_base</phrase><phrase
12155        role="special">::</phrase><phrase role="keyword">operator</phrase><phrase
12156        role="special">()(</phrase><phrase role="identifier">error_code</phrase><phrase
12157        role="special">)</phrase></code> to deal with waking the original fiber as
12158        described above.
12159      </para>
12160      <para>
12161        When <code><phrase role="identifier">async_result</phrase><phrase role="special">&lt;</phrase><phrase
12162        role="identifier">yield_handler</phrase><phrase role="special">&lt;</phrase><phrase
12163        role="identifier">T</phrase><phrase role="special">&gt;&gt;::</phrase><phrase
12164        role="identifier">get</phrase><phrase role="special">()</phrase></code> resumes,
12165        it returns the stored <code><phrase role="identifier">value_</phrase></code>
12166        to <code><phrase role="identifier">async_something</phrase><phrase role="special">()</phrase></code>
12167        and ultimately to <code><phrase role="identifier">async_something</phrase><phrase
12168        role="special">()</phrase></code>&#8217;s caller.
12169      </para>
12170      <para>
12171        The case of a callback signature <code><phrase role="keyword">void</phrase><phrase
12172        role="special">(</phrase><phrase role="identifier">T</phrase><phrase role="special">)</phrase></code>
12173        is handled by having <code><phrase role="identifier">yield_handler</phrase><phrase
12174        role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase
12175        role="keyword">operator</phrase><phrase role="special">()(</phrase><phrase
12176        role="identifier">T</phrase><phrase role="special">)</phrase></code> engage
12177        the <code><phrase role="keyword">void</phrase><phrase role="special">(</phrase><phrase
12178        role="identifier">error_code</phrase><phrase role="special">,</phrase> <phrase
12179        role="identifier">T</phrase><phrase role="special">)</phrase></code> machinery,
12180        passing a <quote>success</quote> <code><phrase role="identifier">error_code</phrase></code>.
12181      </para>
12182      <para>
12183        The source code above is found in <ulink url="../../examples/asio/yield.hpp">yield.hpp</ulink>
12184        and <ulink url="../../examples/asio/detail/yield.hpp">detail/yield.hpp</ulink>.
12185      </para>
12186    </section>
12187  </section>
12188  <section id="fiber.nonblocking">
12189    <title><anchor id="nonblocking"/><link linkend="fiber.nonblocking">Integrating
12190    Fibers with Nonblocking I/O</link></title>
12191    <bridgehead renderas="sect3" id="fiber.nonblocking.h0">
12192      <phrase id="fiber.nonblocking.overview"/><link linkend="fiber.nonblocking.overview">Overview</link>
12193    </bridgehead>
12194    <para>
12195      <emphasis>Nonblocking</emphasis> I/O is distinct from <emphasis>asynchronous</emphasis>
12196      I/O. A true async I/O operation promises to initiate the operation and notify
12197      the caller on completion, usually via some sort of callback (as described in
12198      <link linkend="callbacks">Integrating Fibers with Asynchronous Callbacks</link>).
12199    </para>
12200    <para>
12201      In contrast, a nonblocking I/O operation refuses to start at all if it would
12202      be necessary to block, returning an error code such as <ulink url="http://man7.org/linux/man-pages/man3/errno.3.html"><code><phrase
12203      role="identifier">EWOULDBLOCK</phrase></code></ulink>. The operation is performed
12204      only when it can complete immediately. In effect, the caller must repeatedly
12205      retry the operation until it stops returning <code><phrase role="identifier">EWOULDBLOCK</phrase></code>.
12206    </para>
12207    <para>
12208      In a classic event-driven program, it can be something of a headache to use
12209      nonblocking I/O. At the point where the nonblocking I/O is attempted, a return
12210      value of <code><phrase role="identifier">EWOULDBLOCK</phrase></code> requires
12211      the caller to pass control back to the main event loop, arranging to retry
12212      again on the next iteration.
12213    </para>
12214    <para>
12215      Worse, a nonblocking I/O operation might <emphasis>partially</emphasis> succeed.
12216      That means that the relevant business logic must continue receiving control
12217      on every main loop iteration until all required data have been processed: a
12218      doubly-nested loop, implemented as a callback-driven state machine.
12219    </para>
12220    <para>
12221      <emphasis role="bold">Boost.Fiber</emphasis> can simplify this problem immensely.
12222      Once you have integrated with the application's main loop as described in
12223      <link linkend="integration">Sharing a Thread with Another Main Loop</link>,
12224      waiting for the next main-loop iteration is as simple as calling <link linkend="this_fiber_yield"><code>this_fiber::yield()</code></link>.
12225    </para>
12226    <bridgehead renderas="sect3" id="fiber.nonblocking.h1">
12227      <phrase id="fiber.nonblocking.example_nonblocking_api"/><link linkend="fiber.nonblocking.example_nonblocking_api">Example
12228      Nonblocking API</link>
12229    </bridgehead>
12230    <para>
12231      For purposes of illustration, consider this API:
12232    </para>
12233    <para>
12234<programlisting><phrase role="keyword">class</phrase> <phrase role="identifier">NonblockingAPI</phrase> <phrase role="special">{</phrase>
12235<phrase role="keyword">public</phrase><phrase role="special">:</phrase>
12236    <phrase role="identifier">NonblockingAPI</phrase><phrase role="special">();</phrase>
12237
12238    <phrase role="comment">// nonblocking operation: may return EWOULDBLOCK</phrase>
12239    <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>
12240
12241    <phrase role="special">...</phrase>
12242<phrase role="special">};</phrase>
12243</programlisting>
12244    </para>
12245    <bridgehead renderas="sect3" id="fiber.nonblocking.h2">
12246      <phrase id="fiber.nonblocking.polling_for_completion"/><link linkend="fiber.nonblocking.polling_for_completion">Polling
12247      for Completion</link>
12248    </bridgehead>
12249    <para>
12250      We can build a low-level wrapper around <code><phrase role="identifier">NonblockingAPI</phrase><phrase
12251      role="special">::</phrase><phrase role="identifier">read</phrase><phrase role="special">()</phrase></code>
12252      that shields its caller from ever having to deal with <code><phrase role="identifier">EWOULDBLOCK</phrase></code>:
12253    </para>
12254    <para>
12255<programlisting><phrase role="comment">// guaranteed not to return EWOULDBLOCK</phrase>
12256<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>
12257    <phrase role="keyword">int</phrase> <phrase role="identifier">error</phrase><phrase role="special">;</phrase>
12258    <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>
12259        <phrase role="comment">// not ready yet -- try again on the next iteration of the</phrase>
12260        <phrase role="comment">// application's main loop</phrase>
12261        <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>
12262    <phrase role="special">}</phrase>
12263    <phrase role="keyword">return</phrase> <phrase role="identifier">error</phrase><phrase role="special">;</phrase>
12264<phrase role="special">}</phrase>
12265</programlisting>
12266    </para>
12267    <bridgehead renderas="sect3" id="fiber.nonblocking.h3">
12268      <phrase id="fiber.nonblocking.filling_all_desired_data"/><link linkend="fiber.nonblocking.filling_all_desired_data">Filling
12269      All Desired Data</link>
12270    </bridgehead>
12271    <para>
12272      Given <code><phrase role="identifier">read_chunk</phrase><phrase role="special">()</phrase></code>,
12273      we can straightforwardly iterate until we have all desired data:
12274    </para>
12275    <para>
12276<programlisting><phrase role="comment">// keep reading until desired length, EOF or error</phrase>
12277<phrase role="comment">// may return both partial data and nonzero error</phrase>
12278<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>
12279    <phrase role="comment">// we're going to accumulate results into 'data'</phrase>
12280    <phrase role="identifier">data</phrase><phrase role="special">.</phrase><phrase role="identifier">clear</phrase><phrase role="special">();</phrase>
12281    <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="identifier">chunk</phrase><phrase role="special">;</phrase>
12282    <phrase role="keyword">int</phrase> <phrase role="identifier">error</phrase> <phrase role="special">=</phrase> <phrase role="number">0</phrase><phrase role="special">;</phrase>
12283    <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>
12284           <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>
12285        <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>
12286    <phrase role="special">}</phrase>
12287    <phrase role="keyword">return</phrase> <phrase role="identifier">error</phrase><phrase role="special">;</phrase>
12288<phrase role="special">}</phrase>
12289</programlisting>
12290    </para>
12291    <para>
12292      (Of <emphasis>course</emphasis> there are more efficient ways to accumulate
12293      string data. That's not the point of this example.)
12294    </para>
12295    <bridgehead renderas="sect3" id="fiber.nonblocking.h4">
12296      <phrase id="fiber.nonblocking.wrapping_it_up"/><link linkend="fiber.nonblocking.wrapping_it_up">Wrapping
12297      it Up</link>
12298    </bridgehead>
12299    <para>
12300      Finally, we can define a relevant exception:
12301    </para>
12302    <para>
12303<programlisting><phrase role="comment">// exception class augmented with both partially-read data and errorcode</phrase>
12304<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>
12305<phrase role="keyword">public</phrase><phrase role="special">:</phrase>
12306    <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>
12307        <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>
12308        <phrase role="identifier">partial_</phrase><phrase role="special">(</phrase> <phrase role="identifier">partial</phrase><phrase role="special">),</phrase>
12309        <phrase role="identifier">ec_</phrase><phrase role="special">(</phrase> <phrase role="identifier">ec</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
12310    <phrase role="special">}</phrase>
12311
12312    <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>
12313        <phrase role="keyword">return</phrase> <phrase role="identifier">partial_</phrase><phrase role="special">;</phrase>
12314    <phrase role="special">}</phrase>
12315
12316    <phrase role="keyword">int</phrase> <phrase role="identifier">get_errorcode</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase> <phrase role="special">{</phrase>
12317        <phrase role="keyword">return</phrase> <phrase role="identifier">ec_</phrase><phrase role="special">;</phrase>
12318    <phrase role="special">}</phrase>
12319
12320<phrase role="keyword">private</phrase><phrase role="special">:</phrase>
12321    <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="identifier">partial_</phrase><phrase role="special">;</phrase>
12322    <phrase role="keyword">int</phrase>         <phrase role="identifier">ec_</phrase><phrase role="special">;</phrase>
12323<phrase role="special">};</phrase>
12324</programlisting>
12325    </para>
12326    <para>
12327      and write a simple <code><phrase role="identifier">read</phrase><phrase role="special">()</phrase></code>
12328      function that either returns all desired data or throws <code><phrase role="identifier">IncompleteRead</phrase></code>:
12329    </para>
12330    <para>
12331<programlisting><phrase role="comment">// read all desired data or throw IncompleteRead</phrase>
12332<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>
12333    <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="identifier">data</phrase><phrase role="special">;</phrase>
12334    <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>
12335
12336    <phrase role="comment">// for present purposes, EOF isn't a failure</phrase>
12337    <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>
12338        <phrase role="keyword">return</phrase> <phrase role="identifier">data</phrase><phrase role="special">;</phrase>
12339    <phrase role="special">}</phrase>
12340
12341    <phrase role="comment">// oh oh, partial read</phrase>
12342    <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">ostringstream</phrase> <phrase role="identifier">msg</phrase><phrase role="special">;</phrase>
12343    <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>
12344        <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>
12345    <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>
12346<phrase role="special">}</phrase>
12347</programlisting>
12348    </para>
12349    <para>
12350      Once we can transparently wait for the next main-loop iteration using <link linkend="this_fiber_yield"><code>this_fiber::yield()</code></link>,
12351      ordinary encapsulation Just Works.
12352    </para>
12353    <para>
12354      The source code above is found in <ulink url="../../examples/adapt_nonblocking.cpp">adapt_nonblocking.cpp</ulink>.
12355    </para>
12356  </section>
12357  <section id="fiber.when_any">
12358    <title><anchor id="when_any"/><link linkend="fiber.when_any">when_any / when_all
12359    functionality</link></title>
12360    <bridgehead renderas="sect3" id="fiber.when_any.h0">
12361      <phrase id="fiber.when_any.overview"/><link linkend="fiber.when_any.overview">Overview</link>
12362    </bridgehead>
12363    <para>
12364      A bit of wisdom from the early days of computing still holds true today: prefer
12365      to model program state using the instruction pointer rather than with Boolean
12366      flags. In other words, if the program must <quote>do something</quote> and
12367      then do something almost the same, but with minor changes... perhaps parts
12368      of that something should be broken out as smaller separate functions, rather
12369      than introducing flags to alter the internal behavior of a monolithic function.
12370    </para>
12371    <para>
12372      To that we would add: prefer to describe control flow using C++ native constructs
12373      such as function calls, <code><phrase role="keyword">if</phrase></code>, <code><phrase
12374      role="keyword">while</phrase></code>, <code><phrase role="keyword">for</phrase></code>,
12375      <code><phrase role="keyword">do</phrase></code> et al. rather than as chains
12376      of callbacks.
12377    </para>
12378    <para>
12379      One of the great strengths of <emphasis role="bold">Boost.Fiber</emphasis>
12380      is the flexibility it confers on the coder to restructure an application from
12381      chains of callbacks to straightforward C++ statement sequence, even when code
12382      in that fiber is in fact interleaved with code running in other fibers.
12383    </para>
12384    <para>
12385      There has been much recent discussion about the benefits of when_any and when_all
12386      functionality. When dealing with asynchronous and possibly unreliable services,
12387      these are valuable idioms. But of course when_any and when_all are closely
12388      tied to the use of chains of callbacks.
12389    </para>
12390    <para>
12391      This section presents recipes for achieving the same ends, in the context of
12392      a fiber that wants to <quote>do something</quote> when one or more other independent
12393      activities have completed. Accordingly, these are <code><phrase role="identifier">wait_something</phrase><phrase
12394      role="special">()</phrase></code> functions rather than <code><phrase role="identifier">when_something</phrase><phrase
12395      role="special">()</phrase></code> functions. The expectation is that the calling
12396      fiber asks to launch those independent activities, then waits for them, then
12397      sequentially proceeds with whatever processing depends on those results.
12398    </para>
12399    <para>
12400      The function names shown (e.g. <link linkend="wait_first_simple"><code><phrase
12401      role="identifier">wait_first_simple</phrase><phrase role="special">()</phrase></code></link>)
12402      are for illustrative purposes only, because all these functions have been bundled
12403      into a single source file. Presumably, if (say) <link linkend="wait_first_success"><code><phrase
12404      role="identifier">wait_first_success</phrase><phrase role="special">()</phrase></code></link>
12405      best suits your application needs, you could introduce that variant with the
12406      name <code><phrase role="identifier">wait_any</phrase><phrase role="special">()</phrase></code>.
12407    </para>
12408    <note>
12409      <para>
12410        The functions presented in this section accept variadic argument lists of
12411        task functions. Corresponding <code><phrase role="identifier">wait_something</phrase><phrase
12412        role="special">()</phrase></code> functions accepting a container of task
12413        functions are left as an exercise for the interested reader. Those should
12414        actually be simpler. Most of the complexity would arise from overloading
12415        the same name for both purposes.
12416      </para>
12417    </note>
12418    <para>
12419      All the source code for this section is found in <ulink url="../../examples/wait_stuff.cpp">wait_stuff.cpp</ulink>.
12420    </para>
12421    <bridgehead renderas="sect3" id="fiber.when_any.h1">
12422      <phrase id="fiber.when_any.example_task_function"/><link linkend="fiber.when_any.example_task_function">Example
12423      Task Function</link>
12424    </bridgehead>
12425    <para>
12426      <anchor id="wait_sleeper"/>We found it convenient to model an asynchronous
12427      task using this function:
12428    </para>
12429    <para>
12430<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>
12431<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>
12432    <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>
12433    <phrase role="identifier">descb</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="identifier">item</phrase><phrase role="special">;</phrase>
12434    <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>
12435    <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>
12436    <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>
12437
12438    <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>
12439    <phrase role="keyword">if</phrase> <phrase role="special">(</phrase> <phrase role="identifier">thrw</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
12440        <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>
12441    <phrase role="special">}</phrase>
12442    <phrase role="keyword">return</phrase> <phrase role="identifier">item</phrase><phrase role="special">;</phrase>
12443<phrase role="special">}</phrase>
12444</programlisting>
12445    </para>
12446    <para>
12447      with type-specific <code><phrase role="identifier">sleeper</phrase><phrase
12448      role="special">()</phrase></code> <quote>front ends</quote> for <code><phrase
12449      role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase></code>,
12450      <code><phrase role="keyword">double</phrase></code> and <code><phrase role="keyword">int</phrase></code>.
12451    </para>
12452    <para>
12453      <code><phrase role="identifier">Verbose</phrase></code> simply prints a message
12454      to <code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase
12455      role="identifier">cout</phrase></code> on construction and destruction.
12456    </para>
12457    <para>
12458      Basically:
12459    </para>
12460    <orderedlist>
12461      <listitem>
12462        <simpara>
12463          <code><phrase role="identifier">sleeper</phrase><phrase role="special">()</phrase></code>
12464          prints a start message;
12465        </simpara>
12466      </listitem>
12467      <listitem>
12468        <simpara>
12469          sleeps for the specified number of milliseconds;
12470        </simpara>
12471      </listitem>
12472      <listitem>
12473        <simpara>
12474          if <code><phrase role="identifier">thrw</phrase></code> is passed as <code><phrase
12475          role="keyword">true</phrase></code>, throws a string description of the
12476          passed <code><phrase role="identifier">item</phrase></code>;
12477        </simpara>
12478      </listitem>
12479      <listitem>
12480        <simpara>
12481          else returns the passed <code><phrase role="identifier">item</phrase></code>.
12482        </simpara>
12483      </listitem>
12484      <listitem>
12485        <simpara>
12486          On the way out, <code><phrase role="identifier">sleeper</phrase><phrase
12487          role="special">()</phrase></code> produces a stop message.
12488        </simpara>
12489      </listitem>
12490    </orderedlist>
12491    <para>
12492      This function will feature in the example calls to the various functions presented
12493      below.
12494    </para>
12495    <section id="fiber.when_any.when_any">
12496      <title><link linkend="fiber.when_any.when_any">when_any</link></title>
12497      <section id="fiber.when_any.when_any.when_any__simple_completion">
12498        <title><anchor id="wait_first_simple_section"/><link linkend="fiber.when_any.when_any.when_any__simple_completion">when_any,
12499        simple completion</link></title>
12500        <para>
12501          The simplest case is when you only need to know that the first of a set
12502          of asynchronous tasks has completed &mdash; but you don't need to obtain a return
12503          value, and you're confident that they will not throw exceptions.
12504        </para>
12505        <para>
12506          <anchor id="wait_done"/>For this we introduce a <code><phrase role="identifier">Done</phrase></code>
12507          class to wrap a <code><phrase role="keyword">bool</phrase></code> variable
12508          with a <link linkend="class_condition_variable"><code>condition_variable</code></link> and a <link linkend="class_mutex"><code>mutex</code></link>:
12509        </para>
12510        <para>
12511<programlisting><phrase role="comment">// Wrap canonical pattern for condition_variable + bool flag</phrase>
12512<phrase role="keyword">struct</phrase> <phrase role="identifier">Done</phrase> <phrase role="special">{</phrase>
12513<phrase role="keyword">private</phrase><phrase role="special">:</phrase>
12514    <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>
12515    <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>
12516    <phrase role="keyword">bool</phrase>                                <phrase role="identifier">ready</phrase> <phrase role="special">=</phrase> <phrase role="keyword">false</phrase><phrase role="special">;</phrase>
12517
12518<phrase role="keyword">public</phrase><phrase role="special">:</phrase>
12519    <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>
12520
12521    <phrase role="keyword">void</phrase> <phrase role="identifier">wait</phrase><phrase role="special">()</phrase> <phrase role="special">{</phrase>
12522        <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>
12523        <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>
12524    <phrase role="special">}</phrase>
12525
12526    <phrase role="keyword">void</phrase> <phrase role="identifier">notify</phrase><phrase role="special">()</phrase> <phrase role="special">{</phrase>
12527        <phrase role="special">{</phrase>
12528            <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>
12529            <phrase role="identifier">ready</phrase> <phrase role="special">=</phrase> <phrase role="keyword">true</phrase><phrase role="special">;</phrase>
12530        <phrase role="special">}</phrase> <phrase role="comment">// release mutex</phrase>
12531        <phrase role="identifier">cond</phrase><phrase role="special">.</phrase><phrase role="identifier">notify_one</phrase><phrase role="special">();</phrase>
12532    <phrase role="special">}</phrase>
12533<phrase role="special">};</phrase>
12534</programlisting>
12535        </para>
12536        <para>
12537          The pattern we follow throughout this section is to pass a <ulink url="http://www.cplusplus.com/reference/memory/shared_ptr/"><code><phrase
12538          role="identifier">std</phrase><phrase role="special">::</phrase><phrase
12539          role="identifier">shared_ptr</phrase><phrase role="special">&lt;&gt;</phrase></code></ulink>
12540          to the relevant synchronization object to the various tasks' fiber functions.
12541          This eliminates nagging questions about the lifespan of the synchronization
12542          object relative to the last of the fibers.
12543        </para>
12544        <para>
12545          <anchor id="wait_first_simple"/><code><phrase role="identifier">wait_first_simple</phrase><phrase
12546          role="special">()</phrase></code> uses that tactic for <link linkend="wait_done"><code><phrase
12547          role="identifier">Done</phrase></code></link>:
12548        </para>
12549        <para>
12550<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>
12551<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>
12552    <phrase role="comment">// Use shared_ptr because each function's fiber will bind it separately,</phrase>
12553    <phrase role="comment">// and we're going to return before the last of them completes.</phrase>
12554    <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>
12555    <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>
12556    <phrase role="identifier">done</phrase><phrase role="special">-&gt;</phrase><phrase role="identifier">wait</phrase><phrase role="special">();</phrase>
12557<phrase role="special">}</phrase>
12558</programlisting>
12559        </para>
12560        <para>
12561          <anchor id="wait_first_simple_impl"/><code><phrase role="identifier">wait_first_simple_impl</phrase><phrase
12562          role="special">()</phrase></code> is an ordinary recursion over the argument
12563          pack, capturing <code><phrase role="identifier">Done</phrase><phrase role="special">::</phrase><phrase
12564          role="identifier">ptr</phrase></code> for each new fiber:
12565        </para>
12566        <para>
12567<programlisting><phrase role="comment">// Degenerate case: when there are no functions to wait for, return</phrase>
12568<phrase role="comment">// immediately.</phrase>
12569<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>
12570<phrase role="special">}</phrase>
12571
12572<phrase role="comment">// When there's at least one function to wait for, launch it and recur to</phrase>
12573<phrase role="comment">// process the rest.</phrase>
12574<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>
12575<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>
12576    <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>
12577                              <phrase role="identifier">function</phrase><phrase role="special">();</phrase>
12578                              <phrase role="identifier">done</phrase><phrase role="special">-&gt;</phrase><phrase role="identifier">notify</phrase><phrase role="special">();</phrase>
12579                          <phrase role="special">}).</phrase><phrase role="identifier">detach</phrase><phrase role="special">();</phrase>
12580    <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>
12581<phrase role="special">}</phrase>
12582</programlisting>
12583        </para>
12584        <para>
12585          The body of the fiber's lambda is extremely simple, as promised: call the
12586          function, notify <link linkend="wait_done"><code><phrase role="identifier">Done</phrase></code></link>
12587          when it returns. The first fiber to do so allows <code><phrase role="identifier">wait_first_simple</phrase><phrase
12588          role="special">()</phrase></code> to return &mdash; which is why it's useful to
12589          have <code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase
12590          role="identifier">shared_ptr</phrase><phrase role="special">&lt;</phrase><phrase
12591          role="identifier">Done</phrase><phrase role="special">&gt;</phrase></code>
12592          manage the lifespan of our <code><phrase role="identifier">Done</phrase></code>
12593          object rather than declaring it as a stack variable in <code><phrase role="identifier">wait_first_simple</phrase><phrase
12594          role="special">()</phrase></code>.
12595        </para>
12596        <para>
12597          This is how you might call it:
12598        </para>
12599        <para>
12600<programlisting><phrase role="identifier">wait_first_simple</phrase><phrase role="special">(</phrase>
12601        <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>
12602        <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>
12603        <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>
12604</programlisting>
12605        </para>
12606        <para>
12607          In this example, control resumes after <code><phrase role="identifier">wait_first_simple</phrase><phrase
12608          role="special">()</phrase></code> when <link linkend="wait_sleeper"><code><phrase
12609          role="identifier">sleeper</phrase><phrase role="special">(</phrase><phrase
12610          role="string">&quot;wfs_short&quot;</phrase><phrase role="special">,</phrase>
12611          <phrase role="number">50</phrase><phrase role="special">)</phrase></code></link>
12612          completes &mdash; even though the other two <code><phrase role="identifier">sleeper</phrase><phrase
12613          role="special">()</phrase></code> fibers are still running.
12614        </para>
12615      </section>
12616      <section id="fiber.when_any.when_any.when_any__return_value">
12617        <title><link linkend="fiber.when_any.when_any.when_any__return_value">when_any,
12618        return value</link></title>
12619        <para>
12620          It seems more useful to add the ability to capture the return value from
12621          the first of the task functions to complete. Again, we assume that none
12622          will throw an exception.
12623        </para>
12624        <para>
12625          One tactic would be to adapt our <link linkend="wait_done"><code><phrase
12626          role="identifier">Done</phrase></code></link> class to store the first
12627          of the return values, rather than a simple <code><phrase role="keyword">bool</phrase></code>.
12628          However, we choose instead to use a <link linkend="class_buffered_channel"><code>buffered_channel&lt;&gt;</code></link>.
12629          We'll only need to enqueue the first value, so we'll <link linkend="buffered_channel_close"><code>buffered_channel::close()</code></link> it
12630          once we've retrieved that value. Subsequent <code><phrase role="identifier">push</phrase><phrase
12631          role="special">()</phrase></code> calls will return <code><phrase role="identifier">closed</phrase></code>.
12632        </para>
12633        <para>
12634          <anchor id="wait_first_value"/>
12635<programlisting><phrase role="comment">// Assume that all passed functions have the same return type. The return type</phrase>
12636<phrase role="comment">// of wait_first_value() is the return type of the first passed function. It is</phrase>
12637<phrase role="comment">// simply invalid to pass NO functions.</phrase>
12638<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>
12639<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>
12640<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>
12641    <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>
12642    <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>
12643    <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>
12644    <phrase role="comment">// launch all the relevant fibers</phrase>
12645    <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>
12646                                       <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>
12647                                       <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>
12648    <phrase role="comment">// retrieve the first value</phrase>
12649    <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>
12650    <phrase role="comment">// close the channel: no subsequent push() has to succeed</phrase>
12651    <phrase role="identifier">chanp</phrase><phrase role="special">-&gt;</phrase><phrase role="identifier">close</phrase><phrase role="special">();</phrase>
12652    <phrase role="keyword">return</phrase> <phrase role="identifier">value</phrase><phrase role="special">;</phrase>
12653<phrase role="special">}</phrase>
12654</programlisting>
12655        </para>
12656        <para>
12657          <anchor id="wait_first_value_impl"/>The meat of the <code><phrase role="identifier">wait_first_value_impl</phrase><phrase
12658          role="special">()</phrase></code> function is as you might expect:
12659        </para>
12660        <para>
12661<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>
12662<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>
12663                            <phrase role="identifier">Fn</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="identifier">function</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
12664    <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>
12665                              <phrase role="comment">// Ignore channel_op_status returned by push():</phrase>
12666                              <phrase role="comment">// might be closed; we simply don't care.</phrase>
12667                              <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>
12668                          <phrase role="special">}).</phrase><phrase role="identifier">detach</phrase><phrase role="special">();</phrase>
12669<phrase role="special">}</phrase>
12670</programlisting>
12671        </para>
12672        <para>
12673          It calls the passed function, pushes its return value and ignores the
12674          <code><phrase role="identifier">push</phrase><phrase role="special">()</phrase></code>
12675          result. You might call it like this:
12676        </para>
12677        <para>
12678<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>
12679        <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>
12680        <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>
12681        <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>
12682<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>
12683<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>
12684</programlisting>
12685        </para>
12686      </section>
12687      <section id="fiber.when_any.when_any.when_any__produce_first_outcome__whether_result_or_exception">
12688        <title><link linkend="fiber.when_any.when_any.when_any__produce_first_outcome__whether_result_or_exception">when_any,
12689        produce first outcome, whether result or exception</link></title>
12690        <para>
12691          We may not be running in an environment in which we can guarantee no exception
12692          will be thrown by any of our task functions. In that case, the above implementations
12693          of <code><phrase role="identifier">wait_first_something</phrase><phrase
12694          role="special">()</phrase></code> would be naïve: as mentioned in <link
12695          linkend="exceptions">the section on Fiber Management</link>, an uncaught
12696          exception in one of our task fibers would cause <code><phrase role="identifier">std</phrase><phrase
12697          role="special">::</phrase><phrase role="identifier">terminate</phrase><phrase
12698          role="special">()</phrase></code> to be called.
12699        </para>
12700        <para>
12701          Let's at least ensure that such an exception would propagate to the fiber
12702          awaiting the first result. We can use <link linkend="class_future"><code>future&lt;&gt;</code></link> to transport
12703          either a return value or an exception. Therefore, we will change <link
12704          linkend="wait_first_value"><code><phrase role="identifier">wait_first_value</phrase><phrase
12705          role="special">()</phrase></code></link>'s <link linkend="class_buffered_channel"><code>buffered_channel&lt;&gt;</code></link> to
12706          hold <code><phrase role="identifier">future</phrase><phrase role="special">&lt;</phrase>
12707          <phrase role="identifier">T</phrase> <phrase role="special">&gt;</phrase></code>
12708          items instead of simply <code><phrase role="identifier">T</phrase></code>.
12709        </para>
12710        <para>
12711          Once we have a <code><phrase role="identifier">future</phrase><phrase role="special">&lt;&gt;</phrase></code>
12712          in hand, all we need do is call <link linkend="future_get"><code>future::get()</code></link>, which will either
12713          return the value or rethrow the exception.
12714        </para>
12715        <para>
12716          <anchor id="wait_first_outcome"/>
12717<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>
12718<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>
12719<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>
12720    <phrase role="comment">// In this case, the value we pass through the channel is actually a</phrase>
12721    <phrase role="comment">// future -- which is already ready. future can carry either a value or an</phrase>
12722    <phrase role="comment">// exception.</phrase>
12723    <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>
12724    <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>
12725    <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>
12726    <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>
12727    <phrase role="comment">// launch all the relevant fibers</phrase>
12728    <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>
12729                                         <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>
12730                                         <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>
12731    <phrase role="comment">// retrieve the first future</phrase>
12732    <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>
12733    <phrase role="comment">// close the channel: no subsequent push() has to succeed</phrase>
12734    <phrase role="identifier">chanp</phrase><phrase role="special">-&gt;</phrase><phrase role="identifier">close</phrase><phrase role="special">();</phrase>
12735    <phrase role="comment">// either return value or throw exception</phrase>
12736    <phrase role="keyword">return</phrase> <phrase role="identifier">future</phrase><phrase role="special">.</phrase><phrase role="identifier">get</phrase><phrase role="special">();</phrase>
12737<phrase role="special">}</phrase>
12738</programlisting>
12739        </para>
12740        <para>
12741          So far so good &mdash; but there's a timing issue. How should we obtain the <code><phrase
12742          role="identifier">future</phrase><phrase role="special">&lt;&gt;</phrase></code>
12743          to <link linkend="buffered_channel_push"><code>buffered_channel::push()</code></link> on the queue?
12744        </para>
12745        <para>
12746          We could call <link linkend="fibers_async"><code>fibers::async()</code></link>. That would certainly produce
12747          a <code><phrase role="identifier">future</phrase><phrase role="special">&lt;&gt;</phrase></code>
12748          for the task function. The trouble is that it would return too quickly!
12749          We only want <code><phrase role="identifier">future</phrase><phrase role="special">&lt;&gt;</phrase></code>
12750          items for <emphasis>completed</emphasis> tasks on our <code><phrase role="identifier">queue</phrase><phrase
12751          role="special">&lt;&gt;</phrase></code>. In fact, we only want the <code><phrase
12752          role="identifier">future</phrase><phrase role="special">&lt;&gt;</phrase></code>
12753          for the one that completes first. If each fiber launched by <code><phrase
12754          role="identifier">wait_first_outcome</phrase><phrase role="special">()</phrase></code>
12755          were to <code><phrase role="identifier">push</phrase><phrase role="special">()</phrase></code>
12756          the result of calling <code><phrase role="identifier">async</phrase><phrase
12757          role="special">()</phrase></code>, the queue would only ever report the
12758          result of the leftmost task item &mdash; <emphasis>not</emphasis> the one that
12759          completes most quickly.
12760        </para>
12761        <para>
12762          Calling <link linkend="future_get"><code>future::get()</code></link> on the future returned by <code><phrase
12763          role="identifier">async</phrase><phrase role="special">()</phrase></code>
12764          wouldn't be right. You can only call <code><phrase role="identifier">get</phrase><phrase
12765          role="special">()</phrase></code> once per <code><phrase role="identifier">future</phrase><phrase
12766          role="special">&lt;&gt;</phrase></code> instance! And if there were an
12767          exception, it would be rethrown inside the helper fiber at the producer
12768          end of the queue, rather than propagated to the consumer end.
12769        </para>
12770        <para>
12771          We could call <link linkend="future_wait"><code>future::wait()</code></link>. That would block the helper fiber
12772          until the <code><phrase role="identifier">future</phrase><phrase role="special">&lt;&gt;</phrase></code>
12773          became ready, at which point we could <code><phrase role="identifier">push</phrase><phrase
12774          role="special">()</phrase></code> it to be retrieved by <code><phrase role="identifier">wait_first_outcome</phrase><phrase
12775          role="special">()</phrase></code>.
12776        </para>
12777        <para>
12778          That would work &mdash; but there's a simpler tactic that avoids creating an extra
12779          fiber. We can wrap the task function in a <link linkend="class_packaged_task"><code>packaged_task&lt;&gt;</code></link>.
12780          While one naturally thinks of passing a <code><phrase role="identifier">packaged_task</phrase><phrase
12781          role="special">&lt;&gt;</phrase></code> to a new fiber &mdash; that is, in fact,
12782          what <code><phrase role="identifier">async</phrase><phrase role="special">()</phrase></code>
12783          does &mdash; in this case, we're already running in the helper fiber at the producer
12784          end of the queue! We can simply <emphasis>call</emphasis> the <code><phrase
12785          role="identifier">packaged_task</phrase><phrase role="special">&lt;&gt;</phrase></code>.
12786          On return from that call, the task function has completed, meaning that
12787          the <code><phrase role="identifier">future</phrase><phrase role="special">&lt;&gt;</phrase></code>
12788          obtained from the <code><phrase role="identifier">packaged_task</phrase><phrase
12789          role="special">&lt;&gt;</phrase></code> is certain to be ready. At that
12790          point we can simply <code><phrase role="identifier">push</phrase><phrase
12791          role="special">()</phrase></code> it to the queue.
12792        </para>
12793        <para>
12794          <anchor id="wait_first_outcome_impl"/>
12795<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>
12796<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>
12797    <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>
12798        <phrase role="comment">// Use std::bind() here for C++11 compatibility. C++11 lambda capture</phrase>
12799        <phrase role="comment">// can't move a move-only Fn type, but bind() can. Let bind() move the</phrase>
12800        <phrase role="comment">// channel pointer and the function into the bound object, passing</phrase>
12801        <phrase role="comment">// references into the lambda.</phrase>
12802        <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">bind</phrase><phrase role="special">(</phrase>
12803            <phrase role="special">[](</phrase> <phrase role="identifier">CHANP</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">chan</phrase><phrase role="special">,</phrase>
12804                <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>
12805                <phrase role="comment">// Instantiate a packaged_task to capture any exception thrown by</phrase>
12806                <phrase role="comment">// function.</phrase>
12807                <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>
12808                <phrase role="comment">// Immediately run this packaged_task on same fiber. We want</phrase>
12809                <phrase role="comment">// function() to have completed BEFORE we push the future.</phrase>
12810                <phrase role="identifier">task</phrase><phrase role="special">();</phrase>
12811                <phrase role="comment">// Pass the corresponding future to consumer. Ignore</phrase>
12812                <phrase role="comment">// channel_op_status returned by push(): might be closed; we</phrase>
12813                <phrase role="comment">// simply don't care.</phrase>
12814                <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>
12815            <phrase role="special">},</phrase>
12816            <phrase role="identifier">chan</phrase><phrase role="special">,</phrase>
12817            <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>
12818        <phrase role="special">)).</phrase><phrase role="identifier">detach</phrase><phrase role="special">();</phrase>
12819<phrase role="special">}</phrase>
12820</programlisting>
12821        </para>
12822        <para>
12823          Calling it might look like this:
12824        </para>
12825        <para>
12826<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>
12827        <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>
12828        <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>
12829        <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>
12830<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>
12831<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>
12832
12833<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="identifier">thrown</phrase><phrase role="special">;</phrase>
12834<phrase role="keyword">try</phrase> <phrase role="special">{</phrase>
12835    <phrase role="identifier">result</phrase> <phrase role="special">=</phrase> <phrase role="identifier">wait_first_outcome</phrase><phrase role="special">(</phrase>
12836            <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>
12837            <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>
12838            <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>
12839<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>
12840    <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>
12841<phrase role="special">}</phrase>
12842<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>
12843          <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>
12844<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>
12845</programlisting>
12846        </para>
12847      </section>
12848      <section id="fiber.when_any.when_any.when_any__produce_first_success">
12849        <title><link linkend="fiber.when_any.when_any.when_any__produce_first_success">when_any,
12850        produce first success</link></title>
12851        <para>
12852          One scenario for <quote>when_any</quote> functionality is when we're redundantly
12853          contacting some number of possibly-unreliable web services. Not only might
12854          they be slow &mdash; any one of them might produce a failure rather than the desired
12855          result.
12856        </para>
12857        <para>
12858          In such a case, <link linkend="wait_first_outcome"><code><phrase role="identifier">wait_first_outcome</phrase><phrase
12859          role="special">()</phrase></code></link> isn't the right approach. If one
12860          of the services produces an error quickly, while another follows up with
12861          a real answer, we don't want to prefer the error just because it arrived
12862          first!
12863        </para>
12864        <para>
12865          Given the <code><phrase role="identifier">queue</phrase><phrase role="special">&lt;</phrase>
12866          <phrase role="identifier">future</phrase><phrase role="special">&lt;</phrase>
12867          <phrase role="identifier">T</phrase> <phrase role="special">&gt;</phrase>
12868          <phrase role="special">&gt;</phrase></code> we already constructed for
12869          <code><phrase role="identifier">wait_first_outcome</phrase><phrase role="special">()</phrase></code>,
12870          though, we can readily recast the interface function to deliver the first
12871          <emphasis>successful</emphasis> result.
12872        </para>
12873        <para>
12874          That does beg the question: what if <emphasis>all</emphasis> the task functions
12875          throw an exception? In that case we'd probably better know about it.
12876        </para>
12877        <para>
12878          <anchor id="exception_list"/>The <ulink url="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4407.html#parallel.exceptions.synopsis">C++
12879          Parallelism Draft Technical Specification</ulink> proposes a <code><phrase
12880          role="identifier">std</phrase><phrase role="special">::</phrase><phrase
12881          role="identifier">exception_list</phrase></code> exception capable of delivering
12882          a collection of <code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase
12883          role="identifier">exception_ptr</phrase></code>s. Until that becomes universally
12884          available, let's fake up an <code><phrase role="identifier">exception_list</phrase></code>
12885          of our own:
12886        </para>
12887        <para>
12888<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>
12889<phrase role="keyword">public</phrase><phrase role="special">:</phrase>
12890    <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>
12891        <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>
12892    <phrase role="special">}</phrase>
12893
12894    <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>
12895
12896    <phrase role="comment">// N4407 proposed std::exception_list API</phrase>
12897    <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>
12898
12899    <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>
12900        <phrase role="keyword">return</phrase> <phrase role="identifier">bundle_</phrase><phrase role="special">.</phrase><phrase role="identifier">size</phrase><phrase role="special">();</phrase>
12901    <phrase role="special">}</phrase>
12902
12903    <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>
12904        <phrase role="keyword">return</phrase> <phrase role="identifier">bundle_</phrase><phrase role="special">.</phrase><phrase role="identifier">begin</phrase><phrase role="special">();</phrase>
12905    <phrase role="special">}</phrase>
12906
12907    <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>
12908        <phrase role="keyword">return</phrase> <phrase role="identifier">bundle_</phrase><phrase role="special">.</phrase><phrase role="identifier">end</phrase><phrase role="special">();</phrase>
12909    <phrase role="special">}</phrase>
12910
12911    <phrase role="comment">// extension to populate</phrase>
12912    <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>
12913        <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>
12914    <phrase role="special">}</phrase>
12915
12916<phrase role="keyword">private</phrase><phrase role="special">:</phrase>
12917    <phrase role="identifier">bundle_t</phrase> <phrase role="identifier">bundle_</phrase><phrase role="special">;</phrase>
12918<phrase role="special">};</phrase>
12919</programlisting>
12920        </para>
12921        <para>
12922          Now we can build <code><phrase role="identifier">wait_first_success</phrase><phrase
12923          role="special">()</phrase></code>, using <link linkend="wait_first_outcome_impl"><code><phrase
12924          role="identifier">wait_first_outcome_impl</phrase><phrase role="special">()</phrase></code></link>.
12925        </para>
12926        <para>
12927          Instead of retrieving only the first <code><phrase role="identifier">future</phrase><phrase
12928          role="special">&lt;&gt;</phrase></code> from the queue, we must now loop
12929          over <code><phrase role="identifier">future</phrase><phrase role="special">&lt;&gt;</phrase></code>
12930          items. Of course we must limit that iteration! If we launch only <code><phrase
12931          role="identifier">count</phrase></code> producer fibers, the <code><phrase
12932          role="special">(</phrase><phrase role="identifier">count</phrase><phrase
12933          role="special">+</phrase><phrase role="number">1</phrase><phrase role="special">)</phrase></code><superscript>st</superscript>
12934<link linkend="buffered_channel_pop"><code>buffered_channel::pop()</code></link> call
12935          would block forever.
12936        </para>
12937        <para>
12938          Given a ready <code><phrase role="identifier">future</phrase><phrase role="special">&lt;&gt;</phrase></code>,
12939          we can distinguish failure by calling <link linkend="future_get_exception_ptr"><code>future::get_exception_ptr()</code></link>.
12940          If the <code><phrase role="identifier">future</phrase><phrase role="special">&lt;&gt;</phrase></code>
12941          in fact contains a result rather than an exception, <code><phrase role="identifier">get_exception_ptr</phrase><phrase
12942          role="special">()</phrase></code> returns <code><phrase role="keyword">nullptr</phrase></code>.
12943          In that case, we can confidently call <link linkend="future_get"><code>future::get()</code></link> to return
12944          that result to our caller.
12945        </para>
12946        <para>
12947          If the <code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase
12948          role="identifier">exception_ptr</phrase></code> is <emphasis>not</emphasis>
12949          <code><phrase role="keyword">nullptr</phrase></code>, though, we collect
12950          it into our pending <code><phrase role="identifier">exception_list</phrase></code>
12951          and loop back for the next <code><phrase role="identifier">future</phrase><phrase
12952          role="special">&lt;&gt;</phrase></code> from the queue.
12953        </para>
12954        <para>
12955          If we fall out of the loop &mdash; if every single task fiber threw an exception
12956          &mdash; we throw the <code><phrase role="identifier">exception_list</phrase></code>
12957          exception into which we've been collecting those <code><phrase role="identifier">std</phrase><phrase
12958          role="special">::</phrase><phrase role="identifier">exception_ptr</phrase></code>s.
12959        </para>
12960        <para>
12961          <anchor id="wait_first_success"/>
12962<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>
12963<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>
12964<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>
12965    <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>
12966    <phrase role="comment">// In this case, the value we pass through the channel is actually a</phrase>
12967    <phrase role="comment">// future -- which is already ready. future can carry either a value or an</phrase>
12968    <phrase role="comment">// exception.</phrase>
12969    <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>
12970    <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>
12971    <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>
12972    <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>
12973    <phrase role="comment">// launch all the relevant fibers</phrase>
12974    <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>
12975                                         <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>
12976                                         <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>
12977    <phrase role="comment">// instantiate exception_list, just in case</phrase>
12978    <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>
12979    <phrase role="comment">// retrieve up to 'count' results -- but stop there!</phrase>
12980    <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>
12981        <phrase role="comment">// retrieve the next future</phrase>
12982        <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>
12983        <phrase role="comment">// retrieve exception_ptr if any</phrase>
12984        <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>
12985        <phrase role="comment">// if no error, then yay, return value</phrase>
12986        <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>
12987            <phrase role="comment">// close the channel: no subsequent push() has to succeed</phrase>
12988            <phrase role="identifier">chanp</phrase><phrase role="special">-&gt;</phrase><phrase role="identifier">close</phrase><phrase role="special">();</phrase>
12989            <phrase role="comment">// show caller the value we got</phrase>
12990            <phrase role="keyword">return</phrase> <phrase role="identifier">future</phrase><phrase role="special">.</phrase><phrase role="identifier">get</phrase><phrase role="special">();</phrase>
12991        <phrase role="special">}</phrase>
12992
12993        <phrase role="comment">// error is non-null: collect</phrase>
12994        <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>
12995    <phrase role="special">}</phrase>
12996    <phrase role="comment">// We only arrive here when every passed function threw an exception.</phrase>
12997    <phrase role="comment">// Throw our collection to inform caller.</phrase>
12998    <phrase role="keyword">throw</phrase> <phrase role="identifier">exceptions</phrase><phrase role="special">;</phrase>
12999<phrase role="special">}</phrase>
13000</programlisting>
13001        </para>
13002        <para>
13003          A call might look like this:
13004        </para>
13005        <para>
13006<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>
13007            <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>
13008            <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>
13009            <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>
13010<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>
13011<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>
13012</programlisting>
13013        </para>
13014      </section>
13015      <section id="fiber.when_any.when_any.when_any__heterogeneous_types">
13016        <title><link linkend="fiber.when_any.when_any.when_any__heterogeneous_types">when_any,
13017        heterogeneous types</link></title>
13018        <para>
13019          We would be remiss to ignore the case in which the various task functions
13020          have distinct return types. That means that the value returned by the first
13021          of them might have any one of those types. We can express that with <ulink
13022          url="http://www.boost.org/doc/libs/release/doc/html/variant.html">Boost.Variant</ulink>.
13023        </para>
13024        <para>
13025          To keep the example simple, we'll revert to pretending that none of them
13026          can throw an exception. That makes <code><phrase role="identifier">wait_first_value_het</phrase><phrase
13027          role="special">()</phrase></code> strongly resemble <link linkend="wait_first_value"><code><phrase
13028          role="identifier">wait_first_value</phrase><phrase role="special">()</phrase></code></link>.
13029          We can actually reuse <link linkend="wait_first_value_impl"><code><phrase
13030          role="identifier">wait_first_value_impl</phrase><phrase role="special">()</phrase></code></link>,
13031          merely passing <code><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase
13032          role="identifier">variant</phrase><phrase role="special">&lt;</phrase><phrase
13033          role="identifier">T0</phrase><phrase role="special">,</phrase> <phrase
13034          role="identifier">T1</phrase><phrase role="special">,</phrase> <phrase
13035          role="special">...&gt;</phrase></code> as the queue's value type rather
13036          than the common <code><phrase role="identifier">T</phrase></code>!
13037        </para>
13038        <para>
13039          Naturally this could be extended to use <link linkend="wait_first_success"><code><phrase
13040          role="identifier">wait_first_success</phrase><phrase role="special">()</phrase></code></link>
13041          semantics instead.
13042        </para>
13043        <para>
13044<programlisting><phrase role="comment">// No need to break out the first Fn for interface function: let the compiler</phrase>
13045<phrase role="comment">// complain if empty.</phrase>
13046<phrase role="comment">// Our functions have different return types, and we might have to return any</phrase>
13047<phrase role="comment">// of them. Use a variant, expanding std::result_of&lt;Fn()&gt;::type for each Fn in</phrase>
13048<phrase role="comment">// parameter pack.</phrase>
13049<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>
13050<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>
13051<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>
13052    <phrase role="comment">// Use buffered_channel&lt;boost::variant&lt;T1, T2, ...&gt;&gt;; see remarks above.</phrase>
13053    <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>
13054    <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>
13055    <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>
13056    <phrase role="comment">// launch all the relevant fibers</phrase>
13057    <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>
13058                                       <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>
13059    <phrase role="comment">// retrieve the first value</phrase>
13060    <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>
13061    <phrase role="comment">// close the channel: no subsequent push() has to succeed</phrase>
13062    <phrase role="identifier">chanp</phrase><phrase role="special">-&gt;</phrase><phrase role="identifier">close</phrase><phrase role="special">();</phrase>
13063    <phrase role="keyword">return</phrase> <phrase role="identifier">value</phrase><phrase role="special">;</phrase>
13064<phrase role="special">}</phrase>
13065</programlisting>
13066        </para>
13067        <para>
13068          It might be called like this:
13069        </para>
13070        <para>
13071<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>
13072    <phrase role="identifier">wait_first_value_het</phrase><phrase role="special">(</phrase>
13073            <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>
13074            <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>
13075            <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>
13076<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>
13077<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>
13078</programlisting>
13079        </para>
13080      </section>
13081      <section id="fiber.when_any.when_any.when_any__a_dubious_alternative">
13082        <title><link linkend="fiber.when_any.when_any.when_any__a_dubious_alternative">when_any,
13083        a dubious alternative</link></title>
13084        <para>
13085          Certain topics in C++ can arouse strong passions, and exceptions are no
13086          exception. We cannot resist mentioning &mdash; for purely informational purposes
13087          &mdash; that when you need only the <emphasis>first</emphasis> result from some
13088          number of concurrently-running fibers, it would be possible to pass a
13089          <literal>shared_ptr&lt;<link linkend="class_promise"><code>promise&lt;&gt;</code></link>&gt;</literal> to the
13090          participating fibers, then cause the initiating fiber to call <link linkend="future_get"><code>future::get()</code></link> on
13091          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
13092          that shared <code><phrase role="identifier">promise</phrase></code> will
13093          succeed; subsequent <code><phrase role="identifier">set_value</phrase><phrase
13094          role="special">()</phrase></code> calls on the same <code><phrase role="identifier">promise</phrase></code>
13095          instance will throw <code><phrase role="identifier">future_error</phrase></code>.
13096        </para>
13097        <para>
13098          Use this information at your own discretion. Beware the dark side.
13099        </para>
13100      </section>
13101    </section>
13102    <section id="fiber.when_any.when_all_functionality">
13103      <title><link linkend="fiber.when_any.when_all_functionality">when_all functionality</link></title>
13104      <section id="fiber.when_any.when_all_functionality.when_all__simple_completion">
13105        <title><link linkend="fiber.when_any.when_all_functionality.when_all__simple_completion">when_all,
13106        simple completion</link></title>
13107        <para>
13108          For the case in which we must wait for <emphasis>all</emphasis> task functions
13109          to complete &mdash; but we don't need results (or expect exceptions) from any of
13110          them &mdash; we can write <code><phrase role="identifier">wait_all_simple</phrase><phrase
13111          role="special">()</phrase></code> that looks remarkably like <link linkend="wait_first_simple"><code><phrase
13112          role="identifier">wait_first_simple</phrase><phrase role="special">()</phrase></code></link>.
13113          The difference is that instead of our <link linkend="wait_done"><code><phrase
13114          role="identifier">Done</phrase></code></link> class, we instantiate a <link linkend="class_barrier"><code>barrier</code></link> and
13115          call its <link linkend="barrier_wait"><code>barrier::wait()</code></link>.
13116        </para>
13117        <para>
13118          We initialize the <code><phrase role="identifier">barrier</phrase></code>
13119          with <code><phrase role="special">(</phrase><phrase role="identifier">count</phrase><phrase
13120          role="special">+</phrase><phrase role="number">1</phrase><phrase role="special">)</phrase></code>
13121          because we are launching <code><phrase role="identifier">count</phrase></code>
13122          fibers, plus the <code><phrase role="identifier">wait</phrase><phrase role="special">()</phrase></code>
13123          call within <code><phrase role="identifier">wait_all_simple</phrase><phrase
13124          role="special">()</phrase></code> itself.
13125        </para>
13126        <para>
13127<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>
13128<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>
13129    <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>
13130    <phrase role="comment">// Initialize a barrier(count+1) because we'll immediately wait on it. We</phrase>
13131    <phrase role="comment">// don't want to wake up until 'count' more fibers wait on it. Even though</phrase>
13132    <phrase role="comment">// we'll stick around until the last of them completes, use shared_ptr</phrase>
13133    <phrase role="comment">// anyway because it's easier to be confident about lifespan issues.</phrase>
13134    <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>
13135    <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>
13136    <phrase role="identifier">barrier</phrase><phrase role="special">-&gt;</phrase><phrase role="identifier">wait</phrase><phrase role="special">();</phrase>
13137<phrase role="special">}</phrase>
13138</programlisting>
13139        </para>
13140        <para>
13141          As stated above, the only difference between <code><phrase role="identifier">wait_all_simple_impl</phrase><phrase
13142          role="special">()</phrase></code> and <link linkend="wait_first_simple_impl"><code><phrase
13143          role="identifier">wait_first_simple_impl</phrase><phrase role="special">()</phrase></code></link>
13144          is that the former calls <code><phrase role="identifier">barrier</phrase><phrase
13145          role="special">::</phrase><phrase role="identifier">wait</phrase><phrase
13146          role="special">()</phrase></code> rather than <code><phrase role="identifier">Done</phrase><phrase
13147          role="special">::</phrase><phrase role="identifier">notify</phrase><phrase
13148          role="special">()</phrase></code>:
13149        </para>
13150        <para>
13151<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>
13152<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>
13153                           <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>
13154    <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>
13155            <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">bind</phrase><phrase role="special">(</phrase>
13156                <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>
13157                    <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>
13158                        <phrase role="identifier">function</phrase><phrase role="special">();</phrase>
13159                        <phrase role="identifier">barrier</phrase><phrase role="special">-&gt;</phrase><phrase role="identifier">wait</phrase><phrase role="special">();</phrase>
13160                <phrase role="special">},</phrase>
13161                <phrase role="identifier">barrier</phrase><phrase role="special">,</phrase>
13162                <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>
13163            <phrase role="special">)).</phrase><phrase role="identifier">detach</phrase><phrase role="special">();</phrase>
13164    <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>
13165<phrase role="special">}</phrase>
13166</programlisting>
13167        </para>
13168        <para>
13169          You might call it like this:
13170        </para>
13171        <para>
13172<programlisting><phrase role="identifier">wait_all_simple</phrase><phrase role="special">(</phrase>
13173        <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>
13174        <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>
13175        <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>
13176</programlisting>
13177        </para>
13178        <para>
13179          Control will not return from the <code><phrase role="identifier">wait_all_simple</phrase><phrase
13180          role="special">()</phrase></code> call until the last of its task functions
13181          has completed.
13182        </para>
13183      </section>
13184      <section id="fiber.when_any.when_all_functionality.when_all__return_values">
13185        <title><link linkend="fiber.when_any.when_all_functionality.when_all__return_values">when_all,
13186        return values</link></title>
13187        <para>
13188          As soon as we want to collect return values from all the task functions,
13189          we can see right away how to reuse <link linkend="wait_first_value"><code><phrase
13190          role="identifier">wait_first_value</phrase><phrase role="special">()</phrase></code></link>'s
13191          queue&lt;T&gt; for the purpose. All we have to do is avoid closing it after
13192          the first value!
13193        </para>
13194        <para>
13195          But in fact, collecting multiple values raises an interesting question:
13196          do we <emphasis>really</emphasis> want to wait until the slowest of them
13197          has arrived? Wouldn't we rather process each result as soon as it becomes
13198          available?
13199        </para>
13200        <para>
13201          Fortunately we can present both APIs. Let's define <code><phrase role="identifier">wait_all_values_source</phrase><phrase
13202          role="special">()</phrase></code> to return <code><phrase role="identifier">shared_ptr</phrase><phrase
13203          role="special">&lt;</phrase><phrase role="identifier">buffered_channel</phrase><phrase
13204          role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase
13205          role="special">&gt;&gt;</phrase></code>.
13206        </para>
13207        <para>
13208          <anchor id="wait_all_values"/>Given <code><phrase role="identifier">wait_all_values_source</phrase><phrase
13209          role="special">()</phrase></code>, it's straightforward to implement <code><phrase
13210          role="identifier">wait_all_values</phrase><phrase role="special">()</phrase></code>:
13211        </para>
13212        <para>
13213<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>
13214<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>
13215<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>
13216    <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>
13217    <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>
13218    <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>
13219    <phrase role="identifier">vector_t</phrase> <phrase role="identifier">results</phrase><phrase role="special">;</phrase>
13220    <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>
13221
13222    <phrase role="comment">// get channel</phrase>
13223    <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>
13224        <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>
13225                                <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>
13226    <phrase role="comment">// fill results vector</phrase>
13227    <phrase role="identifier">return_t</phrase> <phrase role="identifier">value</phrase><phrase role="special">;</phrase>
13228    <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>
13229        <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>
13230    <phrase role="special">}</phrase>
13231    <phrase role="comment">// return vector to caller</phrase>
13232    <phrase role="keyword">return</phrase> <phrase role="identifier">results</phrase><phrase role="special">;</phrase>
13233<phrase role="special">}</phrase>
13234</programlisting>
13235        </para>
13236        <para>
13237          It might be called like this:
13238        </para>
13239        <para>
13240<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>
13241    <phrase role="identifier">wait_all_values</phrase><phrase role="special">(</phrase>
13242            <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>
13243            <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>
13244            <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>
13245</programlisting>
13246        </para>
13247        <para>
13248          As you can see from the loop in <code><phrase role="identifier">wait_all_values</phrase><phrase
13249          role="special">()</phrase></code>, instead of requiring its caller to count
13250          values, we define <code><phrase role="identifier">wait_all_values_source</phrase><phrase
13251          role="special">()</phrase></code> to <link linkend="buffered_channel_close"><code>buffered_channel::close()</code></link> the
13252          queue when done. But how do we do that? Each producer fiber is independent.
13253          It has no idea whether it is the last one to <link linkend="buffered_channel_push"><code>buffered_channel::push()</code></link> a
13254          value.
13255        </para>
13256        <para>
13257          <anchor id="wait_nqueue"/>We can address that problem with a counting façade
13258          for the <code><phrase role="identifier">queue</phrase><phrase role="special">&lt;&gt;</phrase></code>.
13259          In fact, our façade need only support the producer end of the queue.
13260        </para>
13261        <para>
13262          [wait_nqueue]
13263        </para>
13264        <para>
13265          <anchor id="wait_all_values_source"/>Armed with <code><phrase role="identifier">nqueue</phrase><phrase
13266          role="special">&lt;&gt;</phrase></code>, we can implement <code><phrase
13267          role="identifier">wait_all_values_source</phrase><phrase role="special">()</phrase></code>.
13268          It starts just like <link linkend="wait_first_value"><code><phrase role="identifier">wait_first_value</phrase><phrase
13269          role="special">()</phrase></code></link>. The difference is that we wrap
13270          the <code><phrase role="identifier">queue</phrase><phrase role="special">&lt;</phrase><phrase
13271          role="identifier">T</phrase><phrase role="special">&gt;</phrase></code>
13272          with an <code><phrase role="identifier">nqueue</phrase><phrase role="special">&lt;</phrase><phrase
13273          role="identifier">T</phrase><phrase role="special">&gt;</phrase></code>
13274          to pass to the producer fibers.
13275        </para>
13276        <para>
13277          Then, of course, instead of popping the first value, closing the queue
13278          and returning it, we simply return the <code><phrase role="identifier">shared_ptr</phrase><phrase
13279          role="special">&lt;</phrase><phrase role="identifier">queue</phrase><phrase
13280          role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase
13281          role="special">&gt;&gt;</phrase></code>.
13282        </para>
13283        <para>
13284<programlisting><phrase role="comment">// Return a shared_ptr&lt;buffered_channel&lt;T&gt;&gt; from which the caller can</phrase>
13285<phrase role="comment">// retrieve each new result as it arrives, until 'closed'.</phrase>
13286<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>
13287<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>
13288<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>
13289    <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>
13290    <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>
13291    <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>
13292    <phrase role="comment">// make the channel</phrase>
13293    <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>
13294    <phrase role="comment">// and make an nchannel facade to close it after 'count' items</phrase>
13295    <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>
13296    <phrase role="comment">// pass that nchannel facade to all the relevant fibers</phrase>
13297    <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>
13298                                      <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>
13299                                      <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>
13300    <phrase role="comment">// then return the channel for consumer</phrase>
13301    <phrase role="keyword">return</phrase> <phrase role="identifier">chanp</phrase><phrase role="special">;</phrase>
13302<phrase role="special">}</phrase>
13303</programlisting>
13304        </para>
13305        <para>
13306          For example:
13307        </para>
13308        <para>
13309<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>
13310    <phrase role="identifier">wait_all_values_source</phrase><phrase role="special">(</phrase>
13311            <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>
13312            <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>
13313            <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>
13314<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="identifier">value</phrase><phrase role="special">;</phrase>
13315<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>
13316    <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>
13317              <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>
13318<phrase role="special">}</phrase>
13319</programlisting>
13320        </para>
13321        <para>
13322          <anchor id="wait_all_values_impl"/><code><phrase role="identifier">wait_all_values_impl</phrase><phrase
13323          role="special">()</phrase></code> really is just like <link linkend="wait_first_value_impl"><code><phrase
13324          role="identifier">wait_first_value_impl</phrase><phrase role="special">()</phrase></code></link>
13325          except for the use of <code><phrase role="identifier">nqueue</phrase><phrase
13326          role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase
13327          role="special">&gt;</phrase></code> rather than <code><phrase role="identifier">queue</phrase><phrase
13328          role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase
13329          role="special">&gt;</phrase></code>:
13330        </para>
13331        <para>
13332<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>
13333<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>
13334                           <phrase role="identifier">Fn</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="identifier">function</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
13335    <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>
13336                              <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>
13337                          <phrase role="special">}).</phrase><phrase role="identifier">detach</phrase><phrase role="special">();</phrase>
13338<phrase role="special">}</phrase>
13339</programlisting>
13340        </para>
13341      </section>
13342      <section id="fiber.when_any.when_all_functionality.when_all_until_first_exception">
13343        <title><link linkend="fiber.when_any.when_all_functionality.when_all_until_first_exception">when_all
13344        until first exception</link></title>
13345        <para>
13346          Naturally, just as with <link linkend="wait_first_outcome"><code><phrase
13347          role="identifier">wait_first_outcome</phrase><phrase role="special">()</phrase></code></link>,
13348          we can elaborate <link linkend="wait_all_values"><code><phrase role="identifier">wait_all_values</phrase><phrase
13349          role="special">()</phrase></code></link> and <link linkend="wait_all_values_source"><code><phrase
13350          role="identifier">wait_all_values_source</phrase><phrase role="special">()</phrase></code></link>
13351          by passing <code><phrase role="identifier">future</phrase><phrase role="special">&lt;</phrase>
13352          <phrase role="identifier">T</phrase> <phrase role="special">&gt;</phrase></code>
13353          instead of plain <code><phrase role="identifier">T</phrase></code>.
13354        </para>
13355        <para>
13356          <anchor id="wait_all_until_error"/><code><phrase role="identifier">wait_all_until_error</phrase><phrase
13357          role="special">()</phrase></code> pops that <code><phrase role="identifier">future</phrase><phrase
13358          role="special">&lt;</phrase> <phrase role="identifier">T</phrase> <phrase
13359          role="special">&gt;</phrase></code> and calls its <link linkend="future_get"><code>future::get()</code></link>:
13360        </para>
13361        <para>
13362<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>
13363<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>
13364<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>
13365    <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>
13366    <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>
13367    <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>
13368    <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>
13369    <phrase role="identifier">vector_t</phrase> <phrase role="identifier">results</phrase><phrase role="special">;</phrase>
13370    <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>
13371
13372    <phrase role="comment">// get channel</phrase>
13373    <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">shared_ptr</phrase><phrase role="special">&lt;</phrase>
13374        <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>
13375            <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>
13376                                         <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>
13377    <phrase role="comment">// fill results vector</phrase>
13378    <phrase role="identifier">future_t</phrase> <phrase role="identifier">future</phrase><phrase role="special">;</phrase>
13379    <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>
13380        <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>
13381    <phrase role="special">}</phrase>
13382    <phrase role="comment">// return vector to caller</phrase>
13383    <phrase role="keyword">return</phrase> <phrase role="identifier">results</phrase><phrase role="special">;</phrase>
13384<phrase role="special">}</phrase>
13385</programlisting>
13386        </para>
13387        <para>
13388          For example:
13389        </para>
13390        <para>
13391<programlisting><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="identifier">thrown</phrase><phrase role="special">;</phrase>
13392<phrase role="keyword">try</phrase> <phrase role="special">{</phrase>
13393    <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>
13394            <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>
13395            <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>
13396            <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>
13397<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>
13398    <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>
13399<phrase role="special">}</phrase>
13400<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>
13401          <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>
13402</programlisting>
13403        </para>
13404        <para>
13405          <anchor id="wait_all_until_error_source"/>Naturally this complicates the
13406          API for <code><phrase role="identifier">wait_all_until_error_source</phrase><phrase
13407          role="special">()</phrase></code>. The caller must both retrieve a <code><phrase
13408          role="identifier">future</phrase><phrase role="special">&lt;</phrase>
13409          <phrase role="identifier">T</phrase> <phrase role="special">&gt;</phrase></code>
13410          and call its <code><phrase role="identifier">get</phrase><phrase role="special">()</phrase></code>
13411          method. It would, of course, be possible to return a façade over the consumer
13412          end of the queue that would implicitly perform the <code><phrase role="identifier">get</phrase><phrase
13413          role="special">()</phrase></code> and return a simple <code><phrase role="identifier">T</phrase></code>
13414          (or throw).
13415        </para>
13416        <para>
13417          The implementation is just as you would expect. Notice, however, that we
13418          can reuse <link linkend="wait_first_outcome_impl"><code><phrase role="identifier">wait_first_outcome_impl</phrase><phrase
13419          role="special">()</phrase></code></link>, passing the <code><phrase role="identifier">nqueue</phrase><phrase
13420          role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase
13421          role="special">&gt;</phrase></code> rather than <code><phrase role="identifier">queue</phrase><phrase
13422          role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase
13423          role="special">&gt;</phrase></code>.
13424        </para>
13425        <para>
13426<programlisting><phrase role="comment">// Return a shared_ptr&lt;buffered_channel&lt;future&lt;T&gt;&gt;&gt; from which the caller can</phrase>
13427<phrase role="comment">// get() each new result as it arrives, until 'closed'.</phrase>
13428<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>
13429<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">shared_ptr</phrase><phrase role="special">&lt;</phrase>
13430    <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>
13431        <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>
13432            <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>
13433<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>
13434    <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>
13435    <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>
13436    <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>
13437    <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>
13438    <phrase role="comment">// make the channel</phrase>
13439    <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>
13440    <phrase role="comment">// and make an nchannel facade to close it after 'count' items</phrase>
13441    <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>
13442    <phrase role="comment">// pass that nchannel facade to all the relevant fibers</phrase>
13443    <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>
13444                                         <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>
13445                                         <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>
13446    <phrase role="comment">// then return the channel for consumer</phrase>
13447    <phrase role="keyword">return</phrase> <phrase role="identifier">chanp</phrase><phrase role="special">;</phrase>
13448<phrase role="special">}</phrase>
13449</programlisting>
13450        </para>
13451        <para>
13452          For example:
13453        </para>
13454        <para>
13455<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>
13456<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>
13457    <phrase role="identifier">wait_all_until_error_source</phrase><phrase role="special">(</phrase>
13458            <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>
13459            <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>
13460            <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>
13461<phrase role="identifier">future_t</phrase> <phrase role="identifier">future</phrase><phrase role="special">;</phrase>
13462<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>
13463    <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>
13464    <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>
13465              <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>
13466<phrase role="special">}</phrase>
13467</programlisting>
13468        </para>
13469      </section>
13470      <section id="fiber.when_any.when_all_functionality.wait_all__collecting_all_exceptions">
13471        <title><link linkend="fiber.when_any.when_all_functionality.wait_all__collecting_all_exceptions">wait_all,
13472        collecting all exceptions</link></title>
13473        <para>
13474          <anchor id="wait_all_collect_errors"/>Given <link linkend="wait_all_until_error_source"><code><phrase
13475          role="identifier">wait_all_until_error_source</phrase><phrase role="special">()</phrase></code></link>,
13476          it might be more reasonable to make a <code><phrase role="identifier">wait_all_</phrase><phrase
13477          role="special">...()</phrase></code> that collects <emphasis>all</emphasis>
13478          errors instead of presenting only the first:
13479        </para>
13480        <para>
13481<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>
13482<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>
13483<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>
13484    <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>
13485    <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>
13486    <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>
13487    <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>
13488    <phrase role="identifier">vector_t</phrase> <phrase role="identifier">results</phrase><phrase role="special">;</phrase>
13489    <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>
13490    <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>
13491
13492    <phrase role="comment">// get channel</phrase>
13493    <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">shared_ptr</phrase><phrase role="special">&lt;</phrase>
13494        <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>
13495            <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>
13496                                         <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>
13497    <phrase role="comment">// fill results and/or exceptions vectors</phrase>
13498    <phrase role="identifier">future_t</phrase> <phrase role="identifier">future</phrase><phrase role="special">;</phrase>
13499    <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>
13500        <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>
13501        <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>
13502            <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>
13503        <phrase role="special">}</phrase> <phrase role="keyword">else</phrase> <phrase role="special">{</phrase>
13504            <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>
13505        <phrase role="special">}</phrase>
13506    <phrase role="special">}</phrase>
13507    <phrase role="comment">// if there were any exceptions, throw</phrase>
13508    <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>
13509        <phrase role="keyword">throw</phrase> <phrase role="identifier">exceptions</phrase><phrase role="special">;</phrase>
13510    <phrase role="special">}</phrase>
13511    <phrase role="comment">// no exceptions: return vector to caller</phrase>
13512    <phrase role="keyword">return</phrase> <phrase role="identifier">results</phrase><phrase role="special">;</phrase>
13513<phrase role="special">}</phrase>
13514</programlisting>
13515        </para>
13516        <para>
13517          The implementation is a simple variation on <link linkend="wait_first_success"><code><phrase
13518          role="identifier">wait_first_success</phrase><phrase role="special">()</phrase></code></link>,
13519          using the same <link linkend="exception_list"><code><phrase role="identifier">exception_list</phrase></code></link>
13520          exception class.
13521        </para>
13522      </section>
13523      <section id="fiber.when_any.when_all_functionality.when_all__heterogeneous_types">
13524        <title><link linkend="fiber.when_any.when_all_functionality.when_all__heterogeneous_types">when_all,
13525        heterogeneous types</link></title>
13526        <para>
13527          But what about the case when we must wait for all results of different
13528          types?
13529        </para>
13530        <para>
13531          We can present an API that is frankly quite cool. Consider a sample struct:
13532        </para>
13533        <para>
13534<programlisting><phrase role="keyword">struct</phrase> <phrase role="identifier">Data</phrase> <phrase role="special">{</phrase>
13535    <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="identifier">str</phrase><phrase role="special">;</phrase>
13536    <phrase role="keyword">double</phrase>      <phrase role="identifier">inexact</phrase><phrase role="special">;</phrase>
13537    <phrase role="keyword">int</phrase>         <phrase role="identifier">exact</phrase><phrase role="special">;</phrase>
13538
13539    <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>
13540    <phrase role="special">...</phrase>
13541<phrase role="special">};</phrase>
13542</programlisting>
13543        </para>
13544        <para>
13545          Let's fill its members from task functions all running concurrently:
13546        </para>
13547        <para>
13548<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>
13549        <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>
13550        <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>
13551        <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>
13552<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>
13553</programlisting>
13554        </para>
13555        <para>
13556          Note that for this case, we abandon the notion of capturing the earliest
13557          result first, and so on: we must fill exactly the passed struct in left-to-right
13558          order.
13559        </para>
13560        <para>
13561          That permits a beautifully simple implementation:
13562        </para>
13563        <para>
13564<programlisting><phrase role="comment">// Explicitly pass Result. This can be any type capable of being initialized</phrase>
13565<phrase role="comment">// from the results of the passed functions, such as a struct.</phrase>
13566<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>
13567<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>
13568    <phrase role="comment">// Run each of the passed functions on a separate fiber, passing all their</phrase>
13569    <phrase role="comment">// futures to helper function for processing.</phrase>
13570    <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>
13571            <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>
13572<phrase role="special">}</phrase>
13573</programlisting>
13574        </para>
13575        <para>
13576<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>
13577<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>
13578    <phrase role="comment">// Fetch the results from the passed futures into Result's initializer</phrase>
13579    <phrase role="comment">// list. It's true that the get() calls here will block the implicit</phrase>
13580    <phrase role="comment">// iteration over futures -- but that doesn't matter because we won't be</phrase>
13581    <phrase role="comment">// done until the slowest of them finishes anyway. As results are</phrase>
13582    <phrase role="comment">// processed in argument-list order rather than order of completion, the</phrase>
13583    <phrase role="comment">// leftmost get() to throw an exception will cause that exception to</phrase>
13584    <phrase role="comment">// propagate to the caller.</phrase>
13585    <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>
13586<phrase role="special">}</phrase>
13587</programlisting>
13588        </para>
13589        <para>
13590          It is tempting to try to implement <code><phrase role="identifier">wait_all_members</phrase><phrase
13591          role="special">()</phrase></code> as a one-liner like this:
13592        </para>
13593<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>
13594</programlisting>
13595        <para>
13596          The trouble with this tactic is that it would serialize all the task functions.
13597          The runtime makes a single pass through <code><phrase role="identifier">functions</phrase></code>,
13598          calling <link linkend="fibers_async"><code>fibers::async()</code></link> for each and then immediately calling
13599          <link linkend="future_get"><code>future::get()</code></link> on its returned <code><phrase role="identifier">future</phrase><phrase
13600          role="special">&lt;&gt;</phrase></code>. That blocks the implicit loop.
13601          The above is almost equivalent to writing:
13602        </para>
13603<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>
13604</programlisting>
13605        <para>
13606          in which, of course, there is no concurrency at all.
13607        </para>
13608        <para>
13609          Passing the argument pack through a function-call boundary (<code><phrase
13610          role="identifier">wait_all_members_get</phrase><phrase role="special">()</phrase></code>)
13611          forces the runtime to make <emphasis>two</emphasis> passes: one in <code><phrase
13612          role="identifier">wait_all_members</phrase><phrase role="special">()</phrase></code>
13613          to collect the <code><phrase role="identifier">future</phrase><phrase role="special">&lt;&gt;</phrase></code>s
13614          from all the <code><phrase role="identifier">async</phrase><phrase role="special">()</phrase></code>
13615          calls, the second in <code><phrase role="identifier">wait_all_members_get</phrase><phrase
13616          role="special">()</phrase></code> to fetch each of the results.
13617        </para>
13618        <para>
13619          As noted in comments, within the <code><phrase role="identifier">wait_all_members_get</phrase><phrase
13620          role="special">()</phrase></code> parameter pack expansion pass, the blocking
13621          behavior of <code><phrase role="identifier">get</phrase><phrase role="special">()</phrase></code>
13622          becomes irrelevant. Along the way, we will hit the <code><phrase role="identifier">get</phrase><phrase
13623          role="special">()</phrase></code> for the slowest task function; after
13624          that every subsequent <code><phrase role="identifier">get</phrase><phrase
13625          role="special">()</phrase></code> will complete in trivial time.
13626        </para>
13627        <para>
13628          By the way, we could also use this same API to fill a vector or other collection:
13629        </para>
13630        <para>
13631<programlisting><phrase role="comment">// If we don't care about obtaining results as soon as they arrive, and we</phrase>
13632<phrase role="comment">// prefer a result vector in passed argument order rather than completion</phrase>
13633<phrase role="comment">// order, wait_all_members() is another possible implementation of</phrase>
13634<phrase role="comment">// wait_all_until_error().</phrase>
13635<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>
13636        <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>
13637        <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>
13638        <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>
13639<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>
13640<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>
13641    <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>
13642<phrase role="special">}</phrase>
13643<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>
13644</programlisting>
13645        </para>
13646      </section>
13647    </section>
13648  </section>
13649  <section id="fiber.integration">
13650    <title><anchor id="integration"/><link linkend="fiber.integration">Sharing a
13651    Thread with Another Main Loop</link></title>
13652    <section id="fiber.integration.overview">
13653      <title><link linkend="fiber.integration.overview">Overview</link></title>
13654      <para>
13655        As always with cooperative concurrency, it is important not to let any one
13656        fiber monopolize the processor too long: that could <quote>starve</quote>
13657        other ready fibers. This section discusses a couple of solutions.
13658      </para>
13659    </section>
13660    <section id="fiber.integration.event_driven_program">
13661      <title><link linkend="fiber.integration.event_driven_program">Event-Driven
13662      Program</link></title>
13663      <para>
13664        Consider a classic event-driven program, organized around a main loop that
13665        fetches and dispatches incoming I/O events. You are introducing <emphasis
13666        role="bold">Boost.Fiber</emphasis> because certain asynchronous I/O sequences
13667        are logically sequential, and for those you want to write and maintain code
13668        that looks and acts sequential.
13669      </para>
13670      <para>
13671        You are launching fibers on the application&#8217;s main thread because certain
13672        of their actions will affect its user interface, and the application&#8217;s UI
13673        framework permits UI operations only on the main thread. Or perhaps those
13674        fibers need access to main-thread data, and it would be too expensive in
13675        runtime (or development time) to robustly defend every such data item with
13676        thread synchronization primitives.
13677      </para>
13678      <para>
13679        You must ensure that the application&#8217;s main loop <emphasis>itself</emphasis>
13680        doesn&#8217;t monopolize the processor: that the fibers it launches will get the
13681        CPU cycles they need.
13682      </para>
13683      <para>
13684        The solution is the same as for any fiber that might claim the CPU for an
13685        extended time: introduce calls to <link linkend="this_fiber_yield"><code>this_fiber::yield()</code></link>. The
13686        most straightforward approach is to call <code><phrase role="identifier">yield</phrase><phrase
13687        role="special">()</phrase></code> on every iteration of your existing main
13688        loop. In effect, this unifies the application&#8217;s main loop with <emphasis role="bold">Boost.Fiber</emphasis>&#8217;s
13689        internal main loop. <code><phrase role="identifier">yield</phrase><phrase
13690        role="special">()</phrase></code> allows the fiber manager to run any fibers
13691        that have become ready since the previous iteration of the application&#8217;s main
13692        loop. When these fibers have had a turn, control passes to the thread&#8217;s main
13693        fiber, which returns from <code><phrase role="identifier">yield</phrase><phrase
13694        role="special">()</phrase></code> and resumes the application&#8217;s main loop.
13695      </para>
13696    </section>
13697    <section id="fiber.integration.embedded_main_loop">
13698      <title><anchor id="embedded_main_loop"/><link linkend="fiber.integration.embedded_main_loop">Embedded
13699      Main Loop</link></title>
13700      <para>
13701        More challenging is when the application&#8217;s main loop is embedded in some other
13702        library or framework. Such an application will typically, after performing
13703        all necessary setup, pass control to some form of <code><phrase role="identifier">run</phrase><phrase
13704        role="special">()</phrase></code> function from which control does not return
13705        until application shutdown.
13706      </para>
13707      <para>
13708        A <ulink url="http://www.boost.org/doc/libs/release/libs/asio/index.html">Boost.Asio</ulink>
13709        program might call <ulink url="http://www.boost.org/doc/libs/release/doc/html/boost_asio/reference/io_service/run.html"><code><phrase
13710        role="identifier">io_service</phrase><phrase role="special">::</phrase><phrase
13711        role="identifier">run</phrase><phrase role="special">()</phrase></code></ulink>
13712        in this way.
13713      </para>
13714      <para>
13715        In general, the trick is to arrange to pass control to <link linkend="this_fiber_yield"><code>this_fiber::yield()</code></link> frequently.
13716        You could use an <ulink url="http://www.boost.org/doc/libs/release/doc/html/boost_asio/reference/high_resolution_timer.html">Asio
13717        timer</ulink> for that purpose. You could instantiate the timer, arranging
13718        to call a handler function when the timer expires. The handler function could
13719        call <code><phrase role="identifier">yield</phrase><phrase role="special">()</phrase></code>,
13720        then reset the timer and arrange to wake up again on its next expiration.
13721      </para>
13722      <para>
13723        Since, in this thought experiment, we always pass control to the fiber manager
13724        via <code><phrase role="identifier">yield</phrase><phrase role="special">()</phrase></code>,
13725        the calling fiber is never blocked. Therefore there is always at least one
13726        ready fiber. Therefore the fiber manager never calls <link linkend="algorithm_suspend_until"><code>algorithm::suspend_until()</code></link>.
13727      </para>
13728      <para>
13729        Using <ulink url="http://www.boost.org/doc/libs/release/doc/html/boost_asio/reference/io_service/post.html"><code><phrase
13730        role="identifier">io_service</phrase><phrase role="special">::</phrase><phrase
13731        role="identifier">post</phrase><phrase role="special">()</phrase></code></ulink>
13732        instead of setting a timer for some nonzero interval would be unfriendly
13733        to other threads. When all I/O is pending and all fibers are blocked, the
13734        io_service and the fiber manager would simply spin the CPU, passing control
13735        back and forth to each other. Using a timer allows tuning the responsiveness
13736        of this thread relative to others.
13737      </para>
13738    </section>
13739    <section id="fiber.integration.deeper_dive_into___boost_asio__">
13740      <title><link linkend="fiber.integration.deeper_dive_into___boost_asio__">Deeper
13741      Dive into <ulink url="http://www.boost.org/doc/libs/release/libs/asio/index.html">Boost.Asio</ulink></link></title>
13742      <para>
13743        By now the alert reader is thinking: but surely, with Asio in particular,
13744        we ought to be able to do much better than periodic polling pings!
13745      </para>
13746      <para>
13747        This turns out to be surprisingly tricky. We present a possible approach
13748        in <ulink url="../../examples/asio/round_robin.hpp"><code><phrase role="identifier">examples</phrase><phrase
13749        role="special">/</phrase><phrase role="identifier">asio</phrase><phrase role="special">/</phrase><phrase
13750        role="identifier">round_robin</phrase><phrase role="special">.</phrase><phrase
13751        role="identifier">hpp</phrase></code></ulink>.
13752      </para>
13753      <para>
13754        One consequence of using <ulink url="http://www.boost.org/doc/libs/release/libs/asio/index.html">Boost.Asio</ulink>
13755        is that you must always let Asio suspend the running thread. Since Asio is
13756        aware of pending I/O requests, it can arrange to suspend the thread in such
13757        a way that the OS will wake it on I/O completion. No one else has sufficient
13758        knowledge.
13759      </para>
13760      <para>
13761        So the fiber scheduler must depend on Asio for suspension and resumption.
13762        It requires Asio handler calls to wake it.
13763      </para>
13764      <para>
13765        One dismaying implication is that we cannot support multiple threads calling
13766        <ulink url="http://www.boost.org/doc/libs/release/doc/html/boost_asio/reference/io_service/run.html"><code><phrase
13767        role="identifier">io_service</phrase><phrase role="special">::</phrase><phrase
13768        role="identifier">run</phrase><phrase role="special">()</phrase></code></ulink>
13769        on the same <code><phrase role="identifier">io_service</phrase></code> instance.
13770        The reason is that Asio provides no way to constrain a particular handler
13771        to be called only on a specified thread. A fiber scheduler instance is locked
13772        to a particular thread: that instance cannot manage any other thread&#8217;s fibers.
13773        Yet if we allow multiple threads to call <code><phrase role="identifier">io_service</phrase><phrase
13774        role="special">::</phrase><phrase role="identifier">run</phrase><phrase role="special">()</phrase></code>
13775        on the same <code><phrase role="identifier">io_service</phrase></code> instance,
13776        a fiber scheduler which needs to sleep can have no guarantee that it will
13777        reawaken in a timely manner. It can set an Asio timer, as described above
13778        &mdash; but that timer&#8217;s handler may well execute on a different thread!
13779      </para>
13780      <para>
13781        Another implication is that since an Asio-aware fiber scheduler (not to mention
13782        <link linkend="callbacks_asio"><code><phrase role="identifier">boost</phrase><phrase
13783        role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase
13784        role="special">::</phrase><phrase role="identifier">asio</phrase><phrase
13785        role="special">::</phrase><phrase role="identifier">yield</phrase></code></link>)
13786        depends on handler calls from the <code><phrase role="identifier">io_service</phrase></code>,
13787        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
13788        role="identifier">io_service</phrase><phrase role="special">::</phrase><phrase
13789        role="identifier">stop</phrase><phrase role="special">()</phrase></code></ulink>
13790        is not called until every fiber has terminated.
13791      </para>
13792      <para>
13793        It is easier to reason about the behavior of the presented <code><phrase
13794        role="identifier">asio</phrase><phrase role="special">::</phrase><phrase
13795        role="identifier">round_robin</phrase></code> scheduler if we require that
13796        after initial setup, the thread&#8217;s main fiber is the fiber that calls <code><phrase
13797        role="identifier">io_service</phrase><phrase role="special">::</phrase><phrase
13798        role="identifier">run</phrase><phrase role="special">()</phrase></code>,
13799        so let&#8217;s impose that requirement.
13800      </para>
13801      <para>
13802        Naturally, the first thing we must do on each thread using a custom fiber
13803        scheduler is call <link linkend="use_scheduling_algorithm"><code>use_scheduling_algorithm()</code></link>. However,
13804        since <code><phrase role="identifier">asio</phrase><phrase role="special">::</phrase><phrase
13805        role="identifier">round_robin</phrase></code> requires an <code><phrase role="identifier">io_service</phrase></code>
13806        instance, we must first declare that.
13807      </para>
13808      <para>
13809<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>
13810<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>
13811</programlisting>
13812      </para>
13813      <para>
13814        <code><phrase role="identifier">use_scheduling_algorithm</phrase><phrase
13815        role="special">()</phrase></code> instantiates <code><phrase role="identifier">asio</phrase><phrase
13816        role="special">::</phrase><phrase role="identifier">round_robin</phrase></code>,
13817        which naturally calls its constructor:
13818      </para>
13819      <para>
13820<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>
13821    <phrase role="identifier">io_svc_</phrase><phrase role="special">(</phrase> <phrase role="identifier">io_svc</phrase><phrase role="special">),</phrase>
13822    <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>
13823    <phrase role="comment">// We use add_service() very deliberately. This will throw</phrase>
13824    <phrase role="comment">// service_already_exists if you pass the same io_service instance to</phrase>
13825    <phrase role="comment">// more than one round_robin instance.</phrase>
13826    <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>
13827    <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>
13828</programlisting>
13829      </para>
13830      <para>
13831        <code><phrase role="identifier">asio</phrase><phrase role="special">::</phrase><phrase
13832        role="identifier">round_robin</phrase></code> binds the passed <code><phrase
13833        role="identifier">io_service</phrase></code> pointer and initializes a <ulink
13834        url="http://www.boost.org/doc/libs/release/doc/html/boost_asio/reference/steady_timer.html"><code><phrase
13835        role="identifier">boost</phrase><phrase role="special">::</phrase><phrase
13836        role="identifier">asio</phrase><phrase role="special">::</phrase><phrase
13837        role="identifier">steady_timer</phrase></code></ulink>:
13838      </para>
13839      <para>
13840<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>
13841<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>
13842</programlisting>
13843      </para>
13844      <para>
13845        Then it calls <ulink url="http://www.boost.org/doc/libs/release/doc/html/boost_asio/reference/add_service.html"><code><phrase
13846        role="identifier">boost</phrase><phrase role="special">::</phrase><phrase
13847        role="identifier">asio</phrase><phrase role="special">::</phrase><phrase
13848        role="identifier">add_service</phrase><phrase role="special">()</phrase></code></ulink>
13849        with a nested <code><phrase role="identifier">service</phrase></code> struct:
13850      </para>
13851      <para>
13852<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>
13853    <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>
13854
13855    <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>
13856
13857    <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>
13858        <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>
13859        <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>
13860    <phrase role="special">}</phrase>
13861
13862    <phrase role="keyword">virtual</phrase> <phrase role="special">~</phrase><phrase role="identifier">service</phrase><phrase role="special">()</phrase> <phrase role="special">{}</phrase>
13863
13864    <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>
13865    <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>
13866
13867    <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>
13868        <phrase role="identifier">work_</phrase><phrase role="special">.</phrase><phrase role="identifier">reset</phrase><phrase role="special">();</phrase>
13869    <phrase role="special">}</phrase>
13870<phrase role="special">};</phrase>
13871</programlisting>
13872      </para>
13873      <para>
13874        ... [asio_rr_service_bottom]
13875      </para>
13876      <para>
13877        The <code><phrase role="identifier">service</phrase></code> struct has a
13878        couple of roles.
13879      </para>
13880      <para>
13881        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
13882        role="identifier">boost</phrase><phrase role="special">::</phrase><phrase
13883        role="identifier">asio</phrase><phrase role="special">::</phrase><phrase
13884        role="identifier">io_service</phrase><phrase role="special">::</phrase><phrase
13885        role="identifier">work</phrase></code></ulink>&gt;</literal>. We want the
13886        <code><phrase role="identifier">io_service</phrase></code> instance to continue
13887        its main loop even when there is no pending Asio I/O.
13888      </para>
13889      <para>
13890        But when <ulink url="http://www.boost.org/doc/libs/release/doc/html/boost_asio/reference/io_service__service/shutdown_service.html"><code><phrase
13891        role="identifier">boost</phrase><phrase role="special">::</phrase><phrase
13892        role="identifier">asio</phrase><phrase role="special">::</phrase><phrase
13893        role="identifier">io_service</phrase><phrase role="special">::</phrase><phrase
13894        role="identifier">service</phrase><phrase role="special">::</phrase><phrase
13895        role="identifier">shutdown_service</phrase><phrase role="special">()</phrase></code></ulink>
13896        is called, we discard the <code><phrase role="identifier">io_service</phrase><phrase
13897        role="special">::</phrase><phrase role="identifier">work</phrase></code>
13898        instance so the <code><phrase role="identifier">io_service</phrase></code>
13899        can shut down properly.
13900      </para>
13901      <para>
13902        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
13903        role="identifier">post</phrase><phrase role="special">()</phrase></code></ulink>
13904        a lambda (not yet shown). Let&#8217;s walk further through the example program before
13905        coming back to explain that lambda.
13906      </para>
13907      <para>
13908        The <code><phrase role="identifier">service</phrase></code> constructor returns
13909        to <code><phrase role="identifier">asio</phrase><phrase role="special">::</phrase><phrase
13910        role="identifier">round_robin</phrase></code>&#8217;s constructor, which returns
13911        to <code><phrase role="identifier">use_scheduling_algorithm</phrase><phrase
13912        role="special">()</phrase></code>, which returns to the application code.
13913      </para>
13914      <para>
13915        Once it has called <code><phrase role="identifier">use_scheduling_algorithm</phrase><phrase
13916        role="special">()</phrase></code>, the application may now launch some number
13917        of fibers:
13918      </para>
13919      <para>
13920<programlisting><phrase role="comment">// server</phrase>
13921<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>
13922<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>
13923<phrase role="comment">// client</phrase>
13924<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>
13925<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>
13926<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>
13927<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>
13928    <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>
13929            <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>
13930<phrase role="special">}</phrase>
13931</programlisting>
13932      </para>
13933      <para>
13934        Since we don&#8217;t specify a <link linkend="class_launch"><code>launch</code></link>, these fibers are ready to run,
13935        but have not yet been entered.
13936      </para>
13937      <para>
13938        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
13939        role="identifier">io_service</phrase><phrase role="special">::</phrase><phrase
13940        role="identifier">run</phrase><phrase role="special">()</phrase></code></ulink>:
13941      </para>
13942      <para>
13943<programlisting><phrase role="identifier">io_svc</phrase><phrase role="special">-&gt;</phrase><phrase role="identifier">run</phrase><phrase role="special">();</phrase>
13944</programlisting>
13945      </para>
13946      <para>
13947        Now what?
13948      </para>
13949      <para>
13950        Because this <code><phrase role="identifier">io_service</phrase></code> instance
13951        owns an <code><phrase role="identifier">io_service</phrase><phrase role="special">::</phrase><phrase
13952        role="identifier">work</phrase></code> instance, <code><phrase role="identifier">run</phrase><phrase
13953        role="special">()</phrase></code> does not immediately return. But &mdash; none of
13954        the fibers that will perform actual work has even been entered yet!
13955      </para>
13956      <para>
13957        Without that initial <code><phrase role="identifier">post</phrase><phrase
13958        role="special">()</phrase></code> call in <code><phrase role="identifier">service</phrase></code>&#8217;s
13959        constructor, <emphasis>nothing</emphasis> would happen. The application would
13960        hang right here.
13961      </para>
13962      <para>
13963        So, what should the <code><phrase role="identifier">post</phrase><phrase
13964        role="special">()</phrase></code> handler execute? Simply <link linkend="this_fiber_yield"><code>this_fiber::yield()</code></link>?
13965      </para>
13966      <para>
13967        That would be a promising start. But we have no guarantee that any of the
13968        other fibers will initiate any Asio operations to keep the ball rolling.
13969        For all we know, every other fiber could reach a similar <code><phrase role="identifier">boost</phrase><phrase
13970        role="special">::</phrase><phrase role="identifier">this_fiber</phrase><phrase
13971        role="special">::</phrase><phrase role="identifier">yield</phrase><phrase
13972        role="special">()</phrase></code> call first. Control would return to the
13973        <code><phrase role="identifier">post</phrase><phrase role="special">()</phrase></code>
13974        handler, which would return to Asio, and... the application would hang.
13975      </para>
13976      <para>
13977        The <code><phrase role="identifier">post</phrase><phrase role="special">()</phrase></code>
13978        handler could <code><phrase role="identifier">post</phrase><phrase role="special">()</phrase></code>
13979        itself again. But as discussed in <link linkend="embedded_main_loop">the
13980        previous section</link>, once there are actual I/O operations in flight &mdash; once
13981        we reach a state in which no fiber is ready &mdash;
13982that would cause the thread to
13983        spin.
13984      </para>
13985      <para>
13986        We could, of course, set an Asio timer &mdash; again as <link linkend="embedded_main_loop">previously
13987        discussed</link>. But in this <quote>deeper dive,</quote> we&#8217;re trying to
13988        do a little better.
13989      </para>
13990      <para>
13991        The key to doing better is that since we&#8217;re in a fiber, we can run an actual
13992        loop &mdash; not just a chain of callbacks. We can wait for <quote>something to happen</quote>
13993        by calling <ulink url="http://www.boost.org/doc/libs/release/doc/html/boost_asio/reference/io_service/run_one.html"><code><phrase
13994        role="identifier">io_service</phrase><phrase role="special">::</phrase><phrase
13995        role="identifier">run_one</phrase><phrase role="special">()</phrase></code></ulink>
13996        &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
13997        role="identifier">io_service</phrase><phrase role="special">::</phrase><phrase
13998        role="identifier">poll</phrase><phrase role="special">()</phrase></code></ulink>.
13999      </para>
14000      <para>
14001        Here&#8217;s the body of the lambda passed to the <code><phrase role="identifier">post</phrase><phrase
14002        role="special">()</phrase></code> call.
14003      </para>
14004      <para>
14005<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>
14006     <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>
14007         <phrase role="comment">// run all pending handlers in round_robin</phrase>
14008         <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>
14009         <phrase role="comment">// block this fiber till all pending (ready) fibers are processed</phrase>
14010         <phrase role="comment">// == round_robin::suspend_until() has been called</phrase>
14011         <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>
14012         <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>
14013     <phrase role="special">}</phrase> <phrase role="keyword">else</phrase> <phrase role="special">{</phrase>
14014         <phrase role="comment">// run one handler inside io_service</phrase>
14015         <phrase role="comment">// if no handler available, block this thread</phrase>
14016         <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>
14017             <phrase role="keyword">break</phrase><phrase role="special">;</phrase>
14018         <phrase role="special">}</phrase>
14019     <phrase role="special">}</phrase>
14020<phrase role="special">}</phrase>
14021</programlisting>
14022      </para>
14023      <para>
14024        We want this loop to exit once the <code><phrase role="identifier">io_service</phrase></code>
14025        instance has been <ulink url="http://www.boost.org/doc/libs/release/doc/html/boost_asio/reference/io_service/stopped.html"><code><phrase
14026        role="identifier">stopped</phrase><phrase role="special">()</phrase></code></ulink>.
14027      </para>
14028      <para>
14029        As long as there are ready fibers, we interleave running ready Asio handlers
14030        with running ready fibers.
14031      </para>
14032      <para>
14033        If there are no ready fibers, we wait by calling <code><phrase role="identifier">run_one</phrase><phrase
14034        role="special">()</phrase></code>. Once any Asio handler has been called
14035        &mdash; no matter which &mdash; <code><phrase role="identifier">run_one</phrase><phrase role="special">()</phrase></code>
14036        returns. That handler may have transitioned some fiber to ready state, so
14037        we loop back to check again.
14038      </para>
14039      <para>
14040        (We won&#8217;t describe <code><phrase role="identifier">awakened</phrase><phrase
14041        role="special">()</phrase></code>, <code><phrase role="identifier">pick_next</phrase><phrase
14042        role="special">()</phrase></code> or <code><phrase role="identifier">has_ready_fibers</phrase><phrase
14043        role="special">()</phrase></code>, as these are just like <link linkend="round_robin_awakened"><code>round_robin::awakened()</code></link>,
14044        <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>.)
14045      </para>
14046      <para>
14047        That leaves <code><phrase role="identifier">suspend_until</phrase><phrase
14048        role="special">()</phrase></code> and <code><phrase role="identifier">notify</phrase><phrase
14049        role="special">()</phrase></code>.
14050      </para>
14051      <para>
14052        Doubtless you have been asking yourself: why are we calling <code><phrase
14053        role="identifier">io_service</phrase><phrase role="special">::</phrase><phrase
14054        role="identifier">run_one</phrase><phrase role="special">()</phrase></code>
14055        in the lambda loop? Why not call it in <code><phrase role="identifier">suspend_until</phrase><phrase
14056        role="special">()</phrase></code>, whose very API was designed for just such
14057        a purpose?
14058      </para>
14059      <para>
14060        Under normal circumstances, when the fiber manager finds no ready fibers,
14061        it calls <link linkend="algorithm_suspend_until"><code>algorithm::suspend_until()</code></link>. Why test <code><phrase
14062        role="identifier">has_ready_fibers</phrase><phrase role="special">()</phrase></code>
14063        in the lambda loop? Why not leverage the normal mechanism?
14064      </para>
14065      <para>
14066        The answer is: it matters who&#8217;s asking.
14067      </para>
14068      <para>
14069        Consider the lambda loop shown above. The only <emphasis role="bold">Boost.Fiber</emphasis>
14070        APIs it engages are <code><phrase role="identifier">has_ready_fibers</phrase><phrase
14071        role="special">()</phrase></code> and <link linkend="this_fiber_yield"><code>this_fiber::yield()</code></link>.
14072        <code><phrase role="identifier">yield</phrase><phrase role="special">()</phrase></code>
14073        does not <emphasis>block</emphasis> the calling fiber: the calling fiber
14074        does not become unready. It is immediately passed back to <link linkend="algorithm_awakened"><code>algorithm::awakened()</code></link>,
14075        to be resumed in its turn when all other ready fibers have had a chance to
14076        run. In other words: during a <code><phrase role="identifier">yield</phrase><phrase
14077        role="special">()</phrase></code> call, <emphasis>there is always at least
14078        one ready fiber.</emphasis>
14079      </para>
14080      <para>
14081        As long as this lambda loop is still running, the fiber manager does not
14082        call <code><phrase role="identifier">suspend_until</phrase><phrase role="special">()</phrase></code>
14083        because it always has a fiber ready to run.
14084      </para>
14085      <para>
14086        However, the lambda loop <emphasis>itself</emphasis> can detect the case
14087        when no <emphasis>other</emphasis> fibers are ready to run: the running fiber
14088        is not <emphasis>ready</emphasis> but <emphasis>running.</emphasis>
14089      </para>
14090      <para>
14091        That said, <code><phrase role="identifier">suspend_until</phrase><phrase
14092        role="special">()</phrase></code> and <code><phrase role="identifier">notify</phrase><phrase
14093        role="special">()</phrase></code> are in fact called during orderly shutdown
14094        processing, so let&#8217;s try a plausible implementation.
14095      </para>
14096      <para>
14097<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>
14098    <phrase role="comment">// Set a timer so at least one handler will eventually fire, causing</phrase>
14099    <phrase role="comment">// run_one() to eventually return.</phrase>
14100    <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>
14101        <phrase role="comment">// Each expires_at(time_point) call cancels any previous pending</phrase>
14102        <phrase role="comment">// call. We could inadvertently spin like this:</phrase>
14103        <phrase role="comment">// dispatcher calls suspend_until() with earliest wake time</phrase>
14104        <phrase role="comment">// suspend_until() sets suspend_timer_</phrase>
14105        <phrase role="comment">// lambda loop calls run_one()</phrase>
14106        <phrase role="comment">// some other asio handler runs before timer expires</phrase>
14107        <phrase role="comment">// run_one() returns to lambda loop</phrase>
14108        <phrase role="comment">// lambda loop yields to dispatcher</phrase>
14109        <phrase role="comment">// dispatcher finds no ready fibers</phrase>
14110        <phrase role="comment">// dispatcher calls suspend_until() with SAME wake time</phrase>
14111        <phrase role="comment">// suspend_until() sets suspend_timer_ to same time, canceling</phrase>
14112        <phrase role="comment">// previous async_wait()</phrase>
14113        <phrase role="comment">// lambda loop calls run_one()</phrase>
14114        <phrase role="comment">// asio calls suspend_timer_ handler with operation_aborted</phrase>
14115        <phrase role="comment">// run_one() returns to lambda loop... etc. etc.</phrase>
14116        <phrase role="comment">// So only actually set the timer when we're passed a DIFFERENT</phrase>
14117        <phrase role="comment">// abs_time value.</phrase>
14118        <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>
14119        <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>
14120                                    <phrase role="identifier">this_fiber</phrase><phrase role="special">::</phrase><phrase role="identifier">yield</phrase><phrase role="special">();</phrase>
14121                                  <phrase role="special">});</phrase>
14122    <phrase role="special">}</phrase>
14123    <phrase role="identifier">cnd_</phrase><phrase role="special">.</phrase><phrase role="identifier">notify_one</phrase><phrase role="special">();</phrase>
14124<phrase role="special">}</phrase>
14125</programlisting>
14126      </para>
14127      <para>
14128        As you might expect, <code><phrase role="identifier">suspend_until</phrase><phrase
14129        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
14130        role="identifier">asio</phrase><phrase role="special">::</phrase><phrase
14131        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
14132        role="identifier">expires_at</phrase><phrase role="special">()</phrase></code></ulink>
14133        the passed <ulink url="http://en.cppreference.com/w/cpp/chrono/steady_clock"><code><phrase
14134        role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase
14135        role="special">::</phrase><phrase role="identifier">steady_clock</phrase><phrase
14136        role="special">::</phrase><phrase role="identifier">time_point</phrase></code></ulink>.
14137        Usually.
14138      </para>
14139      <para>
14140        As indicated in comments, we avoid setting <code><phrase role="identifier">suspend_timer_</phrase></code>
14141        multiple times to the <emphasis>same</emphasis> <code><phrase role="identifier">time_point</phrase></code>
14142        value since every <code><phrase role="identifier">expires_at</phrase><phrase
14143        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
14144        role="identifier">async_wait</phrase><phrase role="special">()</phrase></code></ulink>
14145        call. There is a chance that we could spin. Reaching <code><phrase role="identifier">suspend_until</phrase><phrase
14146        role="special">()</phrase></code> means the fiber manager intends to yield
14147        the processor to Asio. Cancelling the previous <code><phrase role="identifier">async_wait</phrase><phrase
14148        role="special">()</phrase></code> call would fire its handler, causing <code><phrase
14149        role="identifier">run_one</phrase><phrase role="special">()</phrase></code>
14150        to return, potentially causing the fiber manager to call <code><phrase role="identifier">suspend_until</phrase><phrase
14151        role="special">()</phrase></code> again with the same <code><phrase role="identifier">time_point</phrase></code>
14152        value...
14153      </para>
14154      <para>
14155        Given that we suspend the thread by calling <code><phrase role="identifier">io_service</phrase><phrase
14156        role="special">::</phrase><phrase role="identifier">run_one</phrase><phrase
14157        role="special">()</phrase></code>, what&#8217;s important is that our <code><phrase
14158        role="identifier">async_wait</phrase><phrase role="special">()</phrase></code>
14159        call will cause a handler to run, which will cause <code><phrase role="identifier">run_one</phrase><phrase
14160        role="special">()</phrase></code> to return. It&#8217;s not so important specifically
14161        what that handler does.
14162      </para>
14163      <para>
14164<programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">notify</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase> <phrase role="special">{</phrase>
14165    <phrase role="comment">// Something has happened that should wake one or more fibers BEFORE</phrase>
14166    <phrase role="comment">// suspend_timer_ expires. Reset the timer to cause it to fire</phrase>
14167    <phrase role="comment">// immediately, causing the run_one() call to return. In theory we</phrase>
14168    <phrase role="comment">// could use cancel() because we don't care whether suspend_timer_'s</phrase>
14169    <phrase role="comment">// handler is called with operation_aborted or success. However --</phrase>
14170    <phrase role="comment">// cancel() doesn't change the expiration time, and we use</phrase>
14171    <phrase role="comment">// suspend_timer_'s expiration time to decide whether it's already</phrase>
14172    <phrase role="comment">// set. If suspend_until() set some specific wake time, then notify()</phrase>
14173    <phrase role="comment">// canceled it, then suspend_until() was called again with the same</phrase>
14174    <phrase role="comment">// wake time, it would match suspend_timer_'s expiration time and we'd</phrase>
14175    <phrase role="comment">// refrain from setting the timer. So instead of simply calling</phrase>
14176    <phrase role="comment">// cancel(), reset the timer, which cancels the pending sleep AND sets</phrase>
14177    <phrase role="comment">// a new expiration time. This will cause us to spin the loop twice --</phrase>
14178    <phrase role="comment">// once for the operation_aborted handler, once for timer expiration</phrase>
14179    <phrase role="comment">// -- but that shouldn't be a big problem.</phrase>
14180    <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>
14181                                <phrase role="identifier">this_fiber</phrase><phrase role="special">::</phrase><phrase role="identifier">yield</phrase><phrase role="special">();</phrase>
14182                              <phrase role="special">});</phrase>
14183    <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>
14184<phrase role="special">}</phrase>
14185</programlisting>
14186      </para>
14187      <para>
14188        Since an <code><phrase role="identifier">expires_at</phrase><phrase role="special">()</phrase></code>
14189        call cancels any previous <code><phrase role="identifier">async_wait</phrase><phrase
14190        role="special">()</phrase></code> call, we can make <code><phrase role="identifier">notify</phrase><phrase
14191        role="special">()</phrase></code> simply call <code><phrase role="identifier">steady_timer</phrase><phrase
14192        role="special">::</phrase><phrase role="identifier">expires_at</phrase><phrase
14193        role="special">()</phrase></code>. That should cause the <code><phrase role="identifier">io_service</phrase></code>
14194        to call the <code><phrase role="identifier">async_wait</phrase><phrase role="special">()</phrase></code>
14195        handler with <code><phrase role="identifier">operation_aborted</phrase></code>.
14196      </para>
14197      <para>
14198        The comments in <code><phrase role="identifier">notify</phrase><phrase role="special">()</phrase></code>
14199        explain why we call <code><phrase role="identifier">expires_at</phrase><phrase
14200        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
14201        role="identifier">cancel</phrase><phrase role="special">()</phrase></code></ulink>.
14202      </para>
14203      <para>
14204        This <code><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase
14205        role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase
14206        role="identifier">asio</phrase><phrase role="special">::</phrase><phrase
14207        role="identifier">round_robin</phrase></code> implementation is used in
14208        <ulink url="../../examples/asio/autoecho.cpp"><code><phrase role="identifier">examples</phrase><phrase
14209        role="special">/</phrase><phrase role="identifier">asio</phrase><phrase role="special">/</phrase><phrase
14210        role="identifier">autoecho</phrase><phrase role="special">.</phrase><phrase
14211        role="identifier">cpp</phrase></code></ulink>.
14212      </para>
14213      <para>
14214        It seems possible that you could put together a more elegant Fiber / Asio
14215        integration. But as noted at the outset: it&#8217;s tricky.
14216      </para>
14217    </section>
14218  </section>
14219  <section id="fiber.speculation">
14220    <title><anchor id="speculation"/><link linkend="fiber.speculation">Specualtive
14221    execution</link></title>
14222    <bridgehead renderas="sect3" id="fiber.speculation.h0">
14223      <phrase id="fiber.speculation.hardware_transactional_memory"/><link linkend="fiber.speculation.hardware_transactional_memory">Hardware
14224      transactional memory</link>
14225    </bridgehead>
14226    <para>
14227      With help of hardware transactional memory multiple logical processors execute
14228      a critical region speculatively, e.g. without explicit synchronization.<sbr/>
14229      If the transactional execution completes successfully, then all memory operations
14230      performed within the transactional region are commited without any inter-thread
14231      serialization.<sbr/> When the optimistic execution fails, the processor aborts
14232      the transaction and discards all performed modifications.<sbr/> In non-transactional
14233      code a single lock serializes the access to a critical region. With a transactional
14234      memory, multiple logical processor start a transaction and update the memory
14235      (the data) inside the ciritical region. Unless some logical processors try
14236      to update the same data, the transactions would always succeed.
14237    </para>
14238    <bridgehead renderas="sect3" id="fiber.speculation.h1">
14239      <phrase id="fiber.speculation.intel_transactional_synchronisation_extensions__tsx_"/><link
14240      linkend="fiber.speculation.intel_transactional_synchronisation_extensions__tsx_">Intel
14241      Transactional Synchronisation Extensions (TSX)</link>
14242    </bridgehead>
14243    <para>
14244      TSX is Intel's implementation of hardware transactional memory in modern Intel
14245      processors<footnote id="fiber.speculation.f0">
14246      <para>
14247        intel.com: <ulink url="https://software.intel.com/en-us/node/695149">Intel
14248        Transactional Synchronization Extensions</ulink>
14249      </para>
14250      </footnote>.<sbr/> In TSX the hardware keeps track of which cachelines have
14251      been read from and which have been written to in a transaction. The cache-line
14252      size (64-byte) and the n-way set associative cache determine the maximum size
14253      of memory in a transaction. For instance if a transaction modifies 9 cache-lines
14254      at a processor with a 8-way set associative cache, the transaction will always
14255      be aborted.
14256    </para>
14257    <note>
14258      <para>
14259        TXS is enabled if property <code><phrase role="identifier">htm</phrase><phrase
14260        role="special">=</phrase><phrase role="identifier">tsx</phrase></code> is
14261        specified at b2 command-line and <code><phrase role="identifier">BOOST_USE_TSX</phrase></code>
14262        is applied to the compiler.
14263      </para>
14264    </note>
14265    <note>
14266      <para>
14267        A TSX-transaction will be aborted if the floating point state is modified
14268        inside a critical region. As a consequence floating point operations, e.g.
14269        store/load of floating point related registers during a fiber (context) switch
14270        are disabled.
14271      </para>
14272    </note>
14273    <important>
14274      <para>
14275        TSX can not be used together with MSVC at this time!
14276      </para>
14277    </important>
14278    <para>
14279      Boost.Fiber uses TSX-enabled spinlocks to protect critical regions (see section
14280      <link linkend="tuning">Tuning</link>).
14281    </para>
14282  </section>
14283  <section id="fiber.numa">
14284    <title><anchor id="numa"/><link linkend="fiber.numa">NUMA</link></title>
14285    <para>
14286      Modern micro-processors contain integrated memory controllers that are connected
14287      via channels to the memory. Accessing the memory can be organized in two kinds:<sbr/>
14288      Uniform Memory Access (UMA) and Non-Uniform Memory Access (NUMA).
14289    </para>
14290    <para>
14291      In contrast to UMA, that provides a centralized pool of memory (and thus does
14292      not scale after a certain number of processors), a NUMA architecture divides
14293      the memory into local and remote memory relative to the micro-processor.<sbr/>
14294      Local memory is directly attached to the processor's integrated memory controller.
14295      Memory connected to the memory controller of another micro-processor (multi-socket
14296      systems) is considered as remote memory. If a memory controller access remote
14297      memory it has to traverse the interconnect<footnote id="fiber.numa.f0">
14298      <para>
14299        On x86 the interconnection is implemented by Intel's Quick Path Interconnect
14300        (QPI) and AMD's HyperTransport.
14301      </para>
14302      </footnote> and connect to the remote memory controller.<sbr/> Thus accessing
14303      remote memory adds additional latency overhead to local memory access. Because
14304      of the different memory locations, a NUMA-system experiences <emphasis>non-uniform</emphasis>
14305      memory access time.<sbr/> As a consequence the best performance is achieved
14306      by keeping the memory access local.
14307    </para>
14308    <para>
14309      <inlinemediaobject><imageobject><imagedata align="center" fileref="../../../../libs/fiber/doc/NUMA.png"></imagedata></imageobject>
14310      <textobject>
14311        <phrase>NUMA</phrase>
14312      </textobject>
14313      </inlinemediaobject>
14314    </para>
14315    <bridgehead renderas="sect3" id="fiber.numa.h0">
14316      <phrase id="fiber.numa.numa_support_in_boost_fiber"/><link linkend="fiber.numa.numa_support_in_boost_fiber">NUMA
14317      support in Boost.Fiber</link>
14318    </bridgehead>
14319    <para>
14320      Because only a subset of the NUMA-functionality is exposed by several operating
14321      systems, Boost.Fiber provides only a minimalistic NUMA API.
14322    </para>
14323    <important>
14324      <para>
14325        In order to enable NUMA support, b2 property <code><phrase role="identifier">numa</phrase><phrase
14326        role="special">=</phrase><phrase role="identifier">on</phrase></code> must
14327        be specified and linked against additional library <code><phrase role="identifier">libboost_fiber_numa</phrase><phrase
14328        role="special">.</phrase><phrase role="identifier">so</phrase></code>.
14329      </para>
14330    </important>
14331    <important>
14332      <para>
14333        MinGW using pthread implementation is not supported on Windows.
14334      </para>
14335    </important>
14336    <table frame="all" id="fiber.numa.supported_functionality_operating_systems">
14337      <title>Supported functionality/operating systems</title>
14338      <tgroup cols="7">
14339        <thead>
14340          <row>
14341            <entry>
14342            </entry>
14343            <entry>
14344              <para>
14345                AIX
14346              </para>
14347            </entry>
14348            <entry>
14349              <para>
14350                FreeBSD
14351              </para>
14352            </entry>
14353            <entry>
14354              <para>
14355                HP/UX
14356              </para>
14357            </entry>
14358            <entry>
14359              <para>
14360                Linux
14361              </para>
14362            </entry>
14363            <entry>
14364              <para>
14365                Solaris
14366              </para>
14367            </entry>
14368            <entry>
14369              <para>
14370                Windows
14371              </para>
14372            </entry>
14373          </row>
14374        </thead>
14375        <tbody>
14376          <row>
14377            <entry>
14378              <para>
14379                pin thread
14380              </para>
14381            </entry>
14382            <entry>
14383              <para>
14384                +
14385              </para>
14386            </entry>
14387            <entry>
14388              <para>
14389                +
14390              </para>
14391            </entry>
14392            <entry>
14393              <para>
14394                +
14395              </para>
14396            </entry>
14397            <entry>
14398              <para>
14399                +
14400              </para>
14401            </entry>
14402            <entry>
14403              <para>
14404                +
14405              </para>
14406            </entry>
14407            <entry>
14408              <para>
14409                +
14410              </para>
14411            </entry>
14412          </row>
14413          <row>
14414            <entry>
14415              <para>
14416                logical CPUs/NUMA nodes
14417              </para>
14418            </entry>
14419            <entry>
14420              <para>
14421                +
14422              </para>
14423            </entry>
14424            <entry>
14425              <para>
14426                +
14427              </para>
14428            </entry>
14429            <entry>
14430              <para>
14431                +
14432              </para>
14433            </entry>
14434            <entry>
14435              <para>
14436                +
14437              </para>
14438            </entry>
14439            <entry>
14440              <para>
14441                +
14442              </para>
14443            </entry>
14444            <entry>
14445              <para>
14446                +<footnote id="fiber.numa.f1">
14447                <para>
14448                  Windows organizes logical cpus in groups of 64; boost.fiber maps
14449                  {group-id,cpud-id} to a scalar equivalent to cpu ID of Linux (64
14450                  * group ID + cpu ID).
14451                </para>
14452                </footnote>
14453              </para>
14454            </entry>
14455          </row>
14456          <row>
14457            <entry>
14458              <para>
14459                NUMA node distance
14460              </para>
14461            </entry>
14462            <entry>
14463              <para>
14464                -
14465              </para>
14466            </entry>
14467            <entry>
14468              <para>
14469                -
14470              </para>
14471            </entry>
14472            <entry>
14473              <para>
14474                -
14475              </para>
14476            </entry>
14477            <entry>
14478              <para>
14479                +
14480              </para>
14481            </entry>
14482            <entry>
14483              <para>
14484                -
14485              </para>
14486            </entry>
14487            <entry>
14488              <para>
14489                -
14490              </para>
14491            </entry>
14492          </row>
14493          <row>
14494            <entry>
14495              <para>
14496                tested on
14497              </para>
14498            </entry>
14499            <entry>
14500              <para>
14501                AIX 7.2
14502              </para>
14503            </entry>
14504            <entry>
14505              <para>
14506                FreeBSD 11
14507              </para>
14508            </entry>
14509            <entry>
14510              <para>
14511                -
14512              </para>
14513            </entry>
14514            <entry>
14515              <para>
14516                Arch Linux (4.10.13)
14517              </para>
14518            </entry>
14519            <entry>
14520              <para>
14521                OpenIndiana HIPSTER
14522              </para>
14523            </entry>
14524            <entry>
14525              <para>
14526                Windows 10
14527              </para>
14528            </entry>
14529          </row>
14530        </tbody>
14531      </tgroup>
14532    </table>
14533    <para>
14534      In order to keep the memory access local as possible, the NUMA topology must
14535      be evaluated.
14536    </para>
14537<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>
14538<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>
14539    <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>
14540    <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>
14541    <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>
14542        <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>
14543    <phrase role="special">}</phrase>
14544    <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>
14545    <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>
14546        <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>
14547    <phrase role="special">}</phrase>
14548    <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>
14549<phrase role="special">}</phrase>
14550<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>
14551
14552<phrase role="identifier">output</phrase><phrase role="special">:</phrase>
14553    <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>
14554    <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>
14555    <phrase role="identifier">done</phrase>
14556</programlisting>
14557    <para>
14558      The example shows that the systems consits out of 2 NUMA-nodes, to each NUMA-node
14559      belong 16 logical cpus. The distance measures the costs to access the memory
14560      of another NUMA-node. A NUMA-node has always a distance <code><phrase role="number">10</phrase></code>
14561      to itself (lowest possible value).<sbr/> The position in the array corresponds
14562      with the NUMA-node ID.
14563    </para>
14564    <para>
14565      Some work-loads benefit from pinning threads to a logical cpus. For instance
14566      scheduling algorithm <link linkend="class_numa_work_stealing"><code>numa::work_stealing</code></link> pins the thread
14567      that runs the fiber scheduler to a logical cpu. This prevents the operating
14568      system scheduler to move the thread to another logical cpu that might run other
14569      fiber scheduler(s) or migrating the thread to a logical cpu part of another
14570      NUMA-node.
14571    </para>
14572<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>
14573    <phrase role="comment">// thread registers itself at work-stealing scheduler</phrase>
14574    <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>
14575    <phrase role="special">...</phrase>
14576<phrase role="special">}</phrase>
14577
14578<phrase role="comment">// evaluate the NUMA topology</phrase>
14579<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>
14580<phrase role="comment">// start-thread runs on NUMA-node `0`</phrase>
14581<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>
14582<phrase role="comment">// start-thread is pinnded to first cpu ID in the list of logical cpus of NUMA-node `0`</phrase>
14583<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>
14584<phrase role="comment">// start worker-threads first</phrase>
14585<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>
14586<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>
14587    <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>
14588        <phrase role="comment">// exclude start-thread</phrase>
14589        <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>
14590            <phrase role="comment">// spawn thread</phrase>
14591            <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>
14592        <phrase role="special">}</phrase>
14593    <phrase role="special">}</phrase>
14594<phrase role="special">}</phrase>
14595<phrase role="comment">// start-thread registers itself on work-stealing scheduler</phrase>
14596<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>
14597<phrase role="special">...</phrase>
14598</programlisting>
14599    <para>
14600      The example evaluates the NUMA topology with <code><phrase role="identifier">boost</phrase><phrase
14601      role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase
14602      role="special">::</phrase><phrase role="identifier">numa</phrase><phrase role="special">::</phrase><phrase
14603      role="identifier">topology</phrase><phrase role="special">()</phrase></code>
14604      and spawns for each logical cpu a thread. Each spawned thread installs the
14605      NUMA-aware work-stealing scheduler. The scheduler pins the thread to the logical
14606      cpu that was specified at construction.<sbr/> If the local queue of one thread
14607      runs out of ready fibers, the thread tries to steal a ready fiber from another
14608      thread running at logical cpu that belong to the same NUMA-node (local memory
14609      access). If no fiber could be stolen, the thread tries to steal fibers from
14610      logical cpus part of other NUMA-nodes (remote memory access).
14611    </para>
14612    <bridgehead renderas="sect3" id="fiber.numa.h1">
14613      <phrase id="fiber.numa.synopsis"/><link linkend="fiber.numa.synopsis">Synopsis</link>
14614    </bridgehead>
14615<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>
14616<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>
14617
14618<phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase>
14619<phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase>
14620<phrase role="keyword">namespace</phrase> <phrase role="identifier">numa</phrase> <phrase role="special">{</phrase>
14621
14622<phrase role="keyword">struct</phrase> <phrase role="identifier">node</phrase> <phrase role="special">{</phrase>
14623    <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">uint32_t</phrase>                   <phrase role="identifier">id</phrase><phrase role="special">;</phrase>
14624    <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>
14625    <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>
14626<phrase role="special">};</phrase>
14627<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>
14628
14629<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>
14630
14631<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>
14632<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>
14633
14634<phrase role="special">}}}</phrase>
14635
14636<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>
14637
14638<phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase>
14639<phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase>
14640<phrase role="keyword">namespace</phrase> <phrase role="identifier">numa</phrase> <phrase role="special">{</phrase>
14641<phrase role="keyword">namespace</phrase> <phrase role="identifier">algo</phrase> <phrase role="special">{</phrase>
14642
14643<phrase role="keyword">class</phrase> <phrase role="identifier">work_stealing</phrase><phrase role="special">;</phrase>
14644
14645<phrase role="special">}}}</phrase>
14646</programlisting>
14647    <para>
14648      <bridgehead renderas="sect4" id="class_numa_node_bridgehead">
14649  <phrase id="class_numa_node"/>
14650  <link linkend="class_numa_node">Class <code>numa::node</code></link>
14651</bridgehead>
14652    </para>
14653<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>
14654
14655<phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase>
14656<phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase>
14657<phrase role="keyword">namespace</phrase> <phrase role="identifier">numa</phrase> <phrase role="special">{</phrase>
14658
14659<phrase role="keyword">struct</phrase> <phrase role="identifier">node</phrase> <phrase role="special">{</phrase>
14660    <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">uint32_t</phrase>                   <phrase role="identifier">id</phrase><phrase role="special">;</phrase>
14661    <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>
14662    <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>
14663<phrase role="special">};</phrase>
14664<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>
14665
14666<phrase role="special">}}}</phrase>
14667</programlisting>
14668    <para>
14669      <bridgehead renderas="sect4" id="numa_node_id_bridgehead">
14670  <phrase id="numa_node_id"/>
14671  <link linkend="numa_node_id">Data member <code>id</code></link>
14672</bridgehead>
14673    </para>
14674<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>
14675</programlisting>
14676    <variablelist>
14677      <title></title>
14678      <varlistentry>
14679        <term>Effects:</term>
14680        <listitem>
14681          <para>
14682            ID of the NUMA-node
14683          </para>
14684        </listitem>
14685      </varlistentry>
14686    </variablelist>
14687    <para>
14688      <bridgehead renderas="sect4" id="numa_node_logical_cpus_bridgehead">
14689  <phrase id="numa_node_logical_cpus"/>
14690  <link linkend="numa_node_logical_cpus">Data
14691      member <code>logical_cpus</code></link>
14692</bridgehead>
14693    </para>
14694<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>
14695</programlisting>
14696    <variablelist>
14697      <title></title>
14698      <varlistentry>
14699        <term>Effects:</term>
14700        <listitem>
14701          <para>
14702            set of logical cpu IDs belonging to the NUMA-node
14703          </para>
14704        </listitem>
14705      </varlistentry>
14706    </variablelist>
14707    <para>
14708      <bridgehead renderas="sect4" id="numa_node_distance_bridgehead">
14709  <phrase id="numa_node_distance"/>
14710  <link linkend="numa_node_distance">Data member
14711      <code>distance</code></link>
14712</bridgehead>
14713    </para>
14714<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>
14715</programlisting>
14716    <variablelist>
14717      <title></title>
14718      <varlistentry>
14719        <term>Effects:</term>
14720        <listitem>
14721          <para>
14722            The distance between NUMA-nodes describe the cots of accessing the remote
14723            memory.
14724          </para>
14725        </listitem>
14726      </varlistentry>
14727      <varlistentry>
14728        <term>Note:</term>
14729        <listitem>
14730          <para>
14731            A NUMA-node has a distance of <code><phrase role="number">10</phrase></code>
14732            to itself, remote NUMA-nodes have a distance &gt; <code><phrase role="number">10</phrase></code>.
14733            The index in the array corresponds to the ID <code><phrase role="identifier">id</phrase></code>
14734            of the NUMA-node. At the moment only Linux returns the correct distances,
14735            for all other operating systems remote NUMA-nodes get a default value
14736            of <code><phrase role="number">20</phrase></code>.
14737          </para>
14738        </listitem>
14739      </varlistentry>
14740    </variablelist>
14741    <para>
14742      <bridgehead renderas="sect4" id="numa_node_operator_less_bridgehead">
14743  <phrase id="numa_node_operator_less"/>
14744  <link linkend="numa_node_operator_less">Member
14745      function <code>operator&lt;</code>()</link>
14746</bridgehead>
14747    </para>
14748<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>
14749</programlisting>
14750    <variablelist>
14751      <title></title>
14752      <varlistentry>
14753        <term>Returns:</term>
14754        <listitem>
14755          <para>
14756            <code><phrase role="keyword">true</phrase></code> if <code><phrase role="identifier">lhs</phrase>
14757            <phrase role="special">!=</phrase> <phrase role="identifier">rhs</phrase></code>
14758            is true and the implementation-defined total order of <code><phrase role="identifier">node</phrase><phrase
14759            role="special">::</phrase><phrase role="identifier">id</phrase></code>
14760            values places <code><phrase role="identifier">lhs</phrase></code> before
14761            <code><phrase role="identifier">rhs</phrase></code>, false otherwise.
14762          </para>
14763        </listitem>
14764      </varlistentry>
14765      <varlistentry>
14766        <term>Throws:</term>
14767        <listitem>
14768          <para>
14769            Nothing.
14770          </para>
14771        </listitem>
14772      </varlistentry>
14773    </variablelist>
14774    <para>
14775      <bridgehead renderas="sect4" id="numa_topology_bridgehead">
14776  <phrase id="numa_topology"/>
14777  <link linkend="numa_topology">Non-member function <code>numa::topology()</code></link>
14778</bridgehead>
14779    </para>
14780<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>
14781
14782<phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase>
14783<phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase>
14784<phrase role="keyword">namespace</phrase> <phrase role="identifier">numa</phrase> <phrase role="special">{</phrase>
14785
14786<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>
14787
14788<phrase role="special">}}}</phrase>
14789</programlisting>
14790    <variablelist>
14791      <title></title>
14792      <varlistentry>
14793        <term>Effects:</term>
14794        <listitem>
14795          <para>
14796            Evaluates the NUMA topology.
14797          </para>
14798        </listitem>
14799      </varlistentry>
14800      <varlistentry>
14801        <term>Returns:</term>
14802        <listitem>
14803          <para>
14804            a vector of NUMA-nodes describing the NUMA architecture of the system
14805            (each element represents a NUMA-node).
14806          </para>
14807        </listitem>
14808      </varlistentry>
14809      <varlistentry>
14810        <term>Throws:</term>
14811        <listitem>
14812          <para>
14813            <code><phrase role="identifier">system_error</phrase></code>
14814          </para>
14815        </listitem>
14816      </varlistentry>
14817    </variablelist>
14818    <para>
14819      <bridgehead renderas="sect4" id="numa_pin_thread_bridgehead">
14820  <phrase id="numa_pin_thread"/>
14821  <link linkend="numa_pin_thread">Non-member function
14822      <code>numa::pin_thread()</code></link>
14823</bridgehead>
14824    </para>
14825<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>
14826
14827<phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase>
14828<phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase>
14829<phrase role="keyword">namespace</phrase> <phrase role="identifier">numa</phrase> <phrase role="special">{</phrase>
14830
14831<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>
14832<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>
14833
14834<phrase role="special">}}}</phrase>
14835</programlisting>
14836    <variablelist>
14837      <title></title>
14838      <varlistentry>
14839        <term>Effects:</term>
14840        <listitem>
14841          <para>
14842            First version pins <code><phrase role="keyword">this</phrase> <phrase
14843            role="identifier">thread</phrase></code> to the logical cpu with ID
14844            <code><phrase role="identifier">cpu_id</phrase></code>, e.g. the operating
14845            system scheduler will not migrate the thread to another logical cpu.
14846            The second variant pins the thread with the native ID <code><phrase role="identifier">h</phrase></code>
14847            to logical cpu with ID <code><phrase role="identifier">cpu_id</phrase></code>.
14848          </para>
14849        </listitem>
14850      </varlistentry>
14851      <varlistentry>
14852        <term>Throws:</term>
14853        <listitem>
14854          <para>
14855            <code><phrase role="identifier">system_error</phrase></code>
14856          </para>
14857        </listitem>
14858      </varlistentry>
14859    </variablelist>
14860    <para>
14861      <bridgehead renderas="sect4" id="class_numa_work_stealing_bridgehead">
14862  <phrase id="class_numa_work_stealing"/>
14863  <link linkend="class_numa_work_stealing">Class
14864      <code>numa::work_stealing</code></link>
14865</bridgehead>
14866    </para>
14867    <para>
14868      This class implements <link linkend="class_algorithm"><code>algorithm</code></link>; the thread running this scheduler
14869      is pinned to the given logical cpu. If the local ready-queue runs out of ready
14870      fibers, ready fibers are stolen from other schedulers that run on logical cpus
14871      that belong to the same NUMA-node (local memory access).<sbr/> If no ready
14872      fibers can be stolen from the local NUMA-node, the algorithm selects schedulers
14873      running on other NUMA-nodes (remote memory access).<sbr/> The victim scheduler
14874      (from which a ready fiber is stolen) is selected at random.
14875    </para>
14876<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>
14877
14878<phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase>
14879<phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase>
14880<phrase role="keyword">namespace</phrase> <phrase role="identifier">numa</phrase> <phrase role="special">{</phrase>
14881<phrase role="keyword">namespace</phrase> <phrase role="identifier">algo</phrase> <phrase role="special">{</phrase>
14882
14883<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>
14884<phrase role="keyword">public</phrase><phrase role="special">:</phrase>
14885    <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>
14886                   <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>
14887                   <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>
14888                   <phrase role="keyword">bool</phrase> <phrase role="identifier">suspend</phrase> <phrase role="special">=</phrase> <phrase role="keyword">false</phrase><phrase role="special">);</phrase>
14889
14890    <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>
14891    <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>
14892
14893    <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>
14894    <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>
14895
14896    <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>
14897
14898    <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>
14899
14900    <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>
14901
14902    <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>
14903
14904    <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>
14905<phrase role="special">};</phrase>
14906
14907<phrase role="special">}}}}</phrase>
14908</programlisting>
14909    <bridgehead renderas="sect3" id="fiber.numa.h2">
14910      <phrase id="fiber.numa.constructor"/><link linkend="fiber.numa.constructor">Constructor</link>
14911    </bridgehead>
14912<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>
14913               <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>
14914               <phrase role="keyword">bool</phrase> <phrase role="identifier">suspend</phrase> <phrase role="special">=</phrase> <phrase role="keyword">false</phrase><phrase role="special">);</phrase>
14915</programlisting>
14916    <variablelist>
14917      <title></title>
14918      <varlistentry>
14919        <term>Effects:</term>
14920        <listitem>
14921          <para>
14922            Constructs work-stealing scheduling algorithm. The thread is pinned to
14923            logical cpu with ID <code><phrase role="identifier">cpu_id</phrase></code>.
14924            If local ready-queue runs out of ready fibers, ready fibers are stolen
14925            from other schedulers using <code><phrase role="identifier">topology</phrase></code>
14926            (represents the NUMA-topology of the system).
14927          </para>
14928        </listitem>
14929      </varlistentry>
14930      <varlistentry>
14931        <term>Throws:</term>
14932        <listitem>
14933          <para>
14934            <code><phrase role="identifier">system_error</phrase></code>
14935          </para>
14936        </listitem>
14937      </varlistentry>
14938      <varlistentry>
14939        <term>Note:</term>
14940        <listitem>
14941          <para>
14942            If <code><phrase role="identifier">suspend</phrase></code> is set to
14943            <code><phrase role="keyword">true</phrase></code>, then the scheduler
14944            suspends if no ready fiber could be stolen. The scheduler will by woken
14945            up if a sleeping fiber times out or it was notified from remote (other
14946            thread or fiber scheduler).
14947          </para>
14948        </listitem>
14949      </varlistentry>
14950    </variablelist>
14951    <para>
14952      <bridgehead renderas="sect4" id="numa_work_stealing_awakened_bridgehead">
14953  <phrase id="numa_work_stealing_awakened"/>
14954  <link linkend="numa_work_stealing_awakened">Member
14955      function <code>awakened</code>()</link>
14956</bridgehead>
14957    </para>
14958<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>
14959</programlisting>
14960    <variablelist>
14961      <title></title>
14962      <varlistentry>
14963        <term>Effects:</term>
14964        <listitem>
14965          <para>
14966            Enqueues fiber <code><phrase role="identifier">f</phrase></code> onto
14967            the shared ready queue.
14968          </para>
14969        </listitem>
14970      </varlistentry>
14971      <varlistentry>
14972        <term>Throws:</term>
14973        <listitem>
14974          <para>
14975            Nothing.
14976          </para>
14977        </listitem>
14978      </varlistentry>
14979    </variablelist>
14980    <para>
14981      <bridgehead renderas="sect4" id="numa_work_stealing_pick_next_bridgehead">
14982  <phrase id="numa_work_stealing_pick_next"/>
14983  <link linkend="numa_work_stealing_pick_next">Member
14984      function <code>pick_next</code>()</link>
14985</bridgehead>
14986    </para>
14987<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>
14988</programlisting>
14989    <variablelist>
14990      <title></title>
14991      <varlistentry>
14992        <term>Returns:</term>
14993        <listitem>
14994          <para>
14995            the fiber at the head of the ready queue, or <code><phrase role="keyword">nullptr</phrase></code>
14996            if the queue is empty.
14997          </para>
14998        </listitem>
14999      </varlistentry>
15000      <varlistentry>
15001        <term>Throws:</term>
15002        <listitem>
15003          <para>
15004            Nothing.
15005          </para>
15006        </listitem>
15007      </varlistentry>
15008      <varlistentry>
15009        <term>Note:</term>
15010        <listitem>
15011          <para>
15012            Placing ready fibers onto the tail of the sahred queue, and returning
15013            them from the head of that queue, shares the thread between ready fibers
15014            in round-robin fashion.
15015          </para>
15016        </listitem>
15017      </varlistentry>
15018    </variablelist>
15019    <para>
15020      <bridgehead renderas="sect4" id="numa_work_stealing_has_ready_fibers_bridgehead">
15021  <phrase id="numa_work_stealing_has_ready_fibers"/>
15022  <link linkend="numa_work_stealing_has_ready_fibers">Member
15023      function <code>has_ready_fibers</code>()</link>
15024</bridgehead>
15025    </para>
15026<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>
15027</programlisting>
15028    <variablelist>
15029      <title></title>
15030      <varlistentry>
15031        <term>Returns:</term>
15032        <listitem>
15033          <para>
15034            <code><phrase role="keyword">true</phrase></code> if scheduler has fibers
15035            ready to run.
15036          </para>
15037        </listitem>
15038      </varlistentry>
15039      <varlistentry>
15040        <term>Throws:</term>
15041        <listitem>
15042          <para>
15043            Nothing.
15044          </para>
15045        </listitem>
15046      </varlistentry>
15047    </variablelist>
15048    <para>
15049      <bridgehead renderas="sect4" id="numa_work_stealing_suspend_until_bridgehead">
15050  <phrase id="numa_work_stealing_suspend_until"/>
15051  <link linkend="numa_work_stealing_suspend_until">Member
15052      function <code>suspend_until</code>()</link>
15053</bridgehead>
15054    </para>
15055<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>
15056</programlisting>
15057    <variablelist>
15058      <title></title>
15059      <varlistentry>
15060        <term>Effects:</term>
15061        <listitem>
15062          <para>
15063            Informs <code><phrase role="identifier">work_stealing</phrase></code>
15064            that no ready fiber will be available until time-point <code><phrase
15065            role="identifier">abs_time</phrase></code>. This implementation blocks
15066            in <ulink url="http://en.cppreference.com/w/cpp/thread/condition_variable/wait_until"><code><phrase
15067            role="identifier">std</phrase><phrase role="special">::</phrase><phrase
15068            role="identifier">condition_variable</phrase><phrase role="special">::</phrase><phrase
15069            role="identifier">wait_until</phrase><phrase role="special">()</phrase></code></ulink>.
15070          </para>
15071        </listitem>
15072      </varlistentry>
15073      <varlistentry>
15074        <term>Throws:</term>
15075        <listitem>
15076          <para>
15077            Nothing.
15078          </para>
15079        </listitem>
15080      </varlistentry>
15081    </variablelist>
15082    <para>
15083      <bridgehead renderas="sect4" id="numa_work_stealing_notify_bridgehead">
15084  <phrase id="numa_work_stealing_notify"/>
15085  <link linkend="numa_work_stealing_notify">Member
15086      function <code>notify</code>()</link>
15087</bridgehead>
15088    </para>
15089<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>
15090</programlisting>
15091    <variablelist>
15092      <title></title>
15093      <varlistentry>
15094        <term>Effects:</term>
15095        <listitem>
15096          <para>
15097            Wake up a pending call to <link linkend="work_stealing_suspend_until"><code>work_stealing::suspend_until()</code></link>,
15098            some fibers might be ready. This implementation wakes <code><phrase role="identifier">suspend_until</phrase><phrase
15099            role="special">()</phrase></code> via <ulink url="http://en.cppreference.com/w/cpp/thread/condition_variable/notify_all"><code><phrase
15100            role="identifier">std</phrase><phrase role="special">::</phrase><phrase
15101            role="identifier">condition_variable</phrase><phrase role="special">::</phrase><phrase
15102            role="identifier">notify_all</phrase><phrase role="special">()</phrase></code></ulink>.
15103          </para>
15104        </listitem>
15105      </varlistentry>
15106      <varlistentry>
15107        <term>Throws:</term>
15108        <listitem>
15109          <para>
15110            Nothing.
15111          </para>
15112        </listitem>
15113      </varlistentry>
15114    </variablelist>
15115  </section>
15116  <section id="fiber.gpu_computing">
15117    <title><link linkend="fiber.gpu_computing">GPU computing</link></title>
15118    <section id="fiber.gpu_computing.cuda">
15119      <title><anchor id="cuda"/><link linkend="fiber.gpu_computing.cuda">CUDA</link></title>
15120      <para>
15121        <ulink url="http://developer.nvidia.com/cuda-zone/">CUDA (Compute Unified
15122        Device Architecture)</ulink> is a platform for parallel computing on NVIDIA
15123        GPUs. The application programming interface of CUDA gives access to GPU's
15124        instruction set and computation resources (Execution of compute kernels).
15125      </para>
15126      <bridgehead renderas="sect4" id="fiber.gpu_computing.cuda.h0">
15127        <phrase id="fiber.gpu_computing.cuda.synchronization_with_cuda_streams"/><link
15128        linkend="fiber.gpu_computing.cuda.synchronization_with_cuda_streams">Synchronization
15129        with CUDA streams</link>
15130      </bridgehead>
15131      <para>
15132        CUDA operation such as compute kernels or memory transfer (between host and
15133        device) can be grouped/queued by CUDA streams. are executed on the GPUs.
15134        Boost.Fiber enables a fiber to sleep (suspend) till a CUDA stream has completed
15135        its operations. This enables applications to run other fibers on the CPU
15136        without the need to spawn an additional OS-threads. And resume the fiber
15137        when the CUDA streams has finished.
15138      </para>
15139<programlisting><phrase role="identifier">__global__</phrase>
15140<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>
15141    <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>
15142    <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>
15143        <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>
15144        <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>
15145        <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>
15146        <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>
15147        <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>
15148    <phrase role="special">}</phrase>
15149<phrase role="special">}</phrase>
15150
15151<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>
15152    <phrase role="identifier">cudaStream_t</phrase> <phrase role="identifier">stream</phrase><phrase role="special">;</phrase>
15153    <phrase role="identifier">cudaStreamCreate</phrase><phrase role="special">(</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">stream</phrase><phrase role="special">);</phrase>
15154    <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>
15155    <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>
15156    <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>
15157    <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>
15158    <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>
15159    <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>
15160    <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>
15161    <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>
15162    <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>
15163    <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>
15164    <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">minstd_rand</phrase> <phrase role="identifier">generator</phrase><phrase role="special">;</phrase>
15165    <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>
15166    <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>
15167        <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>
15168        <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>
15169    <phrase role="special">}</phrase>
15170    <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>
15171        <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>
15172        <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>
15173        <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>
15174        <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>
15175    <phrase role="special">}</phrase>
15176    <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>
15177    <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>
15178    <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>
15179    <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>
15180    <phrase role="identifier">cudaFreeHost</phrase><phrase role="special">(</phrase> <phrase role="identifier">host_a</phrase><phrase role="special">);</phrase>
15181    <phrase role="identifier">cudaFreeHost</phrase><phrase role="special">(</phrase> <phrase role="identifier">host_b</phrase><phrase role="special">);</phrase>
15182    <phrase role="identifier">cudaFreeHost</phrase><phrase role="special">(</phrase> <phrase role="identifier">host_c</phrase><phrase role="special">);</phrase>
15183    <phrase role="identifier">cudaFree</phrase><phrase role="special">(</phrase> <phrase role="identifier">dev_a</phrase><phrase role="special">);</phrase>
15184    <phrase role="identifier">cudaFree</phrase><phrase role="special">(</phrase> <phrase role="identifier">dev_b</phrase><phrase role="special">);</phrase>
15185    <phrase role="identifier">cudaFree</phrase><phrase role="special">(</phrase> <phrase role="identifier">dev_c</phrase><phrase role="special">);</phrase>
15186    <phrase role="identifier">cudaStreamDestroy</phrase><phrase role="special">(</phrase> <phrase role="identifier">stream</phrase><phrase role="special">);</phrase>
15187<phrase role="special">});</phrase>
15188<phrase role="identifier">f</phrase><phrase role="special">.</phrase><phrase role="identifier">join</phrase><phrase role="special">();</phrase>
15189</programlisting>
15190      <bridgehead renderas="sect4" id="fiber.gpu_computing.cuda.h1">
15191        <phrase id="fiber.gpu_computing.cuda.synopsis"/><link linkend="fiber.gpu_computing.cuda.synopsis">Synopsis</link>
15192      </bridgehead>
15193<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>
15194
15195<phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase>
15196<phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase>
15197<phrase role="keyword">namespace</phrase> <phrase role="identifier">cuda</phrase> <phrase role="special">{</phrase>
15198
15199<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>
15200<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>
15201
15202<phrase role="special">}}}</phrase>
15203</programlisting>
15204      <para>
15205        <bridgehead renderas="sect4" id="cuda_waitfor_bridgehead">
15206  <phrase id="cuda_waitfor"/>
15207  <link linkend="cuda_waitfor">Non-member function <code>cuda::waitfor()</code></link>
15208</bridgehead>
15209      </para>
15210<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>
15211
15212<phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase>
15213<phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase>
15214<phrase role="keyword">namespace</phrase> <phrase role="identifier">cuda</phrase> <phrase role="special">{</phrase>
15215
15216<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>
15217<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>
15218
15219<phrase role="special">}}}</phrase>
15220</programlisting>
15221      <variablelist>
15222        <title></title>
15223        <varlistentry>
15224          <term>Effects:</term>
15225          <listitem>
15226            <para>
15227              Suspends active fiber till CUDA stream has finished its operations.
15228            </para>
15229          </listitem>
15230        </varlistentry>
15231        <varlistentry>
15232          <term>Returns:</term>
15233          <listitem>
15234            <para>
15235              tuple of stream reference and the CUDA stream status
15236            </para>
15237          </listitem>
15238        </varlistentry>
15239      </variablelist>
15240    </section>
15241    <section id="fiber.gpu_computing.hip">
15242      <title><anchor id="hip"/><link linkend="fiber.gpu_computing.hip">ROCm/HIP</link></title>
15243      <para>
15244        <ulink url="http://github.com/ROCm-Developer-Tools/HIP/tree/roc-1.6.0/">HIP</ulink>
15245        is part of the <ulink url="http://rocm.github.io/">ROC (Radeon Open Compute)</ulink>
15246        platform for parallel computing on AMD and NVIDIA GPUs. The application programming
15247        interface of HIP gives access to GPU's instruction set and computation resources
15248        (Execution of compute kernels).
15249      </para>
15250      <bridgehead renderas="sect4" id="fiber.gpu_computing.hip.h0">
15251        <phrase id="fiber.gpu_computing.hip.synchronization_with_rocm_hip_streams"/><link
15252        linkend="fiber.gpu_computing.hip.synchronization_with_rocm_hip_streams">Synchronization
15253        with ROCm/HIP streams</link>
15254      </bridgehead>
15255      <para>
15256        HIP operation such as compute kernels or memory transfer (between host and
15257        device) can be grouped/queued by HIP streams. are executed on the GPUs. Boost.Fiber
15258        enables a fiber to sleep (suspend) till a HIP stream has completed its operations.
15259        This enables applications to run other fibers on the CPU without the need
15260        to spawn an additional OS-threads. And resume the fiber when the HIP streams
15261        has finished.
15262      </para>
15263<programlisting><phrase role="identifier">__global__</phrase>
15264<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>
15265    <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>
15266    <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>
15267        <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>
15268        <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>
15269        <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>
15270        <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>
15271        <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>
15272    <phrase role="special">}</phrase>
15273<phrase role="special">}</phrase>
15274
15275<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>
15276    <phrase role="identifier">hipStream_t</phrase> <phrase role="identifier">stream</phrase><phrase role="special">;</phrase>
15277    <phrase role="identifier">hipStreamCreate</phrase><phrase role="special">(</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">stream</phrase><phrase role="special">);</phrase>
15278    <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>
15279    <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>
15280    <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>
15281    <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>
15282    <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>
15283    <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>
15284    <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>
15285    <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>
15286    <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>
15287    <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>
15288    <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">minstd_rand</phrase> <phrase role="identifier">generator</phrase><phrase role="special">;</phrase>
15289    <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>
15290    <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>
15291        <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>
15292        <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>
15293    <phrase role="special">}</phrase>
15294    <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>
15295        <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>
15296        <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>
15297        <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>
15298        <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>
15299    <phrase role="special">}</phrase>
15300    <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>
15301    <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>
15302    <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>
15303    <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>
15304    <phrase role="identifier">hipHostFree</phrase><phrase role="special">(</phrase> <phrase role="identifier">host_a</phrase><phrase role="special">);</phrase>
15305    <phrase role="identifier">hipHostFree</phrase><phrase role="special">(</phrase> <phrase role="identifier">host_b</phrase><phrase role="special">);</phrase>
15306    <phrase role="identifier">hipHostFree</phrase><phrase role="special">(</phrase> <phrase role="identifier">host_c</phrase><phrase role="special">);</phrase>
15307    <phrase role="identifier">hipFree</phrase><phrase role="special">(</phrase> <phrase role="identifier">dev_a</phrase><phrase role="special">);</phrase>
15308    <phrase role="identifier">hipFree</phrase><phrase role="special">(</phrase> <phrase role="identifier">dev_b</phrase><phrase role="special">);</phrase>
15309    <phrase role="identifier">hipFree</phrase><phrase role="special">(</phrase> <phrase role="identifier">dev_c</phrase><phrase role="special">);</phrase>
15310    <phrase role="identifier">hipStreamDestroy</phrase><phrase role="special">(</phrase> <phrase role="identifier">stream</phrase><phrase role="special">);</phrase>
15311<phrase role="special">});</phrase>
15312<phrase role="identifier">f</phrase><phrase role="special">.</phrase><phrase role="identifier">join</phrase><phrase role="special">();</phrase>
15313</programlisting>
15314      <bridgehead renderas="sect4" id="fiber.gpu_computing.hip.h1">
15315        <phrase id="fiber.gpu_computing.hip.synopsis"/><link linkend="fiber.gpu_computing.hip.synopsis">Synopsis</link>
15316      </bridgehead>
15317<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>
15318
15319<phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase>
15320<phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase>
15321<phrase role="keyword">namespace</phrase> <phrase role="identifier">hip</phrase> <phrase role="special">{</phrase>
15322
15323<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>
15324<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>
15325
15326<phrase role="special">}}}</phrase>
15327</programlisting>
15328      <para>
15329        <bridgehead renderas="sect4" id="hip_waitfor_bridgehead">
15330  <phrase id="hip_waitfor"/>
15331  <link linkend="hip_waitfor">Non-member function <code>hip::waitfor()</code></link>
15332</bridgehead>
15333      </para>
15334<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>
15335
15336<phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase>
15337<phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase>
15338<phrase role="keyword">namespace</phrase> <phrase role="identifier">hip</phrase> <phrase role="special">{</phrase>
15339
15340<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>
15341<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>
15342
15343<phrase role="special">}}}</phrase>
15344</programlisting>
15345      <variablelist>
15346        <title></title>
15347        <varlistentry>
15348          <term>Effects:</term>
15349          <listitem>
15350            <para>
15351              Suspends active fiber till HIP stream has finished its operations.
15352            </para>
15353          </listitem>
15354        </varlistentry>
15355        <varlistentry>
15356          <term>Returns:</term>
15357          <listitem>
15358            <para>
15359              tuple of stream reference and the HIP stream status
15360            </para>
15361          </listitem>
15362        </varlistentry>
15363      </variablelist>
15364    </section>
15365  </section>
15366  <section id="fiber.worker">
15367    <title><anchor id="worker"/><link linkend="fiber.worker">Running with worker
15368    threads</link></title>
15369    <bridgehead renderas="sect3" id="fiber.worker.h0">
15370      <phrase id="fiber.worker.keep_workers_running"/><link linkend="fiber.worker.keep_workers_running">Keep
15371      workers running</link>
15372    </bridgehead>
15373    <para>
15374      If a worker thread is used but no fiber is created or parts of the framework
15375      (like <link linkend="this_fiber_yield"><code>this_fiber::yield()</code></link>) are touched, then no fiber scheduler
15376      is instantiated.
15377    </para>
15378<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>
15379        <phrase role="special">[]{</phrase>
15380            <phrase role="comment">// fiber scheduler not instantiated</phrase>
15381        <phrase role="special">});</phrase>
15382<phrase role="identifier">worker</phrase><phrase role="special">.</phrase><phrase role="identifier">join</phrase><phrase role="special">();</phrase>
15383</programlisting>
15384    <para>
15385      If <emphasis>use_scheduling_algorithm&lt;&gt;()</emphasis> is invoked, the
15386      fiber scheduler is created. If the worker thread simply returns, destroys the
15387      scheduler and terminates.
15388    </para>
15389<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>
15390        <phrase role="special">[]{</phrase>
15391            <phrase role="comment">// fiber scheduler created</phrase>
15392            <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>
15393        <phrase role="special">});</phrase>
15394<phrase role="identifier">worker</phrase><phrase role="special">.</phrase><phrase role="identifier">join</phrase><phrase role="special">();</phrase>
15395</programlisting>
15396    <para>
15397      In order to keep the worker thread running, the fiber associated with the thread
15398      stack (which is called <quote>main</quote> fiber) is blocked. For instance
15399      the <quote>main</quote> fiber might wait on a <link linkend="class_condition_variable"><code>condition_variable</code></link>.
15400      For a gracefully shutdown <link linkend="class_condition_variable"><code>condition_variable</code></link> is signalled
15401      and the <quote>main</quote> fiber returns. The scheduler gets destructed if
15402      all fibers of the worker thread have been terminated.
15403    </para>
15404<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>
15405<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>
15406<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>
15407        <phrase role="special">[&amp;</phrase><phrase role="identifier">mtx</phrase><phrase role="special">,&amp;</phrase><phrase role="identifier">cv</phrase><phrase role="special">]{</phrase>
15408            <phrase role="identifier">mtx</phrase><phrase role="special">.</phrase><phrase role="identifier">lock</phrase><phrase role="special">();</phrase>
15409            <phrase role="comment">// suspend till signalled</phrase>
15410            <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>
15411            <phrase role="identifier">mtx</phrase><phrase role="special">.</phrase><phrase role="identifier">unlock</phrase><phrase role="special">();</phrase>
15412        <phrase role="special">});</phrase>
15413<phrase role="comment">// signal termination</phrase>
15414<phrase role="identifier">cv</phrase><phrase role="special">.</phrase><phrase role="identifier">notify_all</phrase><phrase role="special">();</phrase>
15415<phrase role="identifier">worker</phrase><phrase role="special">.</phrase><phrase role="identifier">join</phrase><phrase role="special">();</phrase>
15416</programlisting>
15417    <bridgehead renderas="sect3" id="fiber.worker.h1">
15418      <phrase id="fiber.worker.processing_tasks"/><link linkend="fiber.worker.processing_tasks">Processing
15419      tasks</link>
15420    </bridgehead>
15421    <para>
15422      Tasks can be transferred via channels. The worker thread runs a pool of fibers
15423      that dequeue and executed tasks from the channel. The termination is signalled
15424      via closing the channel.
15425    </para>
15426<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>
15427<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>
15428<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>
15429        <phrase role="special">[&amp;</phrase><phrase role="identifier">ch</phrase><phrase role="special">]{</phrase>
15430            <phrase role="comment">// create pool of fibers</phrase>
15431            <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>
15432                <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>
15433                    <phrase role="special">[&amp;</phrase><phrase role="identifier">ch</phrase><phrase role="special">]{</phrase>
15434                        <phrase role="identifier">task</phrase> <phrase role="identifier">tsk</phrase><phrase role="special">;</phrase>
15435                        <phrase role="comment">// dequeue and process tasks</phrase>
15436                        <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>
15437                            <phrase role="identifier">tsk</phrase><phrase role="special">();</phrase>
15438                        <phrase role="special">}</phrase>
15439                    <phrase role="special">}}.</phrase><phrase role="identifier">detach</phrase><phrase role="special">();</phrase>
15440            <phrase role="special">}</phrase>
15441            <phrase role="identifier">task</phrase> <phrase role="identifier">tsk</phrase><phrase role="special">;</phrase>
15442            <phrase role="comment">// dequeue and process tasks</phrase>
15443            <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>
15444                <phrase role="identifier">tsk</phrase><phrase role="special">();</phrase>
15445            <phrase role="special">}</phrase>
15446        <phrase role="special">});</phrase>
15447<phrase role="comment">// feed channel with tasks</phrase>
15448<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>
15449<phrase role="special">...</phrase>
15450<phrase role="comment">// signal termination</phrase>
15451<phrase role="identifier">ch</phrase><phrase role="special">.</phrase><phrase role="identifier">close</phrase><phrase role="special">();</phrase>
15452<phrase role="identifier">worker</phrase><phrase role="special">.</phrase><phrase role="identifier">join</phrase><phrase role="special">();</phrase>
15453</programlisting>
15454    <para>
15455      An alternative is to use a work-stealing scheduler. This kind of scheduling
15456      algorithm a worker thread steals fibers from the ready-queue of other worker
15457      threads if its own ready-queue is empty.
15458    </para>
15459    <note>
15460      <para>
15461        Wait till all worker threads have registered the work-stealing scheduling
15462        algorithm.
15463      </para>
15464    </note>
15465<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>
15466<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>
15467<phrase role="comment">// start wotrker-thread first</phrase>
15468<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>
15469        <phrase role="special">[&amp;</phrase><phrase role="identifier">mtx</phrase><phrase role="special">,&amp;</phrase><phrase role="identifier">cv</phrase><phrase role="special">]{</phrase>
15470            <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>
15471            <phrase role="identifier">mtx</phrase><phrase role="special">.</phrase><phrase role="identifier">lock</phrase><phrase role="special">();</phrase>
15472            <phrase role="comment">// suspend main-fiber from the worker thread</phrase>
15473            <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>
15474            <phrase role="identifier">mtx</phrase><phrase role="special">.</phrase><phrase role="identifier">unlock</phrase><phrase role="special">();</phrase>
15475        <phrase role="special">});</phrase>
15476<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>
15477<phrase role="comment">// create fibers with tasks</phrase>
15478<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>
15479<phrase role="special">...</phrase>
15480<phrase role="comment">// signal termination</phrase>
15481<phrase role="identifier">cv</phrase><phrase role="special">.</phrase><phrase role="identifier">notify_all</phrase><phrase role="special">();</phrase>
15482<phrase role="identifier">worker</phrase><phrase role="special">.</phrase><phrase role="identifier">join</phrase><phrase role="special">();</phrase>
15483</programlisting>
15484    <important>
15485      <para>
15486        Because the TIB (thread information block on Windows) is not fully described
15487        in the MSDN, it might be possible that not all required TIB-parts are swapped.
15488        Using WinFiber implementation might be an alternative (see documentation
15489        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
15490        fcontext_t, ucontext_t and WinFiber of boost.context</emphasis></ulink>).
15491      </para>
15492    </important>
15493  </section>
15494  <section id="fiber.performance">
15495    <title><link linkend="fiber.performance">Performance</link></title>
15496    <para>
15497      Performance measurements were taken using <code><phrase role="identifier">std</phrase><phrase
15498      role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase
15499      role="special">::</phrase><phrase role="identifier">highresolution_clock</phrase></code>,
15500      with overhead corrections. The code was compiled with gcc-6.3.1, using build
15501      options: variant = release, optimization = speed. Tests were executed on dual
15502      Intel XEON E5 2620v4 2.2GHz, 16C/32T, 64GB RAM, running Linux (x86_64).
15503    </para>
15504    <para>
15505      Measurements headed 1C/1T were run in a single-threaded process.
15506    </para>
15507    <para>
15508      The <ulink url="https://github.com/atemerev/skynet">microbenchmark <emphasis>syknet</emphasis></ulink>
15509      from Alexander Temerev was ported and used for performance measurements. At
15510      the root the test spawns 10 threads-of-execution (ToE), e.g. actor/goroutine/fiber
15511      etc.. Each spawned ToE spawns additional 10 ToEs ... until <emphasis role="bold">1,000,000</emphasis>
15512      ToEs are created. ToEs return back their ordinal numbers (0 ... 999,999), which
15513      are summed on the previous level and sent back upstream, until reaching the
15514      root. The test was run 10-20 times, producing a range of values for each measurement.
15515    </para>
15516    <table frame="all" id="fiber.performance.time_per_actor_erlang_process_goroutine__other_languages___average_over_1_000_000_">
15517      <title>time per actor/erlang process/goroutine (other languages) (average over
15518      1,000,000)</title>
15519      <tgroup cols="3">
15520        <thead>
15521          <row>
15522            <entry>
15523              <para>
15524                Haskell | stack-1.4.0/ghc-8.0.1
15525              </para>
15526            </entry>
15527            <entry>
15528              <para>
15529                Go | go1.8.1
15530              </para>
15531            </entry>
15532            <entry>
15533              <para>
15534                Erlang | erts-8.3
15535              </para>
15536            </entry>
15537          </row>
15538        </thead>
15539        <tbody>
15540          <row>
15541            <entry>
15542              <para>
15543                0.05 &#xb5;s - 0.06 &#xb5;s
15544              </para>
15545            </entry>
15546            <entry>
15547              <para>
15548                0.42 &#xb5;s - 0.49 &#xb5;s
15549              </para>
15550            </entry>
15551            <entry>
15552              <para>
15553                0.63 &#xb5;s - 0.73 &#xb5;s
15554              </para>
15555            </entry>
15556          </row>
15557        </tbody>
15558      </tgroup>
15559    </table>
15560    <para>
15561      Pthreads are created with a stack size of 8kB while <code><phrase role="identifier">std</phrase><phrase
15562      role="special">::</phrase><phrase role="identifier">thread</phrase></code>'s
15563      use the system default (1MB - 2MB). The microbenchmark could <emphasis role="bold">not</emphasis>
15564      be <emphasis role="bold">run</emphasis> with 1,000,000 threads because of
15565      <emphasis role="bold">resource exhaustion</emphasis> (pthread and std::thread).
15566      Instead the test runs only at <emphasis role="bold">10,000</emphasis> threads.
15567    </para>
15568    <table frame="all" id="fiber.performance.time_per_thread__average_over_10_000___unable_to_spawn_1_000_000_threads_">
15569      <title>time per thread (average over 10,000 - unable to spawn 1,000,000 threads)</title>
15570      <tgroup cols="3">
15571        <thead>
15572          <row>
15573            <entry>
15574              <para>
15575                pthread
15576              </para>
15577            </entry>
15578            <entry>
15579              <para>
15580                <code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase
15581                role="identifier">thread</phrase></code>
15582              </para>
15583            </entry>
15584            <entry>
15585              <para>
15586                <code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase
15587                role="identifier">async</phrase></code>
15588              </para>
15589            </entry>
15590          </row>
15591        </thead>
15592        <tbody>
15593          <row>
15594            <entry>
15595              <para>
15596                54 &#xb5;s - 73 &#xb5;s
15597              </para>
15598            </entry>
15599            <entry>
15600              <para>
15601                52 &#xb5;s - 73 &#xb5;s
15602              </para>
15603            </entry>
15604            <entry>
15605              <para>
15606                106 &#xb5;s - 122 &#xb5;s
15607              </para>
15608            </entry>
15609          </row>
15610        </tbody>
15611      </tgroup>
15612    </table>
15613    <para>
15614      The test utilizes 16 cores with Symmetric MultiThreading enabled (32 logical
15615      CPUs). The fiber stacks are allocated by <link linkend="class_fixedsize_stack"><code>fixedsize_stack</code></link>.
15616    </para>
15617    <para>
15618      As the benchmark shows, the memory allocation algorithm is significant for
15619      performance in a multithreaded environment. The tests use glibc&#8217;s memory allocation
15620      algorithm (based on ptmalloc2) as well as Google&#8217;s <ulink url="http://goog-perftools.sourceforge.net/doc/tcmalloc.html">TCmalloc</ulink>
15621      (via linkflags=&quot;-ltcmalloc&quot;).<footnote id="fiber.performance.f0">
15622      <para>
15623        Tais B. Ferreira, Rivalino Matias, Autran Macedo, Lucio B. Araujo <quote>An
15624        Experimental Study on Memory Allocators in Multicore and Multithreaded Applications</quote>,
15625        PDCAT &#8217;11 Proceedings of the 2011 12th International Conference on Parallel
15626        and Distributed Computing, Applications and Technologies, pages 92-98
15627      </para>
15628      </footnote>
15629    </para>
15630    <para>
15631      In the <link linkend="class_work_stealing"><code>work_stealing</code></link> scheduling algorithm, each thread has
15632      its own local queue. Fibers that are ready to run are pushed to and popped
15633      from the local queue. If the queue runs out of ready fibers, fibers are stolen
15634      from the local queues of other participating threads.
15635    </para>
15636    <table frame="all" id="fiber.performance.time_per_fiber__average_over_1_000_000_">
15637      <title>time per fiber (average over 1.000.000)</title>
15638      <tgroup cols="2">
15639        <thead>
15640          <row>
15641            <entry>
15642              <para>
15643                fiber (16C/32T, work stealing, tcmalloc)
15644              </para>
15645            </entry>
15646            <entry>
15647              <para>
15648                fiber (1C/1T, round robin, tcmalloc)
15649              </para>
15650            </entry>
15651          </row>
15652        </thead>
15653        <tbody>
15654          <row>
15655            <entry>
15656              <para>
15657                0.05 &#xb5;s - 0.09 &#xb5;s
15658              </para>
15659            </entry>
15660            <entry>
15661              <para>
15662                1.69 &#xb5;s - 1.79 &#xb5;s
15663              </para>
15664            </entry>
15665          </row>
15666        </tbody>
15667      </tgroup>
15668    </table>
15669  </section>
15670  <section id="fiber.tuning">
15671    <title><anchor id="tuning"/><link linkend="fiber.tuning">Tuning</link></title>
15672    <bridgehead renderas="sect3" id="fiber.tuning.h0">
15673      <phrase id="fiber.tuning.disable_synchronization"/><link linkend="fiber.tuning.disable_synchronization">Disable
15674      synchronization</link>
15675    </bridgehead>
15676    <para>
15677      With <link linkend="cross_thread_sync"><code><phrase role="identifier">BOOST_FIBERS_NO_ATOMICS</phrase></code></link>
15678      defined at the compiler&#8217;s command line, synchronization between fibers (in different
15679      threads) is disabled. This is acceptable if the application is single threaded
15680      and/or fibers are not synchronized between threads.
15681    </para>
15682    <bridgehead renderas="sect3" id="fiber.tuning.h1">
15683      <phrase id="fiber.tuning.memory_allocation"/><link linkend="fiber.tuning.memory_allocation">Memory
15684      allocation</link>
15685    </bridgehead>
15686    <para>
15687      Memory allocation algorithm is significant for performance in a multithreaded
15688      environment, especially for <emphasis role="bold">Boost.Fiber</emphasis> where
15689      fiber stacks are allocated on the heap. The default user-level memory allocator
15690      (UMA) of glibc is ptmalloc2 but it can be replaced by another UMA that fit
15691      better for the concret work-load For instance Google&#8217;s <ulink url="http://goog-perftools.sourceforge.net/doc/tcmalloc.html">TCmalloc</ulink>
15692      enables a better performance at the <emphasis>skynet</emphasis> microbenchmark
15693      than glibc&#8217;s default memory allocator.
15694    </para>
15695    <bridgehead renderas="sect3" id="fiber.tuning.h2">
15696      <phrase id="fiber.tuning.scheduling_strategies"/><link linkend="fiber.tuning.scheduling_strategies">Scheduling
15697      strategies</link>
15698    </bridgehead>
15699    <para>
15700      The fibers in a thread are coordinated by a fiber manager. Fibers trade control
15701      cooperatively, rather than preemptively. Depending on the work-load several
15702      strategies of scheduling the fibers are possible <footnote id="fiber.tuning.f0">
15703      <para>
15704        1024cores.net: <ulink url="http://www.1024cores.net/home/scalable-architecture/task-scheduling-strategies">Task
15705        Scheduling Strategies</ulink>
15706      </para>
15707      </footnote> that can be implmented on behalf of <link linkend="class_algorithm"><code>algorithm</code></link>.
15708    </para>
15709    <itemizedlist>
15710      <listitem>
15711        <simpara>
15712          work-stealing: ready fibers are hold in a local queue, when the fiber-scheduler's
15713          local queue runs out of ready fibers, it randomly selects another fiber-scheduler
15714          and tries to steal a ready fiber from the victim (implemented in <link linkend="class_work_stealing"><code>work_stealing</code></link> and
15715          <link linkend="class_numa_work_stealing"><code>numa::work_stealing</code></link>)
15716        </simpara>
15717      </listitem>
15718      <listitem>
15719        <simpara>
15720          work-requesting: ready fibers are hold in a local queue, when the fiber-scheduler's
15721          local queue runs out of ready fibers, it randomly selects another fiber-scheduler
15722          and requests for a ready fibers, the victim fiber-scheduler sends a ready-fiber
15723          back
15724        </simpara>
15725      </listitem>
15726      <listitem>
15727        <simpara>
15728          work-sharing: ready fibers are hold in a global queue, fiber-scheduler
15729          concurrently push and pop ready fibers to/from the global queue (implemented
15730          in <link linkend="class_shared_work"><code>shared_work</code></link>)
15731        </simpara>
15732      </listitem>
15733      <listitem>
15734        <simpara>
15735          work-distribution: fibers that became ready are proactivly distributed
15736          to idle fiber-schedulers or fiber-schedulers with low load
15737        </simpara>
15738      </listitem>
15739      <listitem>
15740        <simpara>
15741          work-balancing: a dedicated (helper) fiber-scheduler periodically collects
15742          informations about all fiber-scheduler running in other threads and re-distributes
15743          ready fibers among them
15744        </simpara>
15745      </listitem>
15746    </itemizedlist>
15747    <bridgehead renderas="sect3" id="fiber.tuning.h3">
15748      <phrase id="fiber.tuning.ttas_locks"/><link linkend="fiber.tuning.ttas_locks">TTAS
15749      locks</link>
15750    </bridgehead>
15751    <para>
15752      Boost.Fiber uses internally spinlocks to protect critical regions if fibers
15753      running on different threads interact. Spinlocks are implemented as TTAS (test-test-and-set)
15754      locks, i.e. the spinlock tests the lock before calling an atomic exchange.
15755      This strategy helps to reduce the cache line invalidations triggered by acquiring/releasing
15756      the lock.
15757    </para>
15758    <bridgehead renderas="sect3" id="fiber.tuning.h4">
15759      <phrase id="fiber.tuning.spin_wait_loop"/><link linkend="fiber.tuning.spin_wait_loop">Spin-wait
15760      loop</link>
15761    </bridgehead>
15762    <para>
15763      A lock is considered under contention, if a thread repeatedly fails to acquire
15764      the lock because some other thread was faster. Waiting for a short time lets
15765      other threads finish before trying to enter the critical section again. While
15766      busy waiting on the lock, relaxing the CPU (via pause/yield mnemonic) gives
15767      the CPU a hint that the code is in a spin-wait loop.
15768    </para>
15769    <itemizedlist>
15770      <listitem>
15771        <simpara>
15772          prevents expensive pipeline flushes (speculatively executed load and compare
15773          instructions are not pushed to pipeline)
15774        </simpara>
15775      </listitem>
15776      <listitem>
15777        <simpara>
15778          another hardware thread (simultaneous multithreading) can get time slice
15779        </simpara>
15780      </listitem>
15781      <listitem>
15782        <simpara>
15783          it does delay a few CPU cycles, but this is necessary to prevent starvation
15784        </simpara>
15785      </listitem>
15786    </itemizedlist>
15787    <para>
15788      It is obvious that this strategy is useless on single core systems because
15789      the lock can only released if the thread gives up its time slice in order to
15790      let other threads run. The macro BOOST_FIBERS_SPIN_SINGLE_CORE replaces the
15791      CPU hints (pause/yield mnemonic) by informing the operating system (via <code><phrase
15792      role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">this_thread_yield</phrase><phrase
15793      role="special">()</phrase></code>) that the thread gives up its time slice
15794      and the operating system switches to another thread.
15795    </para>
15796    <bridgehead renderas="sect3" id="fiber.tuning.h5">
15797      <phrase id="fiber.tuning.exponential_back_off"/><link linkend="fiber.tuning.exponential_back_off">Exponential
15798      back-off</link>
15799    </bridgehead>
15800    <para>
15801      The macro BOOST_FIBERS_RETRY_THRESHOLD determines how many times the CPU iterates
15802      in the spin-wait loop before yielding the thread or blocking in futex-wait.
15803      The spinlock tracks how many times the thread failed to acquire the lock. The
15804      higher the contention, the longer the thread should back-off. A <quote>Binary
15805      Exponential Backoff</quote> algorithm together with a randomized contention
15806      window is utilized for this purpose. BOOST_FIBERS_CONTENTION_WINDOW_THRESHOLD
15807      determines the upper limit of the contention window (expressed as the exponent
15808      for basis of two).
15809    </para>
15810    <bridgehead renderas="sect3" id="fiber.tuning.h6">
15811      <phrase id="fiber.tuning.speculative_execution__hardware_transactional_memory_"/><link
15812      linkend="fiber.tuning.speculative_execution__hardware_transactional_memory_">Speculative
15813      execution (hardware transactional memory)</link>
15814    </bridgehead>
15815    <para>
15816      Boost.Fiber uses spinlocks to protect critical regions that can be used together
15817      with transactional memory (see section <link linkend="speculation">Speculative
15818      execution</link>).
15819    </para>
15820    <note>
15821      <para>
15822        TXS is enabled if property <code><phrase role="identifier">htm</phrase><phrase
15823        role="special">=</phrase><phrase role="identifier">tsx</phrase></code> is
15824        specified at b2 command-line and <code><phrase role="identifier">BOOST_USE_TSX</phrase></code>
15825        is applied to the compiler.
15826      </para>
15827    </note>
15828    <note>
15829      <para>
15830        A TSX-transaction will be aborted if the floating point state is modified
15831        inside a critical region. As a consequence floating point operations, e.g.
15832        tore/load of floating point related registers during a fiber (context) switch
15833        are disabled.
15834      </para>
15835    </note>
15836    <bridgehead renderas="sect3" id="fiber.tuning.h7">
15837      <phrase id="fiber.tuning.numa_systems"/><link linkend="fiber.tuning.numa_systems">NUMA
15838      systems</link>
15839    </bridgehead>
15840    <para>
15841      Modern multi-socket systems are usually designed as <link linkend="numa">NUMA
15842      systems</link>. A suitable fiber scheduler like <link linkend="class_numa_work_stealing"><code>numa::work_stealing</code></link> reduces
15843      remote memory access (latence).
15844    </para>
15845    <bridgehead renderas="sect3" id="fiber.tuning.h8">
15846      <phrase id="fiber.tuning.parameters"/><link linkend="fiber.tuning.parameters">Parameters</link>
15847    </bridgehead>
15848    <table frame="all" id="fiber.tuning.parameters_that_migh_be_defiend_at_compiler_s_command_line">
15849      <title>Parameters that migh be defiend at compiler's command line</title>
15850      <tgroup cols="3">
15851        <thead>
15852          <row>
15853            <entry>
15854              <para>
15855                Parameter
15856              </para>
15857            </entry>
15858            <entry>
15859              <para>
15860                Default value
15861              </para>
15862            </entry>
15863            <entry>
15864              <para>
15865                Effect on Boost.Fiber
15866              </para>
15867            </entry>
15868          </row>
15869        </thead>
15870        <tbody>
15871          <row>
15872            <entry>
15873              <para>
15874                BOOST_FIBERS_NO_ATOMICS
15875              </para>
15876            </entry>
15877            <entry>
15878              <para>
15879                -
15880              </para>
15881            </entry>
15882            <entry>
15883              <para>
15884                no multithreading support, all atomics removed, no synchronization
15885                between fibers running in different threads
15886              </para>
15887            </entry>
15888          </row>
15889          <row>
15890            <entry>
15891              <para>
15892                BOOST_FIBERS_SPINLOCK_STD_MUTEX
15893              </para>
15894            </entry>
15895            <entry>
15896              <para>
15897                -
15898              </para>
15899            </entry>
15900            <entry>
15901              <para>
15902                <code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase
15903                role="identifier">mutex</phrase></code> used inside spinlock
15904              </para>
15905            </entry>
15906          </row>
15907          <row>
15908            <entry>
15909              <para>
15910                BOOST_FIBERS_SPINLOCK_TTAS
15911              </para>
15912            </entry>
15913            <entry>
15914              <para>
15915                +
15916              </para>
15917            </entry>
15918            <entry>
15919              <para>
15920                spinlock with test-test-and-swap on shared variable
15921              </para>
15922            </entry>
15923          </row>
15924          <row>
15925            <entry>
15926              <para>
15927                BOOST_FIBERS_SPINLOCK_TTAS_ADAPTIVE
15928              </para>
15929            </entry>
15930            <entry>
15931              <para>
15932                -
15933              </para>
15934            </entry>
15935            <entry>
15936              <para>
15937                spinlock with test-test-and-swap on shared variable, adaptive retries
15938                while busy waiting
15939              </para>
15940            </entry>
15941          </row>
15942          <row>
15943            <entry>
15944              <para>
15945                BOOST_FIBERS_SPINLOCK_TTAS_FUTEX
15946              </para>
15947            </entry>
15948            <entry>
15949              <para>
15950                -
15951              </para>
15952            </entry>
15953            <entry>
15954              <para>
15955                spinlock with test-test-and-swap on shared variable, suspend on futex
15956                after certain number of retries
15957              </para>
15958            </entry>
15959          </row>
15960          <row>
15961            <entry>
15962              <para>
15963                BOOST_FIBERS_SPINLOCK_TTAS_ADAPTIVE_FUTEX
15964              </para>
15965            </entry>
15966            <entry>
15967              <para>
15968                -
15969              </para>
15970            </entry>
15971            <entry>
15972              <para>
15973                spinlock with test-test-and-swap on shared variable, while busy waiting
15974                adaptive retries, suspend on futex certain amount of retries
15975              </para>
15976            </entry>
15977          </row>
15978          <row>
15979            <entry>
15980              <para>
15981                BOOST_FIBERS_SPINLOCK_TTAS + BOOST_USE_TSX
15982              </para>
15983            </entry>
15984            <entry>
15985              <para>
15986                -
15987              </para>
15988            </entry>
15989            <entry>
15990              <para>
15991                spinlock with test-test-and-swap and speculative execution (Intel
15992                TSX required)
15993              </para>
15994            </entry>
15995          </row>
15996          <row>
15997            <entry>
15998              <para>
15999                BOOST_FIBERS_SPINLOCK_TTAS_ADAPTIVE + BOOST_USE_TSX
16000              </para>
16001            </entry>
16002            <entry>
16003              <para>
16004                -
16005              </para>
16006            </entry>
16007            <entry>
16008              <para>
16009                spinlock with test-test-and-swap on shared variable, adaptive retries
16010                while busy waiting and speculative execution (Intel TSX required)
16011              </para>
16012            </entry>
16013          </row>
16014          <row>
16015            <entry>
16016              <para>
16017                BOOST_FIBERS_SPINLOCK_TTAS_FUTEX + BOOST_USE_TSX
16018              </para>
16019            </entry>
16020            <entry>
16021              <para>
16022                -
16023              </para>
16024            </entry>
16025            <entry>
16026              <para>
16027                spinlock with test-test-and-swap on shared variable, suspend on futex
16028                after certain number of retries and speculative execution (Intel
16029                TSX required)
16030              </para>
16031            </entry>
16032          </row>
16033          <row>
16034            <entry>
16035              <para>
16036                BOOST_FIBERS_SPINLOCK_TTAS_ADAPTIVE_FUTEX + BOOST_USE_TSX
16037              </para>
16038            </entry>
16039            <entry>
16040              <para>
16041                -
16042              </para>
16043            </entry>
16044            <entry>
16045              <para>
16046                spinlock with test-test-and-swap on shared variable, while busy waiting
16047                adaptive retries, suspend on futex certain amount of retries and
16048                speculative execution (Intel TSX required)
16049              </para>
16050            </entry>
16051          </row>
16052          <row>
16053            <entry>
16054              <para>
16055                BOOST_FIBERS_SPIN_SINGLE_CORE
16056              </para>
16057            </entry>
16058            <entry>
16059              <para>
16060                -
16061              </para>
16062            </entry>
16063            <entry>
16064              <para>
16065                on single core machines with multiple threads, yield thread (<code><phrase
16066                role="identifier">std</phrase><phrase role="special">::</phrase><phrase
16067                role="identifier">this_thread</phrase><phrase role="special">::</phrase><phrase
16068                role="identifier">yield</phrase><phrase role="special">()</phrase></code>)
16069                after collisions
16070              </para>
16071            </entry>
16072          </row>
16073          <row>
16074            <entry>
16075              <para>
16076                BOOST_FIBERS_RETRY_THRESHOLD
16077              </para>
16078            </entry>
16079            <entry>
16080              <para>
16081                64
16082              </para>
16083            </entry>
16084            <entry>
16085              <para>
16086                max number of retries while busy spinning, the use fallback
16087              </para>
16088            </entry>
16089          </row>
16090          <row>
16091            <entry>
16092              <para>
16093                BOOST_FIBERS_CONTENTION_WINDOW_THRESHOLD
16094              </para>
16095            </entry>
16096            <entry>
16097              <para>
16098                16
16099              </para>
16100            </entry>
16101            <entry>
16102              <para>
16103                max size of collisions window, expressed as exponent for the basis
16104                of two
16105              </para>
16106            </entry>
16107          </row>
16108          <row>
16109            <entry>
16110              <para>
16111                BOOST_FIBERS_SPIN_BEFORE_SLEEP0
16112              </para>
16113            </entry>
16114            <entry>
16115              <para>
16116                32
16117              </para>
16118            </entry>
16119            <entry>
16120              <para>
16121                max number of retries that relax the processor before the thread
16122                sleeps for 0s
16123              </para>
16124            </entry>
16125          </row>
16126          <row>
16127            <entry>
16128              <para>
16129                BOOST_FIBERS_SPIN_BEFORE_YIELD
16130              </para>
16131            </entry>
16132            <entry>
16133              <para>
16134                64
16135              </para>
16136            </entry>
16137            <entry>
16138              <para>
16139                max number of retries where the thread sleeps for 0s before yield
16140                thread (<code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase
16141                role="identifier">this_thread</phrase><phrase role="special">::</phrase><phrase
16142                role="identifier">yield</phrase><phrase role="special">()</phrase></code>)
16143              </para>
16144            </entry>
16145          </row>
16146        </tbody>
16147      </tgroup>
16148    </table>
16149  </section>
16150  <section id="fiber.custom">
16151    <title><anchor id="custom"/><link linkend="fiber.custom">Customization</link></title>
16152    <bridgehead renderas="sect3" id="fiber.custom.h0">
16153      <phrase id="fiber.custom.overview"/><link linkend="fiber.custom.overview">Overview</link>
16154    </bridgehead>
16155    <para>
16156      As noted in the <link linkend="scheduling">Scheduling</link> section, by default
16157      <emphasis role="bold">Boost.Fiber</emphasis> uses its own <link linkend="class_round_robin"><code>round_robin</code></link> scheduler
16158      for each thread. To control the way <emphasis role="bold">Boost.Fiber</emphasis>
16159      schedules ready fibers on a particular thread, in general you must follow several
16160      steps. This section discusses those steps, whereas <link linkend="scheduling">Scheduling</link>
16161      serves as a reference for the classes involved.
16162    </para>
16163    <para>
16164      The library's fiber manager keeps track of suspended (blocked) fibers. Only
16165      when a fiber becomes ready to run is it passed to the scheduler. Of course,
16166      if there are fewer than two ready fibers, the scheduler's job is trivial. Only
16167      when there are two or more ready fibers does the particular scheduler implementation
16168      start to influence the overall sequence of fiber execution.
16169    </para>
16170    <para>
16171      In this section we illustrate a simple custom scheduler that honors an integer
16172      fiber priority. We will implement it such that a fiber with higher priority
16173      is preferred over a fiber with lower priority. Any fibers with equal priority
16174      values are serviced on a round-robin basis.
16175    </para>
16176    <para>
16177      The full source code for the examples below is found in <ulink url="../../examples/priority.cpp">priority.cpp</ulink>.
16178    </para>
16179    <bridgehead renderas="sect3" id="fiber.custom.h1">
16180      <phrase id="fiber.custom.custom_property_class"/><link linkend="fiber.custom.custom_property_class">Custom
16181      Property Class</link>
16182    </bridgehead>
16183    <para>
16184      The first essential point is that we must associate an integer priority with
16185      each fiber.<footnote id="fiber.custom.f0">
16186      <para>
16187        A previous version of the Fiber library implicitly tracked an int priority
16188        for each fiber, even though the default scheduler ignored it. This has been
16189        dropped, since the library now supports arbitrary scheduler-specific fiber
16190        properties.
16191      </para>
16192      </footnote>
16193    </para>
16194    <para>
16195      One might suggest deriving a custom <link linkend="class_fiber"><code>fiber</code></link> subclass to store such
16196      properties. There are a couple of reasons for the present mechanism.
16197    </para>
16198    <orderedlist>
16199      <listitem>
16200        <simpara>
16201          <emphasis role="bold">Boost.Fiber</emphasis> provides a number of different
16202          ways to launch a fiber. (Consider <link linkend="fibers_async"><code>fibers::async()</code></link>.) Higher-level
16203          libraries might introduce additional such wrapper functions. A custom scheduler
16204          must associate its custom properties with <emphasis>every</emphasis> fiber
16205          in the thread, not only the ones explicitly launched by instantiating a
16206          custom <code><phrase role="identifier">fiber</phrase></code> subclass.
16207        </simpara>
16208      </listitem>
16209      <listitem>
16210        <simpara>
16211          Consider a large existing program that launches fibers in many different
16212          places in the code. We discover a need to introduce a custom scheduler
16213          for a particular thread. If supporting that scheduler's custom properties
16214          required a particular <code><phrase role="identifier">fiber</phrase></code>
16215          subclass, we would have to hunt down and modify every place that launches
16216          a fiber on that thread.
16217        </simpara>
16218      </listitem>
16219      <listitem>
16220        <simpara>
16221          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.
16222          A subclass of <code><phrase role="identifier">fiber</phrase></code> would
16223          not add data to <code><phrase role="identifier">context</phrase></code>.
16224        </simpara>
16225      </listitem>
16226    </orderedlist>
16227    <para>
16228      The present mechanism allows you to <quote>drop in</quote> a custom scheduler
16229      with its attendant custom properties <emphasis>without</emphasis> altering
16230      the rest of your application.
16231    </para>
16232    <para>
16233      Instead of deriving a custom scheduler fiber properties subclass from <link linkend="class_fiber"><code>fiber</code></link>,
16234      you must instead derive it from <link linkend="class_fiber_properties"><code>fiber_properties</code></link>.
16235    </para>
16236    <para>
16237<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>
16238<phrase role="keyword">public</phrase><phrase role="special">:</phrase>
16239    <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>
16240        <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" />
16241        <phrase role="identifier">priority_</phrase><phrase role="special">(</phrase> <phrase role="number">0</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
16242    <phrase role="special">}</phrase>
16243
16244    <phrase role="keyword">int</phrase> <phrase role="identifier">get_priority</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase> <phrase role="special">{</phrase>
16245        <phrase role="keyword">return</phrase> <phrase role="identifier">priority_</phrase><phrase role="special">;</phrase> <co id="fiber.custom.c2" linkends="fiber.custom.c3" />
16246    <phrase role="special">}</phrase>
16247
16248    <phrase role="comment">// Call this method to alter priority, because we must notify</phrase>
16249    <phrase role="comment">// priority_scheduler of any change.</phrase>
16250    <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" />
16251        <phrase role="comment">// Of course, it's only worth reshuffling the queue and all if we're</phrase>
16252        <phrase role="comment">// actually changing the priority.</phrase>
16253        <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>
16254            <phrase role="identifier">priority_</phrase> <phrase role="special">=</phrase> <phrase role="identifier">p</phrase><phrase role="special">;</phrase>
16255            <phrase role="identifier">notify</phrase><phrase role="special">();</phrase>
16256        <phrase role="special">}</phrase>
16257    <phrase role="special">}</phrase>
16258
16259    <phrase role="comment">// The fiber name of course is solely for purposes of this example</phrase>
16260    <phrase role="comment">// program; it has nothing to do with implementing scheduler priority.</phrase>
16261    <phrase role="comment">// This is a public data member -- not requiring set/get access methods --</phrase>
16262    <phrase role="comment">// because we need not inform the scheduler of any change.</phrase>
16263    <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" />
16264<phrase role="keyword">private</phrase><phrase role="special">:</phrase>
16265    <phrase role="keyword">int</phrase> <phrase role="identifier">priority_</phrase><phrase role="special">;</phrase>
16266<phrase role="special">};</phrase>
16267</programlisting>
16268    </para>
16269    <calloutlist>
16270      <callout arearefs="fiber.custom.c0" id="fiber.custom.c1">
16271        <para>
16272          Your subclass constructor must accept a <literal><link linkend="class_context"><code>context</code></link>*</literal>
16273          and pass it to the <code><phrase role="identifier">fiber_properties</phrase></code>
16274          constructor.
16275        </para>
16276      </callout>
16277      <callout arearefs="fiber.custom.c2" id="fiber.custom.c3">
16278        <para>
16279          Provide read access methods at your own discretion.
16280        </para>
16281      </callout>
16282      <callout arearefs="fiber.custom.c4" id="fiber.custom.c5">
16283        <para>
16284          It's important to call <code><phrase role="identifier">notify</phrase><phrase
16285          role="special">()</phrase></code> on any change in a property that can
16286          affect the scheduler's behavior. Therefore, such modifications should only
16287          be performed through an access method.
16288        </para>
16289      </callout>
16290      <callout arearefs="fiber.custom.c6" id="fiber.custom.c7">
16291        <para>
16292          A property that does not affect the scheduler does not need access methods.
16293        </para>
16294      </callout>
16295    </calloutlist>
16296    <bridgehead renderas="sect3" id="fiber.custom.h2">
16297      <phrase id="fiber.custom.custom_scheduler_class"/><link linkend="fiber.custom.custom_scheduler_class">Custom
16298      Scheduler Class</link>
16299    </bridgehead>
16300    <para>
16301      Now we can derive a custom scheduler from <link linkend="class_algorithm_with_properties"><code>algorithm_with_properties&lt;&gt;</code></link>,
16302      specifying our custom property class <code><phrase role="identifier">priority_props</phrase></code>
16303      as the template parameter.
16304    </para>
16305    <para>
16306<programlisting><phrase role="keyword">class</phrase> <phrase role="identifier">priority_scheduler</phrase> <phrase role="special">:</phrase>
16307    <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>
16308<phrase role="keyword">private</phrase><phrase role="special">:</phrase>
16309    <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>
16310
16311    <phrase role="identifier">rqueue_t</phrase>                                <phrase role="identifier">rqueue_</phrase><phrase role="special">;</phrase>
16312    <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">mutex</phrase>                  <phrase role="identifier">mtx_</phrase><phrase role="special">{};</phrase>
16313    <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">condition_variable</phrase>     <phrase role="identifier">cnd_</phrase><phrase role="special">{};</phrase>
16314    <phrase role="keyword">bool</phrase>                        <phrase role="identifier">flag_</phrase><phrase role="special">{</phrase> <phrase role="keyword">false</phrase> <phrase role="special">};</phrase>
16315
16316<phrase role="keyword">public</phrase><phrase role="special">:</phrase>
16317    <phrase role="identifier">priority_scheduler</phrase><phrase role="special">()</phrase> <phrase role="special">:</phrase>
16318        <phrase role="identifier">rqueue_</phrase><phrase role="special">()</phrase> <phrase role="special">{</phrase>
16319    <phrase role="special">}</phrase>
16320
16321    <phrase role="comment">// For a subclass of algorithm_with_properties&lt;&gt;, it's important to</phrase>
16322    <phrase role="comment">// override the correct awakened() overload.</phrase>
16323    <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>
16324        <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" />
16325        <phrase role="comment">// With this scheduler, fibers with higher priority values are</phrase>
16326        <phrase role="comment">// preferred over fibers with lower priority values. But fibers with</phrase>
16327        <phrase role="comment">// equal priority values are processed in round-robin fashion. So when</phrase>
16328        <phrase role="comment">// we're handed a new context*, put it at the end of the fibers</phrase>
16329        <phrase role="comment">// with that same priority. In other words: search for the first fiber</phrase>
16330        <phrase role="comment">// in the queue with LOWER priority, and insert before that one.</phrase>
16331        <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>
16332            <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>
16333            <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>
16334        <phrase role="comment">// Now, whether or not we found a fiber with lower priority,</phrase>
16335        <phrase role="comment">// insert this new fiber here.</phrase>
16336        <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>
16337    <phrase role="special">}</phrase>
16338
16339    <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>
16340        <phrase role="comment">// if ready queue is empty, just tell caller</phrase>
16341        <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>
16342            <phrase role="keyword">return</phrase> <phrase role="keyword">nullptr</phrase><phrase role="special">;</phrase>
16343        <phrase role="special">}</phrase>
16344        <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>
16345        <phrase role="identifier">rqueue_</phrase><phrase role="special">.</phrase><phrase role="identifier">pop_front</phrase><phrase role="special">();</phrase>
16346        <phrase role="keyword">return</phrase> <phrase role="identifier">ctx</phrase><phrase role="special">;</phrase>
16347    <phrase role="special">}</phrase>
16348
16349    <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>
16350        <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>
16351    <phrase role="special">}</phrase>
16352
16353    <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>
16354        <phrase role="comment">// Although our priority_props class defines multiple properties, only</phrase>
16355        <phrase role="comment">// one of them (priority) actually calls notify() when changed. The</phrase>
16356        <phrase role="comment">// point of a property_change() override is to reshuffle the ready</phrase>
16357        <phrase role="comment">// queue according to the updated priority value.</phrase>
16358
16359        <phrase role="comment">// 'ctx' might not be in our queue at all, if caller is changing the</phrase>
16360        <phrase role="comment">// priority of (say) the running fiber. If it's not there, no need to</phrase>
16361        <phrase role="comment">// move it: we'll handle it next time it hits awakened().</phrase>
16362        <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" />
16363            <phrase role="keyword">return</phrase><phrase role="special">;</phrase>
16364        <phrase role="special">}</phrase>
16365
16366        <phrase role="comment">// Found ctx: unlink it</phrase>
16367        <phrase role="identifier">ctx</phrase><phrase role="special">-&gt;</phrase><phrase role="identifier">ready_unlink</phrase><phrase role="special">();</phrase>
16368
16369        <phrase role="comment">// Here we know that ctx was in our ready queue, but we've unlinked</phrase>
16370        <phrase role="comment">// it. We happen to have a method that will (re-)add a context* to the</phrase>
16371        <phrase role="comment">// right place in the ready queue.</phrase>
16372        <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>
16373    <phrase role="special">}</phrase>
16374
16375    <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>
16376        <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>
16377            <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>
16378            <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>
16379            <phrase role="identifier">flag_</phrase> <phrase role="special">=</phrase> <phrase role="keyword">false</phrase><phrase role="special">;</phrase>
16380        <phrase role="special">}</phrase> <phrase role="keyword">else</phrase> <phrase role="special">{</phrase>
16381            <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>
16382            <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>
16383            <phrase role="identifier">flag_</phrase> <phrase role="special">=</phrase> <phrase role="keyword">false</phrase><phrase role="special">;</phrase>
16384        <phrase role="special">}</phrase>
16385    <phrase role="special">}</phrase>
16386
16387    <phrase role="keyword">void</phrase> <phrase role="identifier">notify</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase> <phrase role="special">{</phrase>
16388        <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>
16389        <phrase role="identifier">flag_</phrase> <phrase role="special">=</phrase> <phrase role="keyword">true</phrase><phrase role="special">;</phrase>
16390        <phrase role="identifier">lk</phrase><phrase role="special">.</phrase><phrase role="identifier">unlock</phrase><phrase role="special">();</phrase>
16391        <phrase role="identifier">cnd_</phrase><phrase role="special">.</phrase><phrase role="identifier">notify_all</phrase><phrase role="special">();</phrase>
16392    <phrase role="special">}</phrase>
16393<phrase role="special">};</phrase>
16394</programlisting>
16395    </para>
16396    <calloutlist>
16397      <callout arearefs="fiber.custom.c8" id="fiber.custom.c9">
16398        <para>
16399          See <link linkend="ready_queue_t">ready_queue_t</link>.
16400        </para>
16401      </callout>
16402      <callout arearefs="fiber.custom.c10" id="fiber.custom.c11">
16403        <para>
16404          You must override the <link linkend="algorithm_with_properties_awakened"><code>algorithm_with_properties::awakened()</code></link>
16405         method.
16406          This is how your scheduler receives notification of a fiber that has become
16407          ready to run.
16408        </para>
16409      </callout>
16410      <callout arearefs="fiber.custom.c12" id="fiber.custom.c13">
16411        <para>
16412          <code><phrase role="identifier">props</phrase></code> is the instance of
16413          priority_props associated with the passed fiber <code><phrase role="identifier">ctx</phrase></code>.
16414        </para>
16415      </callout>
16416      <callout arearefs="fiber.custom.c14" id="fiber.custom.c15">
16417        <para>
16418          You must override the <link linkend="algorithm_with_properties_pick_next"><code>algorithm_with_properties::pick_next()</code></link>
16419         method.
16420          This is how your scheduler actually advises the fiber manager of the next
16421          fiber to run.
16422        </para>
16423      </callout>
16424      <callout arearefs="fiber.custom.c16" id="fiber.custom.c17">
16425        <para>
16426          You must override <link linkend="algorithm_with_properties_has_ready_fibers"><code>algorithm_with_properties::has_ready_fibers()</code></link>
16427      to
16428          inform the fiber manager of the state of your ready queue.
16429        </para>
16430      </callout>
16431      <callout arearefs="fiber.custom.c18" id="fiber.custom.c19">
16432        <para>
16433          Overriding <link linkend="algorithm_with_properties_property_change"><code>algorithm_with_properties::property_change()</code></link>
16434         is
16435          optional. This override handles the case in which the running fiber changes
16436          the priority of another ready fiber: a fiber already in our queue. In that
16437          case, move the updated fiber within the queue.
16438        </para>
16439      </callout>
16440      <callout arearefs="fiber.custom.c20" id="fiber.custom.c21">
16441        <para>
16442          Your <code><phrase role="identifier">property_change</phrase><phrase role="special">()</phrase></code>
16443          override must be able to handle the case in which the passed <code><phrase
16444          role="identifier">ctx</phrase></code> is not in your ready queue. It might
16445          be running, or it might be blocked.
16446        </para>
16447      </callout>
16448    </calloutlist>
16449    <para>
16450      Our example <code><phrase role="identifier">priority_scheduler</phrase></code>
16451      doesn't override <link linkend="algorithm_with_properties_new_properties"><code>algorithm_with_properties::new_properties()</code></link>:
16452      we're content with allocating <code><phrase role="identifier">priority_props</phrase></code>
16453      instances on the heap.
16454    </para>
16455    <bridgehead renderas="sect3" id="fiber.custom.h3">
16456      <phrase id="fiber.custom.replace_default_scheduler"/><link linkend="fiber.custom.replace_default_scheduler">Replace
16457      Default Scheduler</link>
16458    </bridgehead>
16459    <para>
16460      You must call <link linkend="use_scheduling_algorithm"><code>use_scheduling_algorithm()</code></link> at the start
16461      of each thread on which you want <emphasis role="bold">Boost.Fiber</emphasis>
16462      to use your custom scheduler rather than its own default <link linkend="class_round_robin"><code>round_robin</code></link>.
16463      Specifically, you must call <code><phrase role="identifier">use_scheduling_algorithm</phrase><phrase
16464      role="special">()</phrase></code> before performing any other <emphasis role="bold">Boost.Fiber</emphasis>
16465      operations on that thread.
16466    </para>
16467    <para>
16468<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>
16469    <phrase role="comment">// make sure we use our priority_scheduler rather than default round_robin</phrase>
16470    <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>
16471    <phrase role="special">...</phrase>
16472<phrase role="special">}</phrase>
16473</programlisting>
16474    </para>
16475    <bridgehead renderas="sect3" id="fiber.custom.h4">
16476      <phrase id="fiber.custom.use_properties"/><link linkend="fiber.custom.use_properties">Use
16477      Properties</link>
16478    </bridgehead>
16479    <para>
16480      The running fiber can access its own <link linkend="class_fiber_properties"><code>fiber_properties</code></link> subclass
16481      instance by calling <link linkend="this_fiber_properties"><code>this_fiber::properties()</code></link>. Although
16482      <code><phrase role="identifier">properties</phrase><phrase role="special">&lt;&gt;()</phrase></code>
16483      is a nullary function, you must pass, as a template parameter, the <code><phrase
16484      role="identifier">fiber_properties</phrase></code> subclass.
16485    </para>
16486    <para>
16487<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>
16488</programlisting>
16489    </para>
16490    <para>
16491      Given a <link linkend="class_fiber"><code>fiber</code></link> instance still connected with a running fiber (that
16492      is, not <link linkend="fiber_detach"><code>fiber::detach()</code></link>ed), you may access that fiber's properties
16493      using <link linkend="fiber_properties"><code>fiber::properties()</code></link>. As with <code><phrase role="identifier">boost</phrase><phrase
16494      role="special">::</phrase><phrase role="identifier">this_fiber</phrase><phrase
16495      role="special">::</phrase><phrase role="identifier">properties</phrase><phrase
16496      role="special">&lt;&gt;()</phrase></code>, you must pass your <code><phrase
16497      role="identifier">fiber_properties</phrase></code> subclass as the template
16498      parameter.
16499    </para>
16500    <para>
16501<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>
16502<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>
16503    <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>
16504    <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>
16505    <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>
16506    <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>
16507    <phrase role="keyword">return</phrase> <phrase role="identifier">fiber</phrase><phrase role="special">;</phrase>
16508<phrase role="special">}</phrase>
16509</programlisting>
16510    </para>
16511    <para>
16512      Launching a new fiber schedules that fiber as ready, but does <emphasis>not</emphasis>
16513      immediately enter its <emphasis>fiber-function</emphasis>. The current fiber
16514      retains control until it blocks (or yields, or terminates) for some other reason.
16515      As shown in the <code><phrase role="identifier">launch</phrase><phrase role="special">()</phrase></code>
16516      function above, it is reasonable to launch a fiber and immediately set relevant
16517      properties -- such as, for instance, its priority. Your custom scheduler can
16518      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>.
16519    </para>
16520  </section>
16521  <section id="fiber.rationale">
16522    <title><link linkend="fiber.rationale">Rationale</link></title>
16523    <bridgehead renderas="sect3" id="fiber.rationale.h0">
16524      <phrase id="fiber.rationale.preprocessor_defines"/><link linkend="fiber.rationale.preprocessor_defines">preprocessor
16525      defines</link>
16526    </bridgehead>
16527    <table frame="all" id="fiber.rationale.preopcessor_defines">
16528      <title>preopcessor defines</title>
16529      <tgroup cols="2">
16530        <thead>
16531          <row>
16532            <entry>
16533            </entry>
16534            <entry>
16535            </entry>
16536          </row>
16537        </thead>
16538        <tbody>
16539          <row>
16540            <entry>
16541              <para>
16542                BOOST_FIBERS_NO_ATOMICS
16543              </para>
16544            </entry>
16545            <entry>
16546              <para>
16547                no <code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase
16548                role="identifier">atomic</phrase><phrase role="special">&lt;&gt;</phrase></code>
16549                used, inter-thread synchronization disabled
16550              </para>
16551            </entry>
16552          </row>
16553          <row>
16554            <entry>
16555              <para>
16556                BOOST_FIBERS_SPINLOCK_STD_MUTEX
16557              </para>
16558            </entry>
16559            <entry>
16560              <para>
16561                use <code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase
16562                role="identifier">mutex</phrase></code> as spinlock instead of default
16563                <code><phrase role="identifier">XCHG</phrase></code>-sinlock with
16564                backoff
16565              </para>
16566            </entry>
16567          </row>
16568          <row>
16569            <entry>
16570              <para>
16571                BOOST_FIBERS_SPIN_BACKOFF
16572              </para>
16573            </entry>
16574            <entry>
16575              <para>
16576                limit determines when to used <code><phrase role="identifier">std</phrase><phrase
16577                role="special">::</phrase><phrase role="identifier">this_thread</phrase><phrase
16578                role="special">::</phrase><phrase role="identifier">yield</phrase><phrase
16579                role="special">()</phrase></code> instead of mnemonic <code><phrase
16580                role="identifier">pause</phrase><phrase role="special">/</phrase><phrase
16581                role="identifier">yield</phrase></code> during busy wait (apllies
16582                on to <code><phrase role="identifier">XCHG</phrase></code>-spinlock)
16583              </para>
16584            </entry>
16585          </row>
16586          <row>
16587            <entry>
16588              <para>
16589                BOOST_FIBERS_SINGLE_CORE
16590              </para>
16591            </entry>
16592            <entry>
16593              <para>
16594                allways call <code><phrase role="identifier">std</phrase><phrase
16595                role="special">::</phrase><phrase role="identifier">this_thread</phrase><phrase
16596                role="special">::</phrase><phrase role="identifier">yield</phrase><phrase
16597                role="special">()</phrase></code> without backoff during busy wait
16598                (apllies on to <code><phrase role="identifier">XCHG</phrase></code>-spinlock)
16599              </para>
16600            </entry>
16601          </row>
16602        </tbody>
16603      </tgroup>
16604    </table>
16605    <bridgehead renderas="sect3" id="fiber.rationale.h1">
16606      <phrase id="fiber.rationale.distinction_between_coroutines_and_fibers"/><link
16607      linkend="fiber.rationale.distinction_between_coroutines_and_fibers">distinction
16608      between coroutines and fibers</link>
16609    </bridgehead>
16610    <para>
16611      The fiber library extends the coroutine library by adding a scheduler and synchronization
16612      mechanisms.
16613    </para>
16614    <itemizedlist>
16615      <listitem>
16616        <simpara>
16617          a coroutine yields
16618        </simpara>
16619      </listitem>
16620      <listitem>
16621        <simpara>
16622          a fiber blocks
16623        </simpara>
16624      </listitem>
16625    </itemizedlist>
16626    <para>
16627      When a coroutine yields, it passes control directly to its caller (or, in the
16628      case of symmetric coroutines, a designated other coroutine). When a fiber blocks,
16629      it implicitly passes control to the fiber scheduler. Coroutines have no scheduler
16630      because they need no scheduler.<footnote id="fiber.rationale.f0">
16631      <para>
16632        <ulink url="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4024.pdf">'N4024:
16633        Distinguishing coroutines and fibers'</ulink>
16634      </para>
16635      </footnote>.
16636    </para>
16637    <bridgehead renderas="sect3" id="fiber.rationale.h2">
16638      <phrase id="fiber.rationale.what_about_transactional_memory"/><link linkend="fiber.rationale.what_about_transactional_memory">what
16639      about transactional memory</link>
16640    </bridgehead>
16641    <para>
16642      GCC supports transactional memory since version 4.7. Unfortunately tests show
16643      that transactional memory is slower (ca. 4x) than spinlocks using atomics.
16644      Once transactional memory is improved (supporting hybrid tm), spinlocks will
16645      be replaced by __transaction_atomic{} statements surrounding the critical sections.
16646    </para>
16647    <bridgehead renderas="sect3" id="fiber.rationale.h3">
16648      <phrase id="fiber.rationale.synchronization_between_fibers_running_in_different_threads"/><link
16649      linkend="fiber.rationale.synchronization_between_fibers_running_in_different_threads">synchronization
16650      between fibers running in different threads</link>
16651    </bridgehead>
16652    <para>
16653      Synchronization classes from <ulink url="http://www.boost.org/doc/libs/release/libs/thread/index.html">Boost.Thread</ulink>
16654      block the entire thread. In contrast, the synchronization classes from <emphasis
16655      role="bold">Boost.Fiber</emphasis> block only specific fibers, so that the
16656      scheduler can still keep the thread busy running other fibers in the meantime.
16657      The synchronization classes from <emphasis role="bold">Boost.Fiber</emphasis>
16658      are designed to be thread-safe, i.e. it is possible to synchronize fibers running
16659      in different threads as well as fibers running in the same thread. (However,
16660      there is a build option to disable cross-thread fiber synchronization support;
16661      see <link linkend="cross_thread_sync">this description</link>.)
16662    </para>
16663    <anchor id="spurious_wakeup"/>
16664    <bridgehead renderas="sect3" id="fiber.rationale.h4">
16665      <phrase id="fiber.rationale.spurious_wakeup"/><link linkend="fiber.rationale.spurious_wakeup">spurious
16666      wakeup</link>
16667    </bridgehead>
16668    <para>
16669      Spurious wakeup can happen when using <ulink url="http://en.cppreference.com/w/cpp/thread/condition_variable"><code><phrase
16670      role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">condition_variable</phrase></code></ulink>:
16671      the condition variable appears to be have been signaled while the awaited condition
16672      may still be false. Spurious wakeup can happen repeatedly and is caused on
16673      some multiprocessor systems where making <code><phrase role="identifier">std</phrase><phrase
16674      role="special">::</phrase><phrase role="identifier">condition_variable</phrase></code>
16675      wakeup completely predictable would slow down all <code><phrase role="identifier">std</phrase><phrase
16676      role="special">::</phrase><phrase role="identifier">condition_variable</phrase></code>
16677      operations.<footnote id="fiber.rationale.f1">
16678      <para>
16679        David R. Butenhof <quote>Programming with POSIX Threads</quote>
16680      </para>
16681      </footnote>
16682    </para>
16683    <para>
16684      <link linkend="class_condition_variable"><code>condition_variable</code></link> is not subject to spurious wakeup.
16685      Nonetheless it is prudent to test the business-logic condition in a <code><phrase
16686      role="identifier">wait</phrase><phrase role="special">()</phrase></code> loop
16687      &mdash; or, equivalently, use one of the <code><phrase role="identifier">wait</phrase><phrase
16688      role="special">(</phrase> <phrase role="identifier">lock</phrase><phrase role="special">,</phrase>
16689      <phrase role="identifier">predicate</phrase> <phrase role="special">)</phrase></code>
16690      overloads.
16691    </para>
16692    <para>
16693      See also <link linkend="condition_variable_spurious_wakeups">No Spurious Wakeups</link>.
16694    </para>
16695    <bridgehead renderas="sect3" id="fiber.rationale.h5">
16696      <phrase id="fiber.rationale.migrating_fibers_between_threads"/><link linkend="fiber.rationale.migrating_fibers_between_threads">migrating
16697      fibers between threads</link>
16698    </bridgehead>
16699    <para>
16700      Support for migrating fibers between threads has been integrated. The user-defined
16701      scheduler must call <link linkend="context_detach"><code>context::detach()</code></link> on a fiber-context on the
16702      source thread and <link linkend="context_attach"><code>context::attach()</code></link> on the destination thread,
16703      passing the fiber-context to migrate. (For more information about custom schedulers,
16704      see <link linkend="custom">Customization</link>.) Examples <code><phrase role="identifier">work_sharing</phrase></code>
16705      and <code><phrase role="identifier">work_stealing</phrase></code> in directory
16706      <code><phrase role="identifier">examples</phrase></code> might be used as a
16707      blueprint.
16708    </para>
16709    <para>
16710      See also <link linkend="migration">Migrating fibers between threads</link>.
16711    </para>
16712    <bridgehead renderas="sect3" id="fiber.rationale.h6">
16713      <phrase id="fiber.rationale.support_for_boost_asio"/><link linkend="fiber.rationale.support_for_boost_asio">support
16714      for Boost.Asio</link>
16715    </bridgehead>
16716    <para>
16717      Support for <ulink url="http://www.boost.org/doc/libs/release/libs/asio/index.html">Boost.Asio</ulink>&#8217;s
16718      <emphasis>async-result</emphasis> is not part of the official API. However,
16719      to integrate with a <ulink url="http://www.boost.org/doc/libs/release/doc/html/boost_asio/reference/io_service.html"><code><phrase
16720      role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">asio</phrase><phrase
16721      role="special">::</phrase><phrase role="identifier">io_service</phrase></code></ulink>,
16722      see <link linkend="integration">Sharing a Thread with Another Main Loop</link>.
16723      To interface smoothly with an arbitrary Asio async I/O operation, see <link
16724      linkend="callbacks_asio">Then There&#8217;s <ulink url="http://www.boost.org/doc/libs/release/libs/asio/index.html">Boost.Asio</ulink></link>.
16725    </para>
16726    <bridgehead renderas="sect3" id="fiber.rationale.h7">
16727      <phrase id="fiber.rationale.tested_compilers"/><link linkend="fiber.rationale.tested_compilers">tested
16728      compilers</link>
16729    </bridgehead>
16730    <para>
16731      The library was tested with GCC-5.1.1, Clang-3.6.0 and MSVC-14.0 in c++11-mode.
16732    </para>
16733    <bridgehead renderas="sect3" id="fiber.rationale.h8">
16734      <phrase id="fiber.rationale.supported_architectures"/><link linkend="fiber.rationale.supported_architectures">supported
16735      architectures</link>
16736    </bridgehead>
16737    <para>
16738      <emphasis role="bold">Boost.Fiber</emphasis> depends on <ulink url="http://www.boost.org/doc/libs/release/libs/context/index.html">Boost.Context</ulink>
16739      - 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>.
16740    </para>
16741  </section>
16742  <section id="fiber.acknowledgements">
16743    <title><link linkend="fiber.acknowledgements">Acknowledgments</link></title>
16744    <para>
16745      I'd like to thank Agustín Bergé, Eugene Yakubovich, Giovanni Piero Deretta
16746      and especially Nat Goodspeed.
16747    </para>
16748  </section>
16749</library>
16750