]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/fiber/doc/fibers.xml
bump version to 12.2.2-pve1
[ceph.git] / ceph / src / boost / libs / fiber / doc / fibers.xml
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: 2016/05/22 05:16:53 $"
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/econtext.html"><emphasis>execution_context</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 A fiber launched on a particular thread continues running on that thread unless
108 migrated. It might be unblocked (see <link linkend="blocking">Blocking</link>
109 below) by some other thread, but that only transitions the fiber from <quote>blocked</quote>
110 to <quote>ready</quote> on its current thread &mdash; it does not cause the fiber to
111 resume on the thread that unblocked it.
112 </para>
113 <anchor id="thread_local_storage"/>
114 <bridgehead renderas="sect3" id="fiber.overview.h1">
115 <phrase id="fiber.overview.thread_local_storage"/><link linkend="fiber.overview.thread_local_storage">thread-local
116 storage</link>
117 </bridgehead>
118 <para>
119 Unless migrated, a fiber may access thread-local storage; however that storage
120 will be shared among all fibers running on the same thread. For fiber-local
121 storage, please see <link linkend="class_fiber_specific_ptr"><code>fiber_specific_ptr</code></link>.
122 </para>
123 <anchor id="cross_thread_sync"/>
124 <bridgehead renderas="sect3" id="fiber.overview.h2">
125 <phrase id="fiber.overview.boost_fibers_no_atomics"/><link linkend="fiber.overview.boost_fibers_no_atomics">BOOST_FIBERS_NO_ATOMICS</link>
126 </bridgehead>
127 <para>
128 The fiber synchronization objects provided by this library will, by default,
129 safely synchronize fibers running on different threads. However, this level
130 of synchronization can be removed (for performance) by building the library
131 with <emphasis role="bold"><code><phrase role="identifier">BOOST_FIBERS_NO_ATOMICS</phrase></code></emphasis>
132 defined. When the library is built with that macro, you must ensure that all
133 the fibers referencing a particular synchronization object are running in the
134 same thread. Please see <link linkend="synchronization">Synchronization</link>.
135 </para>
136 <anchor id="blocking"/>
137 <bridgehead renderas="sect3" id="fiber.overview.h3">
138 <phrase id="fiber.overview.blocking"/><link linkend="fiber.overview.blocking">Blocking</link>
139 </bridgehead>
140 <para>
141 Normally, when this documentation states that a particular fiber <emphasis>blocks</emphasis>
142 (or equivalently, <emphasis>suspends),</emphasis> it means that it yields control,
143 allowing other fibers on the same thread to run. The synchronization mechanisms
144 provided by <emphasis role="bold">Boost.Fiber</emphasis> have this behavior.
145 </para>
146 <para>
147 A fiber may, of course, use normal thread synchronization mechanisms; however
148 a fiber that invokes any of these mechanisms will block its entire thread,
149 preventing any other fiber from running on that thread in the meantime. For
150 instance, when a fiber wants to wait for a value from another fiber in the
151 same thread, using <code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase
152 role="identifier">future</phrase></code> would be unfortunate: <code><phrase
153 role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">future</phrase><phrase
154 role="special">::</phrase><phrase role="identifier">get</phrase><phrase role="special">()</phrase></code>
155 would block the whole thread, preventing the other fiber from delivering its
156 value. Use <link linkend="class_future"><code>future&lt;&gt;</code></link> instead.
157 </para>
158 <para>
159 Similarly, a fiber that invokes a normal blocking I/O operation will block
160 its entire thread. Fiber authors are encouraged to consistently use asynchronous
161 I/O. <ulink url="http://www.boost.org/doc/libs/release/libs/asio/index.html">Boost.Asio</ulink>
162 and other asynchronous I/O operations can straightforwardly be adapted for
163 <emphasis role="bold">Boost.Fiber</emphasis>: see <link linkend="callbacks">Integrating
164 Fibers with Asynchronous Callbacks</link>.
165 </para>
166 <warning>
167 <para>
168 This library is <emphasis>not</emphasis> an official Boost library.
169 </para>
170 </warning>
171 <para>
172 <emphasis role="bold">Boost.Fiber</emphasis> depends upon <ulink url="http://www.boost.org/doc/libs/release/libs/context/index.html">Boost.Context</ulink>.
173 Boost version 1.61.0 or greater is required.
174 </para>
175 <note>
176 <para>
177 This library requires C++11!
178 </para>
179 </note>
180 </section>
181 <section id="fiber.fiber_mgmt">
182 <title><link linkend="fiber.fiber_mgmt">Fiber management</link></title>
183 <bridgehead renderas="sect3" id="fiber.fiber_mgmt.h0">
184 <phrase id="fiber.fiber_mgmt.synopsis"/><link linkend="fiber.fiber_mgmt.synopsis">Synopsis</link>
185 </bridgehead>
186 <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>
187
188 <phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase>
189 <phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase>
190
191 <phrase role="keyword">class</phrase> <phrase role="identifier">fiber</phrase><phrase role="special">;</phrase>
192 <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>
193 <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>
194
195 <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>
196 <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>
197 <phrase role="keyword">bool</phrase> <phrase role="identifier">has_ready_fibers</phrase><phrase role="special">();</phrase>
198
199 <phrase role="keyword">namespace</phrase> <phrase role="identifier">algo</phrase> <phrase role="special">{</phrase>
200
201 <phrase role="keyword">struct</phrase> <phrase role="identifier">algorithm</phrase><phrase role="special">;</phrase>
202 <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>
203 <phrase role="keyword">struct</phrase> <phrase role="identifier">algorithm_with_properties</phrase><phrase role="special">;</phrase>
204 <phrase role="keyword">class</phrase> <phrase role="identifier">round_robin</phrase><phrase role="special">;</phrase>
205 <phrase role="keyword">class</phrase> <phrase role="identifier">shared_round_robin</phrase><phrase role="special">;</phrase>
206
207 <phrase role="special">}</phrase>
208
209 <phrase role="keyword">namespace</phrase> <phrase role="identifier">this_fiber</phrase> <phrase role="special">{</phrase>
210
211 <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>
212 <phrase role="keyword">void</phrase> <phrase role="identifier">yield</phrase><phrase role="special">();</phrase>
213 <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>
214 <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>
215 <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>
216 <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>
217 <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>
218 <phrase role="identifier">PROPS</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">properties</phrase><phrase role="special">();</phrase>
219
220 <phrase role="special">}}</phrase>
221 </programlisting>
222 <bridgehead renderas="sect3" id="fiber.fiber_mgmt.h1">
223 <phrase id="fiber.fiber_mgmt.tutorial"/><link linkend="fiber.fiber_mgmt.tutorial">Tutorial</link>
224 </bridgehead>
225 <para>
226 Each <link linkend="class_fiber"><code>fiber</code></link> represents a micro-thread which will be launched and managed
227 cooperatively by a scheduler. Objects of type <link linkend="class_fiber"><code>fiber</code></link> are move-only.
228 </para>
229 <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>
230
231 <phrase role="keyword">void</phrase> <phrase role="identifier">f</phrase><phrase role="special">()</phrase> <phrase role="special">{</phrase>
232 <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>
233
234 <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>
235 <phrase role="special">}</phrase>
236 </programlisting>
237 <bridgehead renderas="sect3" id="fiber.fiber_mgmt.h2">
238 <phrase id="fiber.fiber_mgmt.launching"/><link linkend="fiber.fiber_mgmt.launching">Launching</link>
239 </bridgehead>
240 <para>
241 A new fiber is launched by passing an object of a callable type that can be
242 invoked with no parameters. If the object must not be copied or moved, then
243 <emphasis>std::ref</emphasis> can be used to pass in a reference to the function
244 object. In this case, the user must ensure that the referenced object outlives
245 the newly-created fiber.
246 </para>
247 <programlisting><phrase role="keyword">struct</phrase> <phrase role="identifier">callable</phrase> <phrase role="special">{</phrase>
248 <phrase role="keyword">void</phrase> <phrase role="keyword">operator</phrase><phrase role="special">()();</phrase>
249 <phrase role="special">};</phrase>
250
251 <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>
252 <phrase role="identifier">callable</phrase> <phrase role="identifier">x</phrase><phrase role="special">;</phrase>
253 <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>
254 <phrase role="special">}</phrase> <phrase role="comment">// x is destroyed, but the newly-created fiber has a copy, so this is OK</phrase>
255
256 <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>
257 <phrase role="identifier">callable</phrase> <phrase role="identifier">x</phrase><phrase role="special">;</phrase>
258 <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>
259 <phrase role="special">}</phrase> <phrase role="comment">// x is destroyed, but the newly-created fiber still has a reference</phrase>
260 <phrase role="comment">// this leads to undefined behaviour</phrase>
261 </programlisting>
262 <para>
263 The spawned <link linkend="class_fiber"><code>fiber</code></link> does not immediately start running. It is enqueued
264 in the list of ready-to-run fibers, and will run when the scheduler gets around
265 to it.
266 </para>
267 <anchor id="exceptions"/>
268 <bridgehead renderas="sect3" id="fiber.fiber_mgmt.h3">
269 <phrase id="fiber.fiber_mgmt.exceptions"/><link linkend="fiber.fiber_mgmt.exceptions">Exceptions</link>
270 </bridgehead>
271 <para>
272 An exception escaping from the function or callable object passed to the <link linkend="class_fiber"><code>fiber</code></link>
273 constructor
274 calls <code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase
275 role="identifier">terminate</phrase><phrase role="special">()</phrase></code>.
276 If you need to know which exception was thrown, use <link linkend="class_future"><code>future&lt;&gt;</code></link> or
277 <link linkend="class_packaged_task"><code>packaged_task&lt;&gt;</code></link>.
278 </para>
279 <bridgehead renderas="sect3" id="fiber.fiber_mgmt.h4">
280 <phrase id="fiber.fiber_mgmt.detaching"/><link linkend="fiber.fiber_mgmt.detaching">Detaching</link>
281 </bridgehead>
282 <para>
283 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
284 function. After <link linkend="fiber_detach"><code>fiber::detach()</code></link> is called on a fiber object, that
285 object represents <emphasis>not-a-fiber</emphasis>. The fiber object may then
286 safely be destroyed.
287 </para>
288 <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>
289 </programlisting>
290 <para>
291 <emphasis role="bold">Boost.Fiber</emphasis> provides a number of ways to wait
292 for a running fiber to complete. You can coordinate even with a detached fiber
293 using a <link linkend="class_mutex"><code>mutex</code></link>, or <link linkend="class_condition_variable"><code>condition_variable</code></link>, or
294 any of the other <link linkend="synchronization">synchronization objects</link>
295 provided by the library.
296 </para>
297 <para>
298 If a detached fiber is still running when the thread&#8217;s main fiber terminates,
299 the thread will not shut down.
300 </para>
301 <bridgehead renderas="sect3" id="fiber.fiber_mgmt.h5">
302 <phrase id="fiber.fiber_mgmt.joining"/><link linkend="fiber.fiber_mgmt.joining">Joining</link>
303 </bridgehead>
304 <para>
305 In order to wait for a fiber to finish, the <link linkend="fiber_join"><code>fiber::join()</code></link> member function
306 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
307 until the <link linkend="class_fiber"><code>fiber</code></link> object has completed.
308 </para>
309 <programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">some_fn</phrase><phrase role="special">()</phrase> <phrase role="special">{</phrase>
310 <phrase role="special">...</phrase>
311 <phrase role="special">}</phrase>
312
313 <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>
314 <phrase role="special">...</phrase>
315 <phrase role="identifier">f</phrase><phrase role="special">.</phrase><phrase role="identifier">join</phrase><phrase role="special">();</phrase>
316 </programlisting>
317 <para>
318 If the fiber has already completed, then <link linkend="fiber_join"><code>fiber::join()</code></link> returns immediately
319 and the joined <link linkend="class_fiber"><code>fiber</code></link> object becomes <emphasis>not-a-fiber</emphasis>.
320 </para>
321 <bridgehead renderas="sect3" id="fiber.fiber_mgmt.h6">
322 <phrase id="fiber.fiber_mgmt.destruction"/><link linkend="fiber.fiber_mgmt.destruction">Destruction</link>
323 </bridgehead>
324 <para>
325 When a <link linkend="class_fiber"><code>fiber</code></link> object representing a valid execution context (the fiber
326 is <link linkend="fiber_joinable"><code>fiber::joinable()</code></link>) is destroyed, the program terminates. If
327 you intend the fiber to outlive the <link linkend="class_fiber"><code>fiber</code></link> object that launched it,
328 use the <link linkend="fiber_detach"><code>fiber::detach()</code></link> method.
329 </para>
330 <programlisting><phrase role="special">{</phrase>
331 <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>
332 <phrase role="special">}</phrase> <phrase role="comment">// std::terminate() will be called</phrase>
333
334 <phrase role="special">{</phrase>
335 <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>
336 <phrase role="identifier">f</phrase><phrase role="special">.</phrase><phrase role="identifier">detach</phrase><phrase role="special">();</phrase>
337 <phrase role="special">}</phrase> <phrase role="comment">// okay, program continues</phrase>
338 </programlisting>
339 <anchor id="class_fiber_id"/>
340 <bridgehead renderas="sect3" id="fiber.fiber_mgmt.h7">
341 <phrase id="fiber.fiber_mgmt.fiber_ids"/><link linkend="fiber.fiber_mgmt.fiber_ids">Fiber
342 IDs</link>
343 </bridgehead>
344 <para>
345 Objects of class <link linkend="class_fiber_id"><code><phrase role="identifier">fiber</phrase><phrase
346 role="special">::</phrase><phrase role="identifier">id</phrase></code></link> can be
347 used to identify fibers. Each running <link linkend="class_fiber"><code>fiber</code></link> has a unique <link linkend="class_fiber_id"><code><phrase
348 role="identifier">fiber</phrase><phrase role="special">::</phrase><phrase role="identifier">id</phrase></code></link> obtainable
349 from the corresponding <link linkend="class_fiber"><code>fiber</code></link>
350 by calling the <link linkend="fiber_get_id"><code>fiber::get_id()</code></link> member
351 function. Objects of class <link linkend="class_fiber_id"><code><phrase role="identifier">fiber</phrase><phrase
352 role="special">::</phrase><phrase role="identifier">id</phrase></code></link> can be
353 copied, and used as keys in associative containers: the full range of comparison
354 operators is provided. They can also be written to an output stream using the
355 stream insertion operator, though the output format is unspecified.
356 </para>
357 <para>
358 Each instance of <link linkend="class_fiber_id"><code><phrase role="identifier">fiber</phrase><phrase
359 role="special">::</phrase><phrase role="identifier">id</phrase></code></link> either
360 refers to some fiber, or <emphasis>not-a-fiber</emphasis>. Instances that refer
361 to <emphasis>not-a-fiber</emphasis> compare equal to each other, but not equal
362 to any instances that refer to an actual fiber. The comparison operators on
363 <link linkend="class_fiber_id"><code><phrase role="identifier">fiber</phrase><phrase role="special">::</phrase><phrase
364 role="identifier">id</phrase></code></link> yield a total order for every non-equal
365 <link linkend="class_fiber_id"><code><phrase role="identifier">fiber</phrase><phrase role="special">::</phrase><phrase
366 role="identifier">id</phrase></code></link>.
367 </para>
368 <anchor id="class_launch"/>
369 <bridgehead renderas="sect3" id="fiber.fiber_mgmt.h8">
370 <phrase id="fiber.fiber_mgmt.enumeration__code__phrase_role__identifier__launch__phrase___code_"/><link
371 linkend="fiber.fiber_mgmt.enumeration__code__phrase_role__identifier__launch__phrase___code_">Enumeration
372 <code><phrase role="identifier">launch</phrase></code></link>
373 </bridgehead>
374 <para>
375 <code><phrase role="identifier">launch</phrase></code> specifies whether control
376 passes immediately into a newly-launched fiber.
377 </para>
378 <programlisting><phrase role="keyword">enum</phrase> <phrase role="keyword">class</phrase> <phrase role="identifier">launch</phrase> <phrase role="special">{</phrase>
379 <phrase role="identifier">dispatch</phrase><phrase role="special">,</phrase>
380 <phrase role="identifier">post</phrase>
381 <phrase role="special">};</phrase>
382 </programlisting>
383 <bridgehead renderas="sect3" id="fiber.fiber_mgmt.h9">
384 <phrase id="fiber.fiber_mgmt._code__phrase_role__identifier__dispatch__phrase___code_"/><link
385 linkend="fiber.fiber_mgmt._code__phrase_role__identifier__dispatch__phrase___code_"><code><phrase
386 role="identifier">dispatch</phrase></code></link>
387 </bridgehead>
388 <variablelist>
389 <title></title>
390 <varlistentry>
391 <term>Effects:</term>
392 <listitem>
393 <para>
394 A fiber launched with <code><phrase role="identifier">launch</phrase>
395 <phrase role="special">==</phrase> <phrase role="identifier">dispatch</phrase></code>
396 is entered immediately. In other words, launching a fiber with <code><phrase
397 role="identifier">dispatch</phrase></code> suspends the caller (the previously-running
398 fiber) until the fiber scheduler has a chance to resume it later.
399 </para>
400 </listitem>
401 </varlistentry>
402 </variablelist>
403 <bridgehead renderas="sect3" id="fiber.fiber_mgmt.h10">
404 <phrase id="fiber.fiber_mgmt._code__phrase_role__identifier__post__phrase___code_"/><link
405 linkend="fiber.fiber_mgmt._code__phrase_role__identifier__post__phrase___code_"><code><phrase
406 role="identifier">post</phrase></code></link>
407 </bridgehead>
408 <variablelist>
409 <title></title>
410 <varlistentry>
411 <term>Effects:</term>
412 <listitem>
413 <para>
414 A fiber launched with <code><phrase role="identifier">launch</phrase>
415 <phrase role="special">==</phrase> <phrase role="identifier">post</phrase></code>
416 is passed to the fiber scheduler as ready, but it is not yet entered.
417 The caller (the previously-running fiber) continues executing. The newly-launched
418 fiber will be entered when the fiber scheduler has a chance to resume
419 it later.
420 </para>
421 </listitem>
422 </varlistentry>
423 <varlistentry>
424 <term>Note:</term>
425 <listitem>
426 <para>
427 If <code><phrase role="identifier">launch</phrase></code> is not explicitly
428 specified, <code><phrase role="identifier">post</phrase></code> is the
429 default.
430 </para>
431 </listitem>
432 </varlistentry>
433 </variablelist>
434 <section id="fiber.fiber_mgmt.fiber">
435 <title><anchor id="class_fiber"/><link linkend="fiber.fiber_mgmt.fiber">Class
436 <code><phrase role="identifier">fiber</phrase></code></link></title>
437 <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>
438
439 <phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase>
440 <phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase>
441
442 <phrase role="keyword">class</phrase> <phrase role="identifier">fiber</phrase> <phrase role="special">{</phrase>
443 <phrase role="keyword">public</phrase><phrase role="special">:</phrase>
444 <phrase role="keyword">class</phrase> <phrase role="identifier">id</phrase><phrase role="special">;</phrase>
445
446 <phrase role="keyword">constexpr</phrase> <phrase role="identifier">fiber</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
447
448 <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>
449 <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>
450
451 <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>
452 <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>
453
454 <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>
455 <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">,</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>
456
457 <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>
458 <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">,</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>
459
460 <phrase role="special">~</phrase><phrase role="identifier">fiber</phrase><phrase role="special">();</phrase>
461
462 <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>
463
464 <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>
465
466 <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>
467
468 <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>
469
470 <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>
471
472 <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>
473
474 <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>
475
476 <phrase role="keyword">void</phrase> <phrase role="identifier">detach</phrase><phrase role="special">();</phrase>
477
478 <phrase role="keyword">void</phrase> <phrase role="identifier">join</phrase><phrase role="special">();</phrase>
479
480 <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>
481 <phrase role="identifier">PROPS</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">properties</phrase><phrase role="special">();</phrase>
482 <phrase role="special">};</phrase>
483
484 <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>
485
486 <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>
487
488 <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>
489 <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>
490
491 <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>
492
493 <phrase role="special">}}</phrase>
494 </programlisting>
495 <bridgehead renderas="sect4" id="fiber.fiber_mgmt.fiber.h0">
496 <phrase id="fiber.fiber_mgmt.fiber.default_constructor"/><link linkend="fiber.fiber_mgmt.fiber.default_constructor">Default
497 constructor</link>
498 </bridgehead>
499 <programlisting><phrase role="keyword">constexpr</phrase> <phrase role="identifier">fiber</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
500 </programlisting>
501 <variablelist>
502 <title></title>
503 <varlistentry>
504 <term>Effects:</term>
505 <listitem>
506 <para>
507 Constructs a <link linkend="class_fiber"><code>fiber</code></link> instance that refers to <emphasis>not-a-fiber</emphasis>.
508 </para>
509 </listitem>
510 </varlistentry>
511 <varlistentry>
512 <term>Postconditions:</term>
513 <listitem>
514 <para>
515 <code><phrase role="keyword">this</phrase><phrase role="special">-&gt;</phrase><phrase
516 role="identifier">get_id</phrase><phrase role="special">()</phrase>
517 <phrase role="special">==</phrase> <phrase role="identifier">fiber</phrase><phrase
518 role="special">::</phrase><phrase role="identifier">id</phrase><phrase
519 role="special">()</phrase></code>
520 </para>
521 </listitem>
522 </varlistentry>
523 <varlistentry>
524 <term>Throws:</term>
525 <listitem>
526 <para>
527 Nothing
528 </para>
529 </listitem>
530 </varlistentry>
531 </variablelist>
532 <anchor id="fiber_fiber"/>
533 <bridgehead renderas="sect4" id="fiber.fiber_mgmt.fiber.h1">
534 <phrase id="fiber.fiber_mgmt.fiber.constructor"/><link linkend="fiber.fiber_mgmt.fiber.constructor">Constructor</link>
535 </bridgehead>
536 <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>
537 <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>
538
539 <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>
540 <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>
541
542 <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>
543 <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="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>
544
545 <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>
546 <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="identifier">salloc</phrase><phrase role="special">,</phrase>
547 <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>
548 </programlisting>
549 <variablelist>
550 <title></title>
551 <varlistentry>
552 <term>Preconditions:</term>
553 <listitem>
554 <para>
555 <code><phrase role="identifier">Fn</phrase></code> must be copyable
556 or movable.
557 </para>
558 </listitem>
559 </varlistentry>
560 <varlistentry>
561 <term>Effects:</term>
562 <listitem>
563 <para>
564 <code><phrase role="identifier">fn</phrase></code> is copied or moved
565 into internal storage for access by the new fiber. If <link linkend="class_launch"><code>launch</code></link> is
566 specified (or defaulted) to <code><phrase role="identifier">post</phrase></code>,
567 the new fiber is marked <quote>ready</quote> and will be entered at
568 the next opportunity. If <code><phrase role="identifier">launch</phrase></code>
569 is specified as <code><phrase role="identifier">dispatch</phrase></code>,
570 the calling fiber is suspended and the new fiber is entered immediately.
571 </para>
572 </listitem>
573 </varlistentry>
574 <varlistentry>
575 <term>Postconditions:</term>
576 <listitem>
577 <para>
578 <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>
579 refers to the newly created fiber of execution.
580 </para>
581 </listitem>
582 </varlistentry>
583 <varlistentry>
584 <term>Throws:</term>
585 <listitem>
586 <para>
587 <code><phrase role="identifier">fiber_error</phrase></code> if an error
588 occurs.
589 </para>
590 </listitem>
591 </varlistentry>
592 <varlistentry>
593 <term>Note:</term>
594 <listitem>
595 <para>
596 <link linkend="stack_allocator_concept"><code><phrase role="identifier">StackAllocator</phrase></code></link>
597 is required to allocate a stack for the internal <ulink url="http://www.boost.org/doc/libs/release/libs/context/doc/html/context/econtext.html"><emphasis>execution_context</emphasis></ulink>.
598 If <code><phrase role="identifier">StackAllocator</phrase></code> is
599 not explicitly passed, the default stack allocator depends on <code><phrase
600 role="identifier">BOOST_USE_SEGMENTED_STACKS</phrase></code>: if defined,
601 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>.
602 </para>
603 </listitem>
604 </varlistentry>
605 <varlistentry>
606 <term>See also:</term>
607 <listitem>
608 <para>
609 <ulink url="http://en.cppreference.com/w/cpp/memory/allocator_arg_t"><code><phrase
610 role="identifier">std</phrase><phrase role="special">::</phrase><phrase
611 role="identifier">allocator_arg_t</phrase></code></ulink>, <link linkend="stack">Stack
612 allocation</link>
613 </para>
614 </listitem>
615 </varlistentry>
616 </variablelist>
617 <bridgehead renderas="sect4" id="fiber.fiber_mgmt.fiber.h2">
618 <phrase id="fiber.fiber_mgmt.fiber.move_constructor"/><link linkend="fiber.fiber_mgmt.fiber.move_constructor">Move
619 constructor</link>
620 </bridgehead>
621 <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>
622 </programlisting>
623 <variablelist>
624 <title></title>
625 <varlistentry>
626 <term>Effects:</term>
627 <listitem>
628 <para>
629 Transfers ownership of the fiber managed by <code><phrase role="identifier">other</phrase></code>
630 to the newly constructed <link linkend="class_fiber"><code>fiber</code></link> instance.
631 </para>
632 </listitem>
633 </varlistentry>
634 <varlistentry>
635 <term>Postconditions:</term>
636 <listitem>
637 <para>
638 <code><phrase role="identifier">other</phrase><phrase role="special">.</phrase><phrase
639 role="identifier">get_id</phrase><phrase role="special">()</phrase>
640 <phrase role="special">==</phrase> <phrase role="identifier">fiber</phrase><phrase
641 role="special">::</phrase><phrase role="identifier">id</phrase><phrase
642 role="special">()</phrase></code> and <code><phrase role="identifier">get_id</phrase><phrase
643 role="special">()</phrase></code> returns the value of <code><phrase
644 role="identifier">other</phrase><phrase role="special">.</phrase><phrase
645 role="identifier">get_id</phrase><phrase role="special">()</phrase></code>
646 prior to the construction
647 </para>
648 </listitem>
649 </varlistentry>
650 <varlistentry>
651 <term>Throws:</term>
652 <listitem>
653 <para>
654 Nothing
655 </para>
656 </listitem>
657 </varlistentry>
658 </variablelist>
659 <bridgehead renderas="sect4" id="fiber.fiber_mgmt.fiber.h3">
660 <phrase id="fiber.fiber_mgmt.fiber.move_assignment_operator"/><link linkend="fiber.fiber_mgmt.fiber.move_assignment_operator">Move
661 assignment operator</link>
662 </bridgehead>
663 <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>
664 </programlisting>
665 <variablelist>
666 <title></title>
667 <varlistentry>
668 <term>Effects:</term>
669 <listitem>
670 <para>
671 Transfers ownership of the fiber managed by <code><phrase role="identifier">other</phrase></code>
672 (if any) to <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>.
673 </para>
674 </listitem>
675 </varlistentry>
676 <varlistentry>
677 <term>Postconditions:</term>
678 <listitem>
679 <para>
680 <code><phrase role="identifier">other</phrase><phrase role="special">-&gt;</phrase><phrase
681 role="identifier">get_id</phrase><phrase role="special">()</phrase>
682 <phrase role="special">==</phrase> <phrase role="identifier">fiber</phrase><phrase
683 role="special">::</phrase><phrase role="identifier">id</phrase><phrase
684 role="special">()</phrase></code> and <code><phrase role="identifier">get_id</phrase><phrase
685 role="special">()</phrase></code> returns the value of <code><phrase
686 role="identifier">other</phrase><phrase role="special">.</phrase><phrase
687 role="identifier">get_id</phrase><phrase role="special">()</phrase></code>
688 prior to the assignment.
689 </para>
690 </listitem>
691 </varlistentry>
692 <varlistentry>
693 <term>Throws:</term>
694 <listitem>
695 <para>
696 Nothing
697 </para>
698 </listitem>
699 </varlistentry>
700 </variablelist>
701 <bridgehead renderas="sect4" id="fiber.fiber_mgmt.fiber.h4">
702 <phrase id="fiber.fiber_mgmt.fiber.destructor"/><link linkend="fiber.fiber_mgmt.fiber.destructor">Destructor</link>
703 </bridgehead>
704 <programlisting><phrase role="special">~</phrase><phrase role="identifier">fiber</phrase><phrase role="special">();</phrase>
705 </programlisting>
706 <variablelist>
707 <title></title>
708 <varlistentry>
709 <term>Effects:</term>
710 <listitem>
711 <para>
712 If the fiber is <link linkend="fiber_joinable"><code>fiber::joinable()</code></link>, calls std::terminate.
713 Destroys <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>.
714 </para>
715 </listitem>
716 </varlistentry>
717 <varlistentry>
718 <term>Note:</term>
719 <listitem>
720 <para>
721 The programmer must ensure that the destructor is never executed while
722 the fiber is still <link linkend="fiber_joinable"><code>fiber::joinable()</code></link>. Even if you know
723 that the fiber has completed, you must still call either <link linkend="fiber_join"><code>fiber::join()</code></link> or
724 <link linkend="fiber_detach"><code>fiber::detach()</code></link> before destroying the <code><phrase role="identifier">fiber</phrase></code>
725 object.
726 </para>
727 </listitem>
728 </varlistentry>
729 </variablelist>
730 <para>
731 <bridgehead renderas="sect4" id="fiber_joinable_bridgehead">
732 <phrase id="fiber_joinable"/>
733 <link linkend="fiber_joinable">Member function <code>joinable</code>()</link>
734 </bridgehead>
735 </para>
736 <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>
737 </programlisting>
738 <variablelist>
739 <title></title>
740 <varlistentry>
741 <term>Returns:</term>
742 <listitem>
743 <para>
744 <code><phrase role="keyword">true</phrase></code> if <code><phrase
745 role="special">*</phrase><phrase role="keyword">this</phrase></code>
746 refers to a fiber of execution, which may or may not have completed;
747 otherwise <code><phrase role="keyword">false</phrase></code>.
748 </para>
749 </listitem>
750 </varlistentry>
751 <varlistentry>
752 <term>Throws:</term>
753 <listitem>
754 <para>
755 Nothing
756 </para>
757 </listitem>
758 </varlistentry>
759 </variablelist>
760 <para>
761 <bridgehead renderas="sect4" id="fiber_join_bridgehead">
762 <phrase id="fiber_join"/>
763 <link linkend="fiber_join">Member function <code>join</code>()</link>
764 </bridgehead>
765 </para>
766 <programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">join</phrase><phrase role="special">();</phrase>
767 </programlisting>
768 <variablelist>
769 <title></title>
770 <varlistentry>
771 <term>Preconditions:</term>
772 <listitem>
773 <para>
774 the fiber is <link linkend="fiber_joinable"><code>fiber::joinable()</code></link>.
775 </para>
776 </listitem>
777 </varlistentry>
778 <varlistentry>
779 <term>Effects:</term>
780 <listitem>
781 <para>
782 Waits for the referenced fiber of execution to complete.
783 </para>
784 </listitem>
785 </varlistentry>
786 <varlistentry>
787 <term>Postconditions:</term>
788 <listitem>
789 <para>
790 The fiber of execution referenced on entry has completed. <code><phrase
791 role="special">*</phrase><phrase role="keyword">this</phrase></code>
792 no longer refers to any fiber of execution.
793 </para>
794 </listitem>
795 </varlistentry>
796 <varlistentry>
797 <term>Throws:</term>
798 <listitem>
799 <para>
800 <code><phrase role="identifier">fiber_error</phrase></code>
801 </para>
802 </listitem>
803 </varlistentry>
804 <varlistentry>
805 <term>Error Conditions:</term>
806 <listitem>
807 <para>
808 <emphasis role="bold">resource_deadlock_would_occur</emphasis>: if
809 <code><phrase role="keyword">this</phrase><phrase role="special">-&gt;</phrase><phrase
810 role="identifier">get_id</phrase><phrase role="special">()</phrase>
811 <phrase role="special">==</phrase> <phrase role="identifier">boost</phrase><phrase
812 role="special">::</phrase><phrase role="identifier">this_fiber</phrase><phrase
813 role="special">::</phrase><phrase role="identifier">get_id</phrase><phrase
814 role="special">()</phrase></code>. <emphasis role="bold">invalid_argument</emphasis>:
815 if the fiber is not <link linkend="fiber_joinable"><code>fiber::joinable()</code></link>.
816 </para>
817 </listitem>
818 </varlistentry>
819 </variablelist>
820 <para>
821 <bridgehead renderas="sect4" id="fiber_detach_bridgehead">
822 <phrase id="fiber_detach"/>
823 <link linkend="fiber_detach">Member function <code>detach</code>()</link>
824 </bridgehead>
825 </para>
826 <programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">detach</phrase><phrase role="special">();</phrase>
827 </programlisting>
828 <variablelist>
829 <title></title>
830 <varlistentry>
831 <term>Preconditions:</term>
832 <listitem>
833 <para>
834 the fiber is <link linkend="fiber_joinable"><code>fiber::joinable()</code></link>.
835 </para>
836 </listitem>
837 </varlistentry>
838 <varlistentry>
839 <term>Effects:</term>
840 <listitem>
841 <para>
842 The fiber of execution becomes detached, and no longer has an associated
843 <link linkend="class_fiber"><code>fiber</code></link> object.
844 </para>
845 </listitem>
846 </varlistentry>
847 <varlistentry>
848 <term>Postconditions:</term>
849 <listitem>
850 <para>
851 <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>
852 no longer refers to any fiber of execution.
853 </para>
854 </listitem>
855 </varlistentry>
856 <varlistentry>
857 <term>Throws:</term>
858 <listitem>
859 <para>
860 <code><phrase role="identifier">fiber_error</phrase></code>
861 </para>
862 </listitem>
863 </varlistentry>
864 <varlistentry>
865 <term>Error Conditions:</term>
866 <listitem>
867 <para>
868 <emphasis role="bold">invalid_argument</emphasis>: if the fiber is
869 not <link linkend="fiber_joinable"><code>fiber::joinable()</code></link>.
870 </para>
871 </listitem>
872 </varlistentry>
873 </variablelist>
874 <para>
875 <bridgehead renderas="sect4" id="fiber_get_id_bridgehead">
876 <phrase id="fiber_get_id"/>
877 <link linkend="fiber_get_id">Member function <code>get_id</code>()</link>
878 </bridgehead>
879 </para>
880 <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>
881 </programlisting>
882 <variablelist>
883 <title></title>
884 <varlistentry>
885 <term>Returns:</term>
886 <listitem>
887 <para>
888 If <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>
889 refers to a fiber of execution, an instance of <link linkend="class_fiber_id"><code><phrase
890 role="identifier">fiber</phrase><phrase role="special">::</phrase><phrase
891 role="identifier">id</phrase></code></link> that represents that fiber. Otherwise
892 returns a default-constructed <link linkend="class_fiber_id"><code><phrase role="identifier">fiber</phrase><phrase
893 role="special">::</phrase><phrase role="identifier">id</phrase></code></link>.
894 </para>
895 </listitem>
896 </varlistentry>
897 <varlistentry>
898 <term>Throws:</term>
899 <listitem>
900 <para>
901 Nothing
902 </para>
903 </listitem>
904 </varlistentry>
905 <varlistentry>
906 <term>See also:</term>
907 <listitem>
908 <para>
909 <link linkend="this_fiber_get_id"><code>this_fiber::get_id()</code></link>
910 </para>
911 </listitem>
912 </varlistentry>
913 </variablelist>
914 <para>
915 <bridgehead renderas="sect4" id="fiber_properties_bridgehead">
916 <phrase id="fiber_properties"/>
917 <link linkend="fiber_properties">Templated member
918 function <code>properties</code>()</link>
919 </bridgehead>
920 </para>
921 <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>
922 <phrase role="identifier">PROPS</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">properties</phrase><phrase role="special">();</phrase>
923 </programlisting>
924 <variablelist>
925 <title></title>
926 <varlistentry>
927 <term>Preconditions:</term>
928 <listitem>
929 <para>
930 <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>
931 refers to a fiber of execution. <link linkend="use_scheduling_algorithm"><code>use_scheduling_algorithm()</code></link> has
932 been called from this thread with a subclass of <link linkend="class_algorithm_with_properties"><code>algorithm_with_properties&lt;&gt;</code></link> with
933 the same template argument <code><phrase role="identifier">PROPS</phrase></code>.
934 </para>
935 </listitem>
936 </varlistentry>
937 <varlistentry>
938 <term>Returns:</term>
939 <listitem>
940 <para>
941 a reference to the scheduler properties instance for <code><phrase
942 role="special">*</phrase><phrase role="keyword">this</phrase></code>.
943 </para>
944 </listitem>
945 </varlistentry>
946 <varlistentry>
947 <term>Throws:</term>
948 <listitem>
949 <para>
950 <code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase
951 role="identifier">bad_cast</phrase></code> if <code><phrase role="identifier">use_scheduling_algorithm</phrase><phrase
952 role="special">()</phrase></code> was called with a <code><phrase role="identifier">algorithm_with_properties</phrase></code>
953 subclass with some other template parameter than <code><phrase role="identifier">PROPS</phrase></code>.
954 </para>
955 </listitem>
956 </varlistentry>
957 <varlistentry>
958 <term>Note:</term>
959 <listitem>
960 <para>
961 <link linkend="class_algorithm_with_properties"><code>algorithm_with_properties&lt;&gt;</code></link> provides
962 a way for a user-coded scheduler to associate extended properties,
963 such as priority, with a fiber instance. This method allows access
964 to those user-provided properties.
965 </para>
966 </listitem>
967 </varlistentry>
968 <varlistentry>
969 <term>See also:</term>
970 <listitem>
971 <para>
972 <link linkend="custom">Customization</link>
973 </para>
974 </listitem>
975 </varlistentry>
976 </variablelist>
977 <para>
978 <bridgehead renderas="sect4" id="fiber_swap_bridgehead">
979 <phrase id="fiber_swap"/>
980 <link linkend="fiber_swap">Member function <code>swap</code>()</link>
981 </bridgehead>
982 </para>
983 <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>
984 </programlisting>
985 <variablelist>
986 <title></title>
987 <varlistentry>
988 <term>Effects:</term>
989 <listitem>
990 <para>
991 Exchanges the fiber of execution associated with <code><phrase role="special">*</phrase><phrase
992 role="keyword">this</phrase></code> and <code><phrase role="identifier">other</phrase></code>,
993 so <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>
994 becomes associated with the fiber formerly associated with <code><phrase
995 role="identifier">other</phrase></code>, and vice-versa.
996 </para>
997 </listitem>
998 </varlistentry>
999 <varlistentry>
1000 <term>Postconditions:</term>
1001 <listitem>
1002 <para>
1003 <code><phrase role="keyword">this</phrase><phrase role="special">-&gt;</phrase><phrase
1004 role="identifier">get_id</phrase><phrase role="special">()</phrase></code>
1005 returns the same value as <code><phrase role="identifier">other</phrase><phrase
1006 role="special">.</phrase><phrase role="identifier">get_id</phrase><phrase
1007 role="special">()</phrase></code> prior to the call. <code><phrase
1008 role="identifier">other</phrase><phrase role="special">.</phrase><phrase
1009 role="identifier">get_id</phrase><phrase role="special">()</phrase></code>
1010 returns the same value as <code><phrase role="keyword">this</phrase><phrase
1011 role="special">-&gt;</phrase><phrase role="identifier">get_id</phrase><phrase
1012 role="special">()</phrase></code> prior to the call.
1013 </para>
1014 </listitem>
1015 </varlistentry>
1016 <varlistentry>
1017 <term>Throws:</term>
1018 <listitem>
1019 <para>
1020 Nothing
1021 </para>
1022 </listitem>
1023 </varlistentry>
1024 </variablelist>
1025 <para>
1026 <bridgehead renderas="sect4" id="swap_for_fiber_bridgehead">
1027 <phrase id="swap_for_fiber"/>
1028 <link linkend="swap_for_fiber">Non-member function
1029 <code>swap()</code></link>
1030 </bridgehead>
1031 </para>
1032 <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>
1033 </programlisting>
1034 <variablelist>
1035 <title></title>
1036 <varlistentry>
1037 <term>Effects:</term>
1038 <listitem>
1039 <para>
1040 Same as <code><phrase role="identifier">l</phrase><phrase role="special">.</phrase><phrase
1041 role="identifier">swap</phrase><phrase role="special">(</phrase> <phrase
1042 role="identifier">r</phrase><phrase role="special">)</phrase></code>.
1043 </para>
1044 </listitem>
1045 </varlistentry>
1046 <varlistentry>
1047 <term>Throws:</term>
1048 <listitem>
1049 <para>
1050 Nothing
1051 </para>
1052 </listitem>
1053 </varlistentry>
1054 </variablelist>
1055 <para>
1056 <bridgehead renderas="sect4" id="operator&lt;_bridgehead">
1057 <phrase id="operator&lt;"/>
1058 <link linkend="operator&lt;">Non-member function <code>operator&lt;()</code></link>
1059 </bridgehead>
1060 </para>
1061 <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>
1062 </programlisting>
1063 <variablelist>
1064 <title></title>
1065 <varlistentry>
1066 <term>Returns:</term>
1067 <listitem>
1068 <para>
1069 <code><phrase role="keyword">true</phrase></code> if <code><phrase
1070 role="identifier">l</phrase><phrase role="special">.</phrase><phrase
1071 role="identifier">get_id</phrase><phrase role="special">()</phrase>
1072 <phrase role="special">&lt;</phrase> <phrase role="identifier">r</phrase><phrase
1073 role="special">.</phrase><phrase role="identifier">get_id</phrase><phrase
1074 role="special">()</phrase></code> is <code><phrase role="keyword">true</phrase></code>,
1075 false otherwise.
1076 </para>
1077 </listitem>
1078 </varlistentry>
1079 <varlistentry>
1080 <term>Throws:</term>
1081 <listitem>
1082 <para>
1083 Nothing.
1084 </para>
1085 </listitem>
1086 </varlistentry>
1087 </variablelist>
1088 <para>
1089 <bridgehead renderas="sect4" id="use_scheduling_algorithm_bridgehead">
1090 <phrase id="use_scheduling_algorithm"/>
1091 <link linkend="use_scheduling_algorithm">Non-member
1092 function <code>use_scheduling_algorithm()</code></link>
1093 </bridgehead>
1094 </para>
1095 <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>
1096 <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>
1097 </programlisting>
1098 <variablelist>
1099 <title></title>
1100 <varlistentry>
1101 <term>Effects:</term>
1102 <listitem>
1103 <para>
1104 Directs <emphasis role="bold">Boost.Fiber</emphasis> to use <code><phrase
1105 role="identifier">SchedAlgo</phrase></code>, which must be a concrete
1106 subclass of <link linkend="class_algorithm"><code>algorithm</code></link>, as the scheduling algorithm for
1107 all fibers in the current thread. Pass any required <code><phrase role="identifier">SchedAlgo</phrase></code>
1108 constructor arguments as <code><phrase role="identifier">args</phrase></code>.
1109 </para>
1110 </listitem>
1111 </varlistentry>
1112 <varlistentry>
1113 <term>Note:</term>
1114 <listitem>
1115 <para>
1116 If you want a given thread to use a non-default scheduling algorithm,
1117 make that thread call <code><phrase role="identifier">use_scheduling_algorithm</phrase><phrase
1118 role="special">()</phrase></code> before any other <emphasis role="bold">Boost.Fiber</emphasis>
1119 entry point. If no scheduler has been set for the current thread by
1120 the time <emphasis role="bold">Boost.Fiber</emphasis> needs to use
1121 it, the library will create a default <link linkend="class_round_robin"><code>round_robin</code></link> instance
1122 for this thread.
1123 </para>
1124 </listitem>
1125 </varlistentry>
1126 <varlistentry>
1127 <term>Throws:</term>
1128 <listitem>
1129 <para>
1130 Nothing
1131 </para>
1132 </listitem>
1133 </varlistentry>
1134 <varlistentry>
1135 <term>See also:</term>
1136 <listitem>
1137 <para>
1138 <link linkend="scheduling">Scheduling</link>, <link linkend="custom">Customization</link>
1139 </para>
1140 </listitem>
1141 </varlistentry>
1142 </variablelist>
1143 <para>
1144 <bridgehead renderas="sect4" id="has_ready_fibers_bridgehead">
1145 <phrase id="has_ready_fibers"/>
1146 <link linkend="has_ready_fibers">Non-member function
1147 <code>has_ready_fibers()</code></link>
1148 </bridgehead>
1149 </para>
1150 <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>
1151 </programlisting>
1152 <variablelist>
1153 <title></title>
1154 <varlistentry>
1155 <term>Returns:</term>
1156 <listitem>
1157 <para>
1158 <code><phrase role="keyword">true</phrase></code> if scheduler has
1159 fibers ready to run.
1160 </para>
1161 </listitem>
1162 </varlistentry>
1163 <varlistentry>
1164 <term>Throws:</term>
1165 <listitem>
1166 <para>
1167 Nothing
1168 </para>
1169 </listitem>
1170 </varlistentry>
1171 <varlistentry>
1172 <term>Note:</term>
1173 <listitem>
1174 <para>
1175 Can be used for work-stealing to find an idle scheduler.
1176 </para>
1177 </listitem>
1178 </varlistentry>
1179 </variablelist>
1180 </section>
1181 <section id="fiber.fiber_mgmt.id">
1182 <title><anchor id="class_id"/><link linkend="fiber.fiber_mgmt.id">Class fiber::id</link></title>
1183 <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>
1184
1185 <phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase>
1186 <phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase>
1187
1188 <phrase role="keyword">class</phrase> <phrase role="identifier">id</phrase> <phrase role="special">{</phrase>
1189 <phrase role="keyword">public</phrase><phrase role="special">:</phrase>
1190 <phrase role="keyword">constexpr</phrase> <phrase role="identifier">id</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
1191
1192 <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>
1193
1194 <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>
1195
1196 <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>
1197
1198 <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>
1199
1200 <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>
1201
1202 <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>
1203
1204 <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>
1205 <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>
1206 <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>
1207 <phrase role="special">};</phrase>
1208
1209 <phrase role="special">}}</phrase>
1210 </programlisting>
1211 <bridgehead renderas="sect4" id="fiber.fiber_mgmt.id.h0">
1212 <phrase id="fiber.fiber_mgmt.id.constructor"/><link linkend="fiber.fiber_mgmt.id.constructor">Constructor</link>
1213 </bridgehead>
1214 <programlisting><phrase role="keyword">constexpr</phrase> <phrase role="identifier">id</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
1215 </programlisting>
1216 <variablelist>
1217 <title></title>
1218 <varlistentry>
1219 <term>Effects:</term>
1220 <listitem>
1221 <para>
1222 Represents an instance of <emphasis>not-a-fiber</emphasis>.
1223 </para>
1224 </listitem>
1225 </varlistentry>
1226 <varlistentry>
1227 <term>Throws:</term>
1228 <listitem>
1229 <para>
1230 Nothing.
1231 </para>
1232 </listitem>
1233 </varlistentry>
1234 </variablelist>
1235 <para>
1236 <bridgehead renderas="sect4" id="id_operator_equal_bridgehead">
1237 <phrase id="id_operator_equal"/>
1238 <link linkend="id_operator_equal">Member function
1239 <code>operator==</code>()</link>
1240 </bridgehead>
1241 </para>
1242 <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>
1243 </programlisting>
1244 <variablelist>
1245 <title></title>
1246 <varlistentry>
1247 <term>Returns:</term>
1248 <listitem>
1249 <para>
1250 <code><phrase role="keyword">true</phrase></code> if <code><phrase
1251 role="special">*</phrase><phrase role="keyword">this</phrase></code>
1252 and <code><phrase role="identifier">other</phrase></code> represent
1253 the same fiber, or both represent <emphasis>not-a-fiber</emphasis>,
1254 <code><phrase role="keyword">false</phrase></code> otherwise.
1255 </para>
1256 </listitem>
1257 </varlistentry>
1258 <varlistentry>
1259 <term>Throws:</term>
1260 <listitem>
1261 <para>
1262 Nothing.
1263 </para>
1264 </listitem>
1265 </varlistentry>
1266 </variablelist>
1267 <para>
1268 <bridgehead renderas="sect4" id="id_operator_not_equal_bridgehead">
1269 <phrase id="id_operator_not_equal"/>
1270 <link linkend="id_operator_not_equal">Member
1271 function <code>operator!=</code>()</link>
1272 </bridgehead>
1273 </para>
1274 <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>
1275 </programlisting>
1276 <variablelist>
1277 <title></title>
1278 <varlistentry>
1279 <term>Returns:</term>
1280 <listitem>
1281 <para>
1282 <code>! (other == * this)</code>
1283 </para>
1284 </listitem>
1285 </varlistentry>
1286 <varlistentry>
1287 <term>Throws:</term>
1288 <listitem>
1289 <para>
1290 Nothing.
1291 </para>
1292 </listitem>
1293 </varlistentry>
1294 </variablelist>
1295 <para>
1296 <bridgehead renderas="sect4" id="id_operator_less_bridgehead">
1297 <phrase id="id_operator_less"/>
1298 <link linkend="id_operator_less">Member function
1299 <code>operator&lt;</code>()</link>
1300 </bridgehead>
1301 </para>
1302 <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>
1303 </programlisting>
1304 <variablelist>
1305 <title></title>
1306 <varlistentry>
1307 <term>Returns:</term>
1308 <listitem>
1309 <para>
1310 <code><phrase role="keyword">true</phrase></code> if <code><phrase
1311 role="special">*</phrase><phrase role="keyword">this</phrase> <phrase
1312 role="special">!=</phrase> <phrase role="identifier">other</phrase></code>
1313 is true and the implementation-defined total order of <code><phrase
1314 role="identifier">fiber</phrase><phrase role="special">::</phrase><phrase
1315 role="identifier">id</phrase></code> values places <code><phrase role="special">*</phrase><phrase
1316 role="keyword">this</phrase></code> before <code><phrase role="identifier">other</phrase></code>,
1317 false otherwise.
1318 </para>
1319 </listitem>
1320 </varlistentry>
1321 <varlistentry>
1322 <term>Throws:</term>
1323 <listitem>
1324 <para>
1325 Nothing.
1326 </para>
1327 </listitem>
1328 </varlistentry>
1329 </variablelist>
1330 <para>
1331 <bridgehead renderas="sect4" id="id_operator_greater_bridgehead">
1332 <phrase id="id_operator_greater"/>
1333 <link linkend="id_operator_greater">Member
1334 function <code>operator&gt;</code>()</link>
1335 </bridgehead>
1336 </para>
1337 <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>
1338 </programlisting>
1339 <variablelist>
1340 <title></title>
1341 <varlistentry>
1342 <term>Returns:</term>
1343 <listitem>
1344 <para>
1345 <code><phrase role="identifier">other</phrase> <phrase role="special">&lt;</phrase>
1346 <phrase role="special">*</phrase> <phrase role="keyword">this</phrase></code>
1347 </para>
1348 </listitem>
1349 </varlistentry>
1350 <varlistentry>
1351 <term>Throws:</term>
1352 <listitem>
1353 <para>
1354 Nothing.
1355 </para>
1356 </listitem>
1357 </varlistentry>
1358 </variablelist>
1359 <para>
1360 <bridgehead renderas="sect4" id="id_operator_less_equal_bridgehead">
1361 <phrase id="id_operator_less_equal"/>
1362 <link linkend="id_operator_less_equal">Member
1363 function <code>operator&lt;=</code>()</link>
1364 </bridgehead>
1365 </para>
1366 <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>
1367 </programlisting>
1368 <variablelist>
1369 <title></title>
1370 <varlistentry>
1371 <term>Returns:</term>
1372 <listitem>
1373 <para>
1374 <code><phrase role="special">!</phrase> <phrase role="special">(</phrase><phrase
1375 role="identifier">other</phrase> <phrase role="special">&lt;</phrase>
1376 <phrase role="special">*</phrase> <phrase role="keyword">this</phrase><phrase
1377 role="special">)</phrase></code>
1378 </para>
1379 </listitem>
1380 </varlistentry>
1381 <varlistentry>
1382 <term>Throws:</term>
1383 <listitem>
1384 <para>
1385 Nothing.
1386 </para>
1387 </listitem>
1388 </varlistentry>
1389 </variablelist>
1390 <para>
1391 <bridgehead renderas="sect4" id="id_operator_greater_equal_bridgehead">
1392 <phrase id="id_operator_greater_equal"/>
1393 <link linkend="id_operator_greater_equal">Member
1394 function <code>operator&gt;=</code>()</link>
1395 </bridgehead>
1396 </para>
1397 <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>
1398 </programlisting>
1399 <variablelist>
1400 <title></title>
1401 <varlistentry>
1402 <term>Returns:</term>
1403 <listitem>
1404 <para>
1405 <code><phrase role="special">!</phrase> <phrase role="special">(*</phrase>
1406 <phrase role="keyword">this</phrase> <phrase role="special">&lt;</phrase>
1407 <phrase role="identifier">other</phrase><phrase role="special">)</phrase></code>
1408 </para>
1409 </listitem>
1410 </varlistentry>
1411 <varlistentry>
1412 <term>Throws:</term>
1413 <listitem>
1414 <para>
1415 Nothing.
1416 </para>
1417 </listitem>
1418 </varlistentry>
1419 </variablelist>
1420 <bridgehead renderas="sect4" id="fiber.fiber_mgmt.id.h1">
1421 <phrase id="fiber.fiber_mgmt.id.operator_lt__lt_"/><link linkend="fiber.fiber_mgmt.id.operator_lt__lt_">operator&lt;&lt;</link>
1422 </bridgehead>
1423 <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>
1424 <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>
1425 <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>
1426 </programlisting>
1427 <variablelist>
1428 <title></title>
1429 <varlistentry>
1430 <term>Efects:</term>
1431 <listitem>
1432 <para>
1433 Writes the representation of <code><phrase role="identifier">other</phrase></code>
1434 to stream <code><phrase role="identifier">os</phrase></code>. The representation
1435 is unspecified.
1436 </para>
1437 </listitem>
1438 </varlistentry>
1439 <varlistentry>
1440 <term>Returns:</term>
1441 <listitem>
1442 <para>
1443 <code><phrase role="identifier">os</phrase></code>
1444 </para>
1445 </listitem>
1446 </varlistentry>
1447 </variablelist>
1448 </section>
1449 <section id="fiber.fiber_mgmt.this_fiber">
1450 <title><link linkend="fiber.fiber_mgmt.this_fiber">Namespace this_fiber</link></title>
1451 <para>
1452 In general, <code><phrase role="identifier">this_fiber</phrase></code> operations
1453 may be called from the <quote>main</quote> fiber &mdash; the fiber on which function
1454 <code><phrase role="identifier">main</phrase><phrase role="special">()</phrase></code>
1455 is entered &mdash; as well as from an explicitly-launched thread&#8217;s thread-function.
1456 That is, in many respects the main fiber on each thread can be treated like
1457 an explicitly-launched fiber.
1458 </para>
1459 <programlisting><phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase>
1460 <phrase role="keyword">namespace</phrase> <phrase role="identifier">this_fiber</phrase> <phrase role="special">{</phrase>
1461
1462 <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>
1463 <phrase role="keyword">void</phrase> <phrase role="identifier">yield</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
1464 <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>
1465 <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>
1466 <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>
1467 <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>
1468 <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>
1469 <phrase role="identifier">PROPS</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">properties</phrase><phrase role="special">();</phrase>
1470
1471 <phrase role="special">}}</phrase>
1472 </programlisting>
1473 <para>
1474 <bridgehead renderas="sect4" id="this_fiber_get_id_bridgehead">
1475 <phrase id="this_fiber_get_id"/>
1476 <link linkend="this_fiber_get_id">Non-member
1477 function <code>this_fiber::get_id()</code></link>
1478 </bridgehead>
1479 </para>
1480 <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>
1481
1482 <phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase>
1483 <phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase>
1484
1485 <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>
1486
1487 <phrase role="special">}}</phrase>
1488 </programlisting>
1489 <variablelist>
1490 <title></title>
1491 <varlistentry>
1492 <term>Returns:</term>
1493 <listitem>
1494 <para>
1495 An instance of <link linkend="class_fiber_id"><code><phrase role="identifier">fiber</phrase><phrase
1496 role="special">::</phrase><phrase role="identifier">id</phrase></code></link> that
1497 represents the currently executing fiber.
1498 </para>
1499 </listitem>
1500 </varlistentry>
1501 <varlistentry>
1502 <term>Throws:</term>
1503 <listitem>
1504 <para>
1505 Nothing.
1506 </para>
1507 </listitem>
1508 </varlistentry>
1509 </variablelist>
1510 <para>
1511 <bridgehead renderas="sect4" id="this_fiber_sleep_until_bridgehead">
1512 <phrase id="this_fiber_sleep_until"/>
1513 <link linkend="this_fiber_sleep_until">Non-member
1514 function <code>this_fiber::sleep_until()</code></link>
1515 </bridgehead>
1516 </para>
1517 <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>
1518
1519 <phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase>
1520 <phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase>
1521
1522 <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>
1523 <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>
1524
1525 <phrase role="special">}}</phrase>
1526 </programlisting>
1527 <variablelist>
1528 <title></title>
1529 <varlistentry>
1530 <term>Effects:</term>
1531 <listitem>
1532 <para>
1533 Suspends the current fiber until the time point specified by <code><phrase
1534 role="identifier">abs_time</phrase></code> has been reached.
1535 </para>
1536 </listitem>
1537 </varlistentry>
1538 <varlistentry>
1539 <term>Throws:</term>
1540 <listitem>
1541 <para>
1542 timeout-related exceptions.
1543 </para>
1544 </listitem>
1545 </varlistentry>
1546 <varlistentry>
1547 <term>Note:</term>
1548 <listitem>
1549 <para>
1550 The current fiber will not resume before <code><phrase role="identifier">abs_time</phrase></code>,
1551 but there are no guarantees about how soon after <code><phrase role="identifier">abs_time</phrase></code>
1552 it might resume.
1553 </para>
1554 </listitem>
1555 </varlistentry>
1556 <varlistentry>
1557 <term>Note:</term>
1558 <listitem>
1559 <para>
1560 <quote>timeout-related exceptions</quote> are as defined in the C++
1561 Standard, section <emphasis role="bold">30.2.4 Timing specifications
1562 [thread.req.timing]</emphasis>: <quote>A function that takes an argument
1563 which specifies a timeout will throw if, during its execution, a clock,
1564 time point, or time duration throws an exception. Such exceptions are
1565 referred to as <emphasis>timeout-related exceptions.</emphasis></quote>
1566 </para>
1567 </listitem>
1568 </varlistentry>
1569 </variablelist>
1570 <para>
1571 <bridgehead renderas="sect4" id="this_fiber_sleep_for_bridgehead">
1572 <phrase id="this_fiber_sleep_for"/>
1573 <link linkend="this_fiber_sleep_for">Non-member
1574 function <code>this_fiber::sleep_for()</code></link>
1575 </bridgehead>
1576 </para>
1577 <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>
1578
1579 <phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase>
1580 <phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase>
1581
1582 <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>
1583 <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>
1584
1585 <phrase role="special">}}</phrase>
1586 </programlisting>
1587 <variablelist>
1588 <title></title>
1589 <varlistentry>
1590 <term>Effects:</term>
1591 <listitem>
1592 <para>
1593 Suspends the current fiber until the time duration specified by <code><phrase
1594 role="identifier">rel_time</phrase></code> has elapsed.
1595 </para>
1596 </listitem>
1597 </varlistentry>
1598 <varlistentry>
1599 <term>Throws:</term>
1600 <listitem>
1601 <para>
1602 timeout-related exceptions.
1603 </para>
1604 </listitem>
1605 </varlistentry>
1606 <varlistentry>
1607 <term>Note:</term>
1608 <listitem>
1609 <para>
1610 The current fiber will not resume before <code><phrase role="identifier">rel_time</phrase></code>
1611 has elapsed, but there are no guarantees about how soon after that
1612 it might resume.
1613 </para>
1614 </listitem>
1615 </varlistentry>
1616 </variablelist>
1617 <para>
1618 <bridgehead renderas="sect4" id="this_fiber_yield_bridgehead">
1619 <phrase id="this_fiber_yield"/>
1620 <link linkend="this_fiber_yield">Non-member function
1621 <code>this_fiber::yield()</code></link>
1622 </bridgehead>
1623 </para>
1624 <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>
1625
1626 <phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase>
1627 <phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase>
1628
1629 <phrase role="keyword">void</phrase> <phrase role="identifier">yield</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
1630
1631 <phrase role="special">}}</phrase>
1632 </programlisting>
1633 <variablelist>
1634 <title></title>
1635 <varlistentry>
1636 <term>Effects:</term>
1637 <listitem>
1638 <para>
1639 Reliquishes execution control, allowing other fibers to run.
1640 </para>
1641 </listitem>
1642 </varlistentry>
1643 <varlistentry>
1644 <term>Throws:</term>
1645 <listitem>
1646 <para>
1647 Nothing.
1648 </para>
1649 </listitem>
1650 </varlistentry>
1651 <varlistentry>
1652 <term>Note:</term>
1653 <listitem>
1654 <para>
1655 A fiber that calls <code><phrase role="identifier">yield</phrase><phrase
1656 role="special">()</phrase></code> is not suspended: it is immediately
1657 passed to the scheduler as ready to run.
1658 </para>
1659 </listitem>
1660 </varlistentry>
1661 </variablelist>
1662 <para>
1663 <bridgehead renderas="sect4" id="this_fiber_properties_bridgehead">
1664 <phrase id="this_fiber_properties"/>
1665 <link linkend="this_fiber_properties">Non-member
1666 function <code>this_fiber::properties()</code></link>
1667 </bridgehead>
1668 </para>
1669 <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>
1670
1671 <phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase>
1672 <phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase>
1673
1674 <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>
1675 <phrase role="identifier">PROPS</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">properties</phrase><phrase role="special">();</phrase>
1676
1677 <phrase role="special">}}</phrase>
1678 </programlisting>
1679 <variablelist>
1680 <title></title>
1681 <varlistentry>
1682 <term>Preconditions:</term>
1683 <listitem>
1684 <para>
1685 <link linkend="use_scheduling_algorithm"><code>use_scheduling_algorithm()</code></link> has been called from
1686 this thread with a subclass of <link linkend="class_algorithm_with_properties"><code>algorithm_with_properties&lt;&gt;</code></link> with
1687 the same template argument <code><phrase role="identifier">PROPS</phrase></code>.
1688 </para>
1689 </listitem>
1690 </varlistentry>
1691 <varlistentry>
1692 <term>Returns:</term>
1693 <listitem>
1694 <para>
1695 a reference to the scheduler properties instance for the currently
1696 running fiber.
1697 </para>
1698 </listitem>
1699 </varlistentry>
1700 <varlistentry>
1701 <term>Throws:</term>
1702 <listitem>
1703 <para>
1704 <code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase
1705 role="identifier">bad_cast</phrase></code> if <code><phrase role="identifier">use_scheduling_algorithm</phrase><phrase
1706 role="special">()</phrase></code> was called with an <code><phrase
1707 role="identifier">algorithm_with_properties</phrase></code> subclass
1708 with some other template parameter than <code><phrase role="identifier">PROPS</phrase></code>.
1709 </para>
1710 </listitem>
1711 </varlistentry>
1712 <varlistentry>
1713 <term>Note:</term>
1714 <listitem>
1715 <para>
1716 <link linkend="class_algorithm_with_properties"><code>algorithm_with_properties&lt;&gt;</code></link> provides
1717 a way for a user-coded scheduler to associate extended properties,
1718 such as priority, with a fiber instance. This function allows access
1719 to those user-provided properties.
1720 </para>
1721 </listitem>
1722 </varlistentry>
1723 <varlistentry>
1724 <term>Note:</term>
1725 <listitem>
1726 <para>
1727 The first time this function is called from the main fiber of a thread,
1728 it may internally yield, permitting other fibers to run.
1729 </para>
1730 </listitem>
1731 </varlistentry>
1732 <varlistentry>
1733 <term>See also:</term>
1734 <listitem>
1735 <para>
1736 <link linkend="custom">Customization</link>
1737 </para>
1738 </listitem>
1739 </varlistentry>
1740 </variablelist>
1741 </section>
1742 </section>
1743 <section id="fiber.scheduling">
1744 <title><anchor id="scheduling"/><link linkend="fiber.scheduling">Scheduling</link></title>
1745 <para>
1746 The fibers in a thread are coordinated by a fiber manager. Fibers trade control
1747 cooperatively, rather than preemptively: the currently-running fiber retains
1748 control until it invokes some operation that passes control to the manager.
1749 Each time a fiber suspends (or yields), the fiber manager consults a scheduler
1750 to determine which fiber will run next.
1751 </para>
1752 <para>
1753 <emphasis role="bold">Boost.Fiber</emphasis> provides the fiber manager, but
1754 the scheduler is a customization point. (See <link linkend="custom">Customization</link>.)
1755 </para>
1756 <para>
1757 Each thread has its own scheduler. Different threads in a process may use different
1758 schedulers. By default, <emphasis role="bold">Boost.Fiber</emphasis> implicitly
1759 instantiates <link linkend="class_round_robin"><code>round_robin</code></link> as the scheduler for each thread.
1760 </para>
1761 <para>
1762 You are explicitly permitted to code your own <link linkend="class_algorithm"><code>algorithm</code></link> subclass.
1763 For the most part, your <code><phrase role="identifier">algorithm</phrase></code>
1764 subclass need not defend against cross-thread calls: the fiber manager intercepts
1765 and defers such calls. Most <code><phrase role="identifier">algorithm</phrase></code>
1766 methods are only ever directly called from the thread whose fibers it is managing
1767 &mdash; with exceptions as documented below.
1768 </para>
1769 <para>
1770 Your <code><phrase role="identifier">algorithm</phrase></code> subclass is
1771 engaged on a particular thread by calling <link linkend="use_scheduling_algorithm"><code>use_scheduling_algorithm()</code></link>:
1772 </para>
1773 <programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">thread_fn</phrase><phrase role="special">()</phrase> <phrase role="special">{</phrase>
1774 <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>
1775 <phrase role="special">...</phrase>
1776 <phrase role="special">}</phrase>
1777 </programlisting>
1778 <para>
1779 A scheduler class must implement interface <link linkend="class_algorithm"><code>algorithm</code></link>. <emphasis
1780 role="bold">Boost.Fiber</emphasis> provides one scheduler: <link linkend="class_round_robin"><code>round_robin</code></link>.
1781 </para>
1782 <para>
1783 <bridgehead renderas="sect4" id="class_algorithm_bridgehead">
1784 <phrase id="class_algorithm"/>
1785 <link linkend="class_algorithm">Class <code>algorithm</code></link>
1786 </bridgehead>
1787 </para>
1788 <para>
1789 <code><phrase role="identifier">algorithm</phrase></code> is the abstract base
1790 class defining the interface that a fiber scheduler must implement.
1791 </para>
1792 <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>
1793
1794 <phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase>
1795 <phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase>
1796 <phrase role="keyword">namespace</phrase> <phrase role="identifier">algo</phrase> <phrase role="special">{</phrase>
1797
1798 <phrase role="keyword">struct</phrase> <phrase role="identifier">algorithm</phrase> <phrase role="special">{</phrase>
1799 <phrase role="keyword">virtual</phrase> <phrase role="special">~</phrase><phrase role="identifier">algorithm</phrase><phrase role="special">();</phrase>
1800
1801 <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>
1802
1803 <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>
1804
1805 <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>
1806
1807 <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>
1808
1809 <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>
1810 <phrase role="special">};</phrase>
1811
1812 <phrase role="special">}}}</phrase>
1813 </programlisting>
1814 <para>
1815 <bridgehead renderas="sect4" id="algorithm_awakened_bridgehead">
1816 <phrase id="algorithm_awakened"/>
1817 <link linkend="algorithm_awakened">Member function
1818 <code>awakened</code>()</link>
1819 </bridgehead>
1820 </para>
1821 <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>
1822 </programlisting>
1823 <variablelist>
1824 <title></title>
1825 <varlistentry>
1826 <term>Effects:</term>
1827 <listitem>
1828 <para>
1829 Informs the scheduler that fiber <code><phrase role="identifier">f</phrase></code>
1830 is ready to run. Fiber <code><phrase role="identifier">f</phrase></code>
1831 might be newly launched, or it might have been blocked but has just been
1832 awakened, or it might have called <link linkend="this_fiber_yield"><code>this_fiber::yield()</code></link>.
1833 </para>
1834 </listitem>
1835 </varlistentry>
1836 <varlistentry>
1837 <term>Note:</term>
1838 <listitem>
1839 <para>
1840 This method advises the scheduler to add fiber <code><phrase role="identifier">f</phrase></code>
1841 to its collection of fibers ready to run. A typical scheduler implementation
1842 places <code><phrase role="identifier">f</phrase></code> into a queue.
1843 </para>
1844 </listitem>
1845 </varlistentry>
1846 <varlistentry>
1847 <term>See also:</term>
1848 <listitem>
1849 <para>
1850 <link linkend="class_round_robin"><code>round_robin</code></link>
1851 </para>
1852 </listitem>
1853 </varlistentry>
1854 </variablelist>
1855 <para>
1856 <bridgehead renderas="sect4" id="algorithm_pick_next_bridgehead">
1857 <phrase id="algorithm_pick_next"/>
1858 <link linkend="algorithm_pick_next">Member
1859 function <code>pick_next</code>()</link>
1860 </bridgehead>
1861 </para>
1862 <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>
1863 </programlisting>
1864 <variablelist>
1865 <title></title>
1866 <varlistentry>
1867 <term>Returns:</term>
1868 <listitem>
1869 <para>
1870 the fiber which is to be resumed next, or <code><phrase role="keyword">nullptr</phrase></code>
1871 if there is no ready fiber.
1872 </para>
1873 </listitem>
1874 </varlistentry>
1875 <varlistentry>
1876 <term>Note:</term>
1877 <listitem>
1878 <para>
1879 This is where the scheduler actually specifies the fiber which is to
1880 run next. A typical scheduler implementation chooses the head of the
1881 ready queue.
1882 </para>
1883 </listitem>
1884 </varlistentry>
1885 <varlistentry>
1886 <term>See also:</term>
1887 <listitem>
1888 <para>
1889 <link linkend="class_round_robin"><code>round_robin</code></link>
1890 </para>
1891 </listitem>
1892 </varlistentry>
1893 </variablelist>
1894 <para>
1895 <bridgehead renderas="sect4" id="algorithm_has_ready_fibers_bridgehead">
1896 <phrase id="algorithm_has_ready_fibers"/>
1897 <link linkend="algorithm_has_ready_fibers">Member
1898 function <code>has_ready_fibers</code>()</link>
1899 </bridgehead>
1900 </para>
1901 <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>
1902 </programlisting>
1903 <variablelist>
1904 <title></title>
1905 <varlistentry>
1906 <term>Returns:</term>
1907 <listitem>
1908 <para>
1909 <code><phrase role="keyword">true</phrase></code> if scheduler has fibers
1910 ready to run.
1911 </para>
1912 </listitem>
1913 </varlistentry>
1914 </variablelist>
1915 <para>
1916 <bridgehead renderas="sect4" id="algorithm_suspend_until_bridgehead">
1917 <phrase id="algorithm_suspend_until"/>
1918 <link linkend="algorithm_suspend_until">Member
1919 function <code>suspend_until</code>()</link>
1920 </bridgehead>
1921 </para>
1922 <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>
1923 </programlisting>
1924 <variablelist>
1925 <title></title>
1926 <varlistentry>
1927 <term>Effects:</term>
1928 <listitem>
1929 <para>
1930 Informs the scheduler that no fiber will be ready until time-point <code><phrase
1931 role="identifier">abs_time</phrase></code>.
1932 </para>
1933 </listitem>
1934 </varlistentry>
1935 <varlistentry>
1936 <term>Note:</term>
1937 <listitem>
1938 <para>
1939 This method allows a custom scheduler to yield control to the containing
1940 environment in whatever way makes sense. The fiber manager is stating
1941 that <code><phrase role="identifier">suspend_until</phrase><phrase role="special">()</phrase></code>
1942 need not return until <code><phrase role="identifier">abs_time</phrase></code>
1943 &mdash; or <link linkend="algorithm_notify"><code>algorithm::notify()</code></link> is called &mdash; whichever comes first.
1944 The interaction with <code><phrase role="identifier">notify</phrase><phrase
1945 role="special">()</phrase></code> means that, for instance, calling
1946 <ulink url="http://en.cppreference.com/w/cpp/thread/sleep_until"><code><phrase
1947 role="identifier">std</phrase><phrase role="special">::</phrase><phrase
1948 role="identifier">this_thread</phrase><phrase role="special">::</phrase><phrase
1949 role="identifier">sleep_until</phrase><phrase role="special">(</phrase><phrase
1950 role="identifier">abs_time</phrase><phrase role="special">)</phrase></code></ulink>
1951 would be too simplistic. <link linkend="round_robin_suspend_until"><code>round_robin::suspend_until()</code></link> uses
1952 a <ulink url="http://en.cppreference.com/w/cpp/thread/condition_variable"><code><phrase
1953 role="identifier">std</phrase><phrase role="special">::</phrase><phrase
1954 role="identifier">condition_variable</phrase></code></ulink> to coordinate
1955 with <link linkend="round_robin_notify"><code>round_robin::notify()</code></link>.
1956 </para>
1957 </listitem>
1958 </varlistentry>
1959 <varlistentry>
1960 <term>Note:</term>
1961 <listitem>
1962 <para>
1963 Given that <code><phrase role="identifier">notify</phrase><phrase role="special">()</phrase></code>
1964 might be called from another thread, your <code><phrase role="identifier">suspend_until</phrase><phrase
1965 role="special">()</phrase></code> implementation &mdash; like the rest of your
1966 <code><phrase role="identifier">algorithm</phrase></code> implementation
1967 &mdash; must guard any data it shares with your <code><phrase role="identifier">notify</phrase><phrase
1968 role="special">()</phrase></code> implementation.
1969 </para>
1970 </listitem>
1971 </varlistentry>
1972 </variablelist>
1973 <para>
1974 <bridgehead renderas="sect4" id="algorithm_notify_bridgehead">
1975 <phrase id="algorithm_notify"/>
1976 <link linkend="algorithm_notify">Member function
1977 <code>notify</code>()</link>
1978 </bridgehead>
1979 </para>
1980 <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>
1981 </programlisting>
1982 <variablelist>
1983 <title></title>
1984 <varlistentry>
1985 <term>Effects:</term>
1986 <listitem>
1987 <para>
1988 Requests the scheduler to return from a pending call to <link linkend="algorithm_suspend_until"><code>algorithm::suspend_until()</code></link>.
1989 </para>
1990 </listitem>
1991 </varlistentry>
1992 <varlistentry>
1993 <term>Note:</term>
1994 <listitem>
1995 <para>
1996 Alone among the <code><phrase role="identifier">algorithm</phrase></code>
1997 methods, <code><phrase role="identifier">notify</phrase><phrase role="special">()</phrase></code>
1998 may be called from another thread. Your <code><phrase role="identifier">notify</phrase><phrase
1999 role="special">()</phrase></code> implementation must guard any data
2000 it shares with the rest of your <code><phrase role="identifier">algorithm</phrase></code>
2001 implementation.
2002 </para>
2003 </listitem>
2004 </varlistentry>
2005 </variablelist>
2006 <para>
2007 <bridgehead renderas="sect4" id="class_round_robin_bridgehead">
2008 <phrase id="class_round_robin"/>
2009 <link linkend="class_round_robin">Class <code>round_robin</code></link>
2010 </bridgehead>
2011 </para>
2012 <para>
2013 This class implements <link linkend="class_algorithm"><code>algorithm</code></link>, scheduling fibers in round-robin
2014 fashion.
2015 </para>
2016 <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>
2017
2018 <phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase>
2019 <phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase>
2020 <phrase role="keyword">namespace</phrase> <phrase role="identifier">algo</phrase> <phrase role="special">{</phrase>
2021
2022 <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>
2023 <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>
2024
2025 <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>
2026
2027 <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>
2028
2029 <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>
2030
2031 <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>
2032 <phrase role="special">};</phrase>
2033
2034 <phrase role="special">}}}</phrase>
2035 </programlisting>
2036 <para>
2037 <bridgehead renderas="sect4" id="round_robin_awakened_bridgehead">
2038 <phrase id="round_robin_awakened"/>
2039 <link linkend="round_robin_awakened">Member
2040 function <code>awakened</code>()</link>
2041 </bridgehead>
2042 </para>
2043 <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>
2044 </programlisting>
2045 <variablelist>
2046 <title></title>
2047 <varlistentry>
2048 <term>Effects:</term>
2049 <listitem>
2050 <para>
2051 Enqueues fiber <code><phrase role="identifier">f</phrase></code> onto
2052 a ready queue.
2053 </para>
2054 </listitem>
2055 </varlistentry>
2056 <varlistentry>
2057 <term>Throws:</term>
2058 <listitem>
2059 <para>
2060 Nothing.
2061 </para>
2062 </listitem>
2063 </varlistentry>
2064 </variablelist>
2065 <para>
2066 <bridgehead renderas="sect4" id="round_robin_pick_next_bridgehead">
2067 <phrase id="round_robin_pick_next"/>
2068 <link linkend="round_robin_pick_next">Member
2069 function <code>pick_next</code>()</link>
2070 </bridgehead>
2071 </para>
2072 <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>
2073 </programlisting>
2074 <variablelist>
2075 <title></title>
2076 <varlistentry>
2077 <term>Returns:</term>
2078 <listitem>
2079 <para>
2080 the fiber at the head of the ready queue, or <code><phrase role="keyword">nullptr</phrase></code>
2081 if the queue is empty.
2082 </para>
2083 </listitem>
2084 </varlistentry>
2085 <varlistentry>
2086 <term>Throws:</term>
2087 <listitem>
2088 <para>
2089 Nothing.
2090 </para>
2091 </listitem>
2092 </varlistentry>
2093 <varlistentry>
2094 <term>Note:</term>
2095 <listitem>
2096 <para>
2097 Placing ready fibers onto the tail of a queue, and returning them from
2098 the head of that queue, shares the thread between ready fibers in round-robin
2099 fashion.
2100 </para>
2101 </listitem>
2102 </varlistentry>
2103 </variablelist>
2104 <para>
2105 <bridgehead renderas="sect4" id="round_robin_has_ready_fibers_bridgehead">
2106 <phrase id="round_robin_has_ready_fibers"/>
2107 <link linkend="round_robin_has_ready_fibers">Member
2108 function <code>has_ready_fibers</code>()</link>
2109 </bridgehead>
2110 </para>
2111 <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>
2112 </programlisting>
2113 <variablelist>
2114 <title></title>
2115 <varlistentry>
2116 <term>Returns:</term>
2117 <listitem>
2118 <para>
2119 <code><phrase role="keyword">true</phrase></code> if scheduler has fibers
2120 ready to run.
2121 </para>
2122 </listitem>
2123 </varlistentry>
2124 <varlistentry>
2125 <term>Throws:</term>
2126 <listitem>
2127 <para>
2128 Nothing.
2129 </para>
2130 </listitem>
2131 </varlistentry>
2132 </variablelist>
2133 <para>
2134 <bridgehead renderas="sect4" id="round_robin_suspend_until_bridgehead">
2135 <phrase id="round_robin_suspend_until"/>
2136 <link linkend="round_robin_suspend_until">Member
2137 function <code>suspend_until</code>()</link>
2138 </bridgehead>
2139 </para>
2140 <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>
2141 </programlisting>
2142 <variablelist>
2143 <title></title>
2144 <varlistentry>
2145 <term>Effects:</term>
2146 <listitem>
2147 <para>
2148 Informs <code><phrase role="identifier">round_robin</phrase></code> that
2149 no ready fiber will be available until time-point <code><phrase role="identifier">abs_time</phrase></code>.
2150 This implementation blocks in <ulink url="http://en.cppreference.com/w/cpp/thread/condition_variable/wait_until"><code><phrase
2151 role="identifier">std</phrase><phrase role="special">::</phrase><phrase
2152 role="identifier">condition_variable</phrase><phrase role="special">::</phrase><phrase
2153 role="identifier">wait_until</phrase><phrase role="special">()</phrase></code></ulink>.
2154 </para>
2155 </listitem>
2156 </varlistentry>
2157 <varlistentry>
2158 <term>Throws:</term>
2159 <listitem>
2160 <para>
2161 Nothing.
2162 </para>
2163 </listitem>
2164 </varlistentry>
2165 </variablelist>
2166 <para>
2167 <bridgehead renderas="sect4" id="round_robin_notify_bridgehead">
2168 <phrase id="round_robin_notify"/>
2169 <link linkend="round_robin_notify">Member function
2170 <code>notify</code>()</link>
2171 </bridgehead>
2172 </para>
2173 <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>
2174 </programlisting>
2175 <variablelist>
2176 <title></title>
2177 <varlistentry>
2178 <term>Effects:</term>
2179 <listitem>
2180 <para>
2181 Wake up a pending call to <link linkend="round_robin_suspend_until"><code>round_robin::suspend_until()</code></link>,
2182 some fibers might be ready. This implementation wakes <code><phrase role="identifier">suspend_until</phrase><phrase
2183 role="special">()</phrase></code> via <ulink url="http://en.cppreference.com/w/cpp/thread/condition_variable/notify_all"><code><phrase
2184 role="identifier">std</phrase><phrase role="special">::</phrase><phrase
2185 role="identifier">condition_variable</phrase><phrase role="special">::</phrase><phrase
2186 role="identifier">notify_all</phrase><phrase role="special">()</phrase></code></ulink>.
2187 </para>
2188 </listitem>
2189 </varlistentry>
2190 <varlistentry>
2191 <term>Throws:</term>
2192 <listitem>
2193 <para>
2194 Nothing.
2195 </para>
2196 </listitem>
2197 </varlistentry>
2198 </variablelist>
2199 <para>
2200 <bridgehead renderas="sect4" id="class_shared_work_bridgehead">
2201 <phrase id="class_shared_work"/>
2202 <link linkend="class_shared_work">Class <code>shared_work</code></link>
2203 </bridgehead>
2204 </para>
2205 <para>
2206 This class implements <link linkend="class_algorithm"><code>algorithm</code></link>; ready fibers are shared between
2207 all instances (running on different threads) of shared_work.
2208 </para>
2209 <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>
2210
2211 <phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase>
2212 <phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase>
2213 <phrase role="keyword">namespace</phrase> <phrase role="identifier">algo</phrase> <phrase role="special">{</phrase>
2214
2215 <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>
2216 <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>
2217
2218 <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>
2219
2220 <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>
2221
2222 <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>
2223
2224 <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>
2225 <phrase role="special">};</phrase>
2226
2227 <phrase role="special">}}}</phrase>
2228 </programlisting>
2229 <para>
2230 <bridgehead renderas="sect4" id="shared_work_awakened_bridgehead">
2231 <phrase id="shared_work_awakened"/>
2232 <link linkend="shared_work_awakened">Member
2233 function <code>awakened</code>()</link>
2234 </bridgehead>
2235 </para>
2236 <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>
2237 </programlisting>
2238 <variablelist>
2239 <title></title>
2240 <varlistentry>
2241 <term>Effects:</term>
2242 <listitem>
2243 <para>
2244 Enqueues fiber <code><phrase role="identifier">f</phrase></code> onto
2245 the shared ready queue.
2246 </para>
2247 </listitem>
2248 </varlistentry>
2249 <varlistentry>
2250 <term>Throws:</term>
2251 <listitem>
2252 <para>
2253 Nothing.
2254 </para>
2255 </listitem>
2256 </varlistentry>
2257 </variablelist>
2258 <para>
2259 <bridgehead renderas="sect4" id="shared_work_pick_next_bridgehead">
2260 <phrase id="shared_work_pick_next"/>
2261 <link linkend="shared_work_pick_next">Member
2262 function <code>pick_next</code>()</link>
2263 </bridgehead>
2264 </para>
2265 <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>
2266 </programlisting>
2267 <variablelist>
2268 <title></title>
2269 <varlistentry>
2270 <term>Returns:</term>
2271 <listitem>
2272 <para>
2273 the fiber at the head of the ready queue, or <code><phrase role="keyword">nullptr</phrase></code>
2274 if the queue is empty.
2275 </para>
2276 </listitem>
2277 </varlistentry>
2278 <varlistentry>
2279 <term>Throws:</term>
2280 <listitem>
2281 <para>
2282 Nothing.
2283 </para>
2284 </listitem>
2285 </varlistentry>
2286 <varlistentry>
2287 <term>Note:</term>
2288 <listitem>
2289 <para>
2290 Placing ready fibers onto the tail of the shared queue, and returning
2291 them from the head of that queue, shares the thread between ready fibers
2292 in round-robin fashion.
2293 </para>
2294 </listitem>
2295 </varlistentry>
2296 </variablelist>
2297 <para>
2298 <bridgehead renderas="sect4" id="shared_work_has_ready_fibers_bridgehead">
2299 <phrase id="shared_work_has_ready_fibers"/>
2300 <link linkend="shared_work_has_ready_fibers">Member
2301 function <code>has_ready_fibers</code>()</link>
2302 </bridgehead>
2303 </para>
2304 <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>
2305 </programlisting>
2306 <variablelist>
2307 <title></title>
2308 <varlistentry>
2309 <term>Returns:</term>
2310 <listitem>
2311 <para>
2312 <code><phrase role="keyword">true</phrase></code> if scheduler has fibers
2313 ready to run.
2314 </para>
2315 </listitem>
2316 </varlistentry>
2317 <varlistentry>
2318 <term>Throws:</term>
2319 <listitem>
2320 <para>
2321 Nothing.
2322 </para>
2323 </listitem>
2324 </varlistentry>
2325 </variablelist>
2326 <para>
2327 <bridgehead renderas="sect4" id="shared_work_suspend_until_bridgehead">
2328 <phrase id="shared_work_suspend_until"/>
2329 <link linkend="shared_work_suspend_until">Member
2330 function <code>suspend_until</code>()</link>
2331 </bridgehead>
2332 </para>
2333 <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>
2334 </programlisting>
2335 <variablelist>
2336 <title></title>
2337 <varlistentry>
2338 <term>Effects:</term>
2339 <listitem>
2340 <para>
2341 Informs <code><phrase role="identifier">shared_work</phrase></code> that
2342 no ready fiber will be available until time-point <code><phrase role="identifier">abs_time</phrase></code>.
2343 This implementation blocks in <ulink url="http://en.cppreference.com/w/cpp/thread/condition_variable/wait_until"><code><phrase
2344 role="identifier">std</phrase><phrase role="special">::</phrase><phrase
2345 role="identifier">condition_variable</phrase><phrase role="special">::</phrase><phrase
2346 role="identifier">wait_until</phrase><phrase role="special">()</phrase></code></ulink>.
2347 </para>
2348 </listitem>
2349 </varlistentry>
2350 <varlistentry>
2351 <term>Throws:</term>
2352 <listitem>
2353 <para>
2354 Nothing.
2355 </para>
2356 </listitem>
2357 </varlistentry>
2358 </variablelist>
2359 <para>
2360 <bridgehead renderas="sect4" id="shared_work_notify_bridgehead">
2361 <phrase id="shared_work_notify"/>
2362 <link linkend="shared_work_notify">Member function
2363 <code>notify</code>()</link>
2364 </bridgehead>
2365 </para>
2366 <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>
2367 </programlisting>
2368 <variablelist>
2369 <title></title>
2370 <varlistentry>
2371 <term>Effects:</term>
2372 <listitem>
2373 <para>
2374 Wake up a pending call to <link linkend="shared_work_suspend_until"><code>shared_work::suspend_until()</code></link>,
2375 some fibers might be ready. This implementation wakes <code><phrase role="identifier">suspend_until</phrase><phrase
2376 role="special">()</phrase></code> via <ulink url="http://en.cppreference.com/w/cpp/thread/condition_variable/notify_all"><code><phrase
2377 role="identifier">std</phrase><phrase role="special">::</phrase><phrase
2378 role="identifier">condition_variable</phrase><phrase role="special">::</phrase><phrase
2379 role="identifier">notify_all</phrase><phrase role="special">()</phrase></code></ulink>.
2380 </para>
2381 </listitem>
2382 </varlistentry>
2383 <varlistentry>
2384 <term>Throws:</term>
2385 <listitem>
2386 <para>
2387 Nothing.
2388 </para>
2389 </listitem>
2390 </varlistentry>
2391 </variablelist>
2392 <bridgehead renderas="sect3" id="fiber.scheduling.h0">
2393 <phrase id="fiber.scheduling.custom_scheduler_fiber_properties"/><link linkend="fiber.scheduling.custom_scheduler_fiber_properties">Custom
2394 Scheduler Fiber Properties</link>
2395 </bridgehead>
2396 <para>
2397 A scheduler class directly derived from <link linkend="class_algorithm"><code>algorithm</code></link> can use any
2398 information available from <link linkend="class_context"><code>context</code></link> to implement the <code><phrase
2399 role="identifier">algorithm</phrase></code> interface. But a custom scheduler
2400 might need to track additional properties for a fiber. For instance, a priority-based
2401 scheduler would need to track a fiber&#8217;s priority.
2402 </para>
2403 <para>
2404 <emphasis role="bold">Boost.Fiber</emphasis> provides a mechanism by which
2405 your custom scheduler can associate custom properties with each fiber.
2406 </para>
2407 <para>
2408 <bridgehead renderas="sect4" id="class_fiber_properties_bridgehead">
2409 <phrase id="class_fiber_properties"/>
2410 <link linkend="class_fiber_properties">Class
2411 <code>fiber_properties</code></link>
2412 </bridgehead>
2413 </para>
2414 <para>
2415 A custom fiber properties class must be derived from <code><phrase role="identifier">fiber_properties</phrase></code>.
2416 </para>
2417 <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>
2418
2419 <phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase>
2420 <phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase>
2421
2422 <phrase role="keyword">class</phrase> <phrase role="identifier">fiber_properties</phrase> <phrase role="special">{</phrase>
2423 <phrase role="keyword">public</phrase><phrase role="special">:</phrase>
2424 <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>
2425
2426 <phrase role="keyword">virtual</phrase> <phrase role="special">~</phrase><phrase role="identifier">fiber_properties</phrase><phrase role="special">();</phrase>
2427
2428 <phrase role="keyword">protected</phrase><phrase role="special">:</phrase>
2429 <phrase role="keyword">void</phrase> <phrase role="identifier">notify</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
2430 <phrase role="special">};</phrase>
2431
2432 <phrase role="special">}}</phrase>
2433 </programlisting>
2434 <bridgehead renderas="sect3" id="fiber.scheduling.h1">
2435 <phrase id="fiber.scheduling.constructor"/><link linkend="fiber.scheduling.constructor">Constructor</link>
2436 </bridgehead>
2437 <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>
2438 </programlisting>
2439 <variablelist>
2440 <title></title>
2441 <varlistentry>
2442 <term>Effects:</term>
2443 <listitem>
2444 <para>
2445 Constructs base-class component of custom subclass.
2446 </para>
2447 </listitem>
2448 </varlistentry>
2449 <varlistentry>
2450 <term>Throws:</term>
2451 <listitem>
2452 <para>
2453 Nothing.
2454 </para>
2455 </listitem>
2456 </varlistentry>
2457 <varlistentry>
2458 <term>Note:</term>
2459 <listitem>
2460 <para>
2461 Your subclass constructor must accept a <code><phrase role="identifier">context</phrase><phrase
2462 role="special">*</phrase></code> and pass it to the base-class <code><phrase
2463 role="identifier">fiber_properties</phrase></code> constructor.
2464 </para>
2465 </listitem>
2466 </varlistentry>
2467 </variablelist>
2468 <para>
2469 <bridgehead renderas="sect4" id="fiber_properties_notify_bridgehead">
2470 <phrase id="fiber_properties_notify"/>
2471 <link linkend="fiber_properties_notify">Member
2472 function <code>notify</code>()</link>
2473 </bridgehead>
2474 </para>
2475 <programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">notify</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
2476 </programlisting>
2477 <variablelist>
2478 <title></title>
2479 <varlistentry>
2480 <term>Effects:</term>
2481 <listitem>
2482 <para>
2483 Pass control to the custom <link linkend="class_algorithm_with_properties"><code>algorithm_with_properties&lt;&gt;</code></link> subclass&#8217;s
2484 <link linkend="algorithm_with_properties_property_change"><code>algorithm_with_properties::property_change()</code></link> method.
2485 </para>
2486 </listitem>
2487 </varlistentry>
2488 <varlistentry>
2489 <term>Throws:</term>
2490 <listitem>
2491 <para>
2492 Nothing.
2493 </para>
2494 </listitem>
2495 </varlistentry>
2496 <varlistentry>
2497 <term>Note:</term>
2498 <listitem>
2499 <para>
2500 A custom scheduler&#8217;s <link linkend="algorithm_with_properties_pick_next"><code>algorithm_with_properties::pick_next()</code></link> method
2501 might dynamically select from the ready fibers, or <link linkend="algorithm_with_properties_awakened"><code>algorithm_with_properties::awakened()</code></link> might
2502 instead insert each ready fiber into some form of ready queue for <code><phrase
2503 role="identifier">pick_next</phrase><phrase role="special">()</phrase></code>.
2504 In the latter case, if application code modifies a fiber property (e.g.
2505 priority) that should affect that fiber&#8217;s relationship to other ready
2506 fibers, the custom scheduler must be given the opportunity to reorder
2507 its ready queue. The custom property subclass should implement an access
2508 method to modify such a property; that access method should call <code><phrase
2509 role="identifier">notify</phrase><phrase role="special">()</phrase></code>
2510 once the new property value has been stored. This passes control to the
2511 custom scheduler&#8217;s <code><phrase role="identifier">property_change</phrase><phrase
2512 role="special">()</phrase></code> method, allowing the custom scheduler
2513 to reorder its ready queue appropriately. Use at your discretion. Of
2514 course, if you define a property which does not affect the behavior of
2515 the <code><phrase role="identifier">pick_next</phrase><phrase role="special">()</phrase></code>
2516 method, you need not call <code><phrase role="identifier">notify</phrase><phrase
2517 role="special">()</phrase></code> when that property is modified.
2518 </para>
2519 </listitem>
2520 </varlistentry>
2521 </variablelist>
2522 <para>
2523 <bridgehead renderas="sect4" id="class_algorithm_with_properties_bridgehead">
2524 <phrase id="class_algorithm_with_properties"/>
2525 <link linkend="class_algorithm_with_properties">Template
2526 <code>algorithm_with_properties&lt;&gt;</code></link>
2527 </bridgehead>
2528 </para>
2529 <para>
2530 A custom scheduler that depends on a custom properties class <code><phrase
2531 role="identifier">PROPS</phrase></code> should be derived from <code><phrase
2532 role="identifier">algorithm_with_properties</phrase><phrase role="special">&lt;</phrase><phrase
2533 role="identifier">PROPS</phrase><phrase role="special">&gt;</phrase></code>.
2534 <code><phrase role="identifier">PROPS</phrase></code> should be derived from
2535 <link linkend="class_fiber_properties"><code>fiber_properties</code></link>.
2536 </para>
2537 <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>
2538
2539 <phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase>
2540 <phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase>
2541 <phrase role="keyword">namespace</phrase> <phrase role="identifier">algo</phrase> <phrase role="special">{</phrase>
2542
2543 <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>
2544 <phrase role="keyword">struct</phrase> <phrase role="identifier">algorithm_with_properties</phrase> <phrase role="special">{</phrase>
2545 <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>
2546
2547 <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>
2548
2549 <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>
2550
2551 <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>
2552
2553 <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>
2554
2555 <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>
2556
2557 <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>
2558
2559 <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>
2560 <phrase role="special">};</phrase>
2561
2562 <phrase role="special">}}}</phrase>
2563 </programlisting>
2564 <para>
2565 <bridgehead renderas="sect4" id="algorithm_with_properties_awakened_bridgehead">
2566 <phrase id="algorithm_with_properties_awakened"/>
2567 <link linkend="algorithm_with_properties_awakened">Member
2568 function <code>awakened</code>()</link>
2569 </bridgehead>
2570 </para>
2571 <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>
2572 </programlisting>
2573 <variablelist>
2574 <title></title>
2575 <varlistentry>
2576 <term>Effects:</term>
2577 <listitem>
2578 <para>
2579 Informs the scheduler that fiber <code><phrase role="identifier">f</phrase></code>
2580 is ready to run, like <link linkend="algorithm_awakened"><code>algorithm::awakened()</code></link>. Passes
2581 the fiber&#8217;s associated <code><phrase role="identifier">PROPS</phrase></code>
2582 instance.
2583 </para>
2584 </listitem>
2585 </varlistentry>
2586 <varlistentry>
2587 <term>Throws:</term>
2588 <listitem>
2589 <para>
2590 Nothing.
2591 </para>
2592 </listitem>
2593 </varlistentry>
2594 <varlistentry>
2595 <term>Note:</term>
2596 <listitem>
2597 <para>
2598 An <code><phrase role="identifier">algorithm_with_properties</phrase><phrase
2599 role="special">&lt;&gt;</phrase></code> subclass must override this method
2600 instead of <code><phrase role="identifier">algorithm</phrase><phrase
2601 role="special">::</phrase><phrase role="identifier">awakened</phrase><phrase
2602 role="special">()</phrase></code>.
2603 </para>
2604 </listitem>
2605 </varlistentry>
2606 </variablelist>
2607 <para>
2608 <bridgehead renderas="sect4" id="algorithm_with_properties_pick_next_bridgehead">
2609 <phrase id="algorithm_with_properties_pick_next"/>
2610 <link linkend="algorithm_with_properties_pick_next">Member
2611 function <code>pick_next</code>()</link>
2612 </bridgehead>
2613 </para>
2614 <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>
2615 </programlisting>
2616 <variablelist>
2617 <title></title>
2618 <varlistentry>
2619 <term>Returns:</term>
2620 <listitem>
2621 <para>
2622 the fiber which is to be resumed next, or <code><phrase role="keyword">nullptr</phrase></code>
2623 if there is no ready fiber.
2624 </para>
2625 </listitem>
2626 </varlistentry>
2627 <varlistentry>
2628 <term>Throws:</term>
2629 <listitem>
2630 <para>
2631 Nothing.
2632 </para>
2633 </listitem>
2634 </varlistentry>
2635 <varlistentry>
2636 <term>Note:</term>
2637 <listitem>
2638 <para>
2639 same as <link linkend="algorithm_pick_next"><code>algorithm::pick_next()</code></link>
2640 </para>
2641 </listitem>
2642 </varlistentry>
2643 </variablelist>
2644 <para>
2645 <bridgehead renderas="sect4" id="algorithm_with_properties_has_ready_fibers_bridgehead">
2646 <phrase id="algorithm_with_properties_has_ready_fibers"/>
2647 <link linkend="algorithm_with_properties_has_ready_fibers">Member
2648 function <code>has_ready_fibers</code>()</link>
2649 </bridgehead>
2650 </para>
2651 <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>
2652 </programlisting>
2653 <variablelist>
2654 <title></title>
2655 <varlistentry>
2656 <term>Returns:</term>
2657 <listitem>
2658 <para>
2659 <code><phrase role="keyword">true</phrase></code> if scheduler has fibers
2660 ready to run.
2661 </para>
2662 </listitem>
2663 </varlistentry>
2664 <varlistentry>
2665 <term>Throws:</term>
2666 <listitem>
2667 <para>
2668 Nothing.
2669 </para>
2670 </listitem>
2671 </varlistentry>
2672 <varlistentry>
2673 <term>Note:</term>
2674 <listitem>
2675 <para>
2676 same as <link linkend="algorithm_has_ready_fibers"><code>algorithm::has_ready_fibers()</code></link>
2677 </para>
2678 </listitem>
2679 </varlistentry>
2680 </variablelist>
2681 <para>
2682 <bridgehead renderas="sect4" id="algorithm_with_properties_suspend_until_bridgehead">
2683 <phrase id="algorithm_with_properties_suspend_until"/>
2684 <link linkend="algorithm_with_properties_suspend_until">Member
2685 function <code>suspend_until</code>()</link>
2686 </bridgehead>
2687 </para>
2688 <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>
2689 </programlisting>
2690 <variablelist>
2691 <title></title>
2692 <varlistentry>
2693 <term>Effects:</term>
2694 <listitem>
2695 <para>
2696 Informs the scheduler that no fiber will be ready until time-point <code><phrase
2697 role="identifier">abs_time</phrase></code>.
2698 </para>
2699 </listitem>
2700 </varlistentry>
2701 <varlistentry>
2702 <term>Note:</term>
2703 <listitem>
2704 <para>
2705 same as <link linkend="algorithm_suspend_until"><code>algorithm::suspend_until()</code></link>
2706 </para>
2707 </listitem>
2708 </varlistentry>
2709 </variablelist>
2710 <para>
2711 <bridgehead renderas="sect4" id="algorithm_with_properties_notify_bridgehead">
2712 <phrase id="algorithm_with_properties_notify"/>
2713 <link linkend="algorithm_with_properties_notify">Member
2714 function <code>notify</code>()</link>
2715 </bridgehead>
2716 </para>
2717 <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>
2718 </programlisting>
2719 <variablelist>
2720 <title></title>
2721 <varlistentry>
2722 <term>Effects:</term>
2723 <listitem>
2724 <para>
2725 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>.
2726 </para>
2727 </listitem>
2728 </varlistentry>
2729 <varlistentry>
2730 <term>Note:</term>
2731 <listitem>
2732 <para>
2733 same as <link linkend="algorithm_notify"><code>algorithm::notify()</code></link>
2734 </para>
2735 </listitem>
2736 </varlistentry>
2737 </variablelist>
2738 <para>
2739 <bridgehead renderas="sect4" id="algorithm_with_properties_properties_bridgehead">
2740 <phrase id="algorithm_with_properties_properties"/>
2741 <link linkend="algorithm_with_properties_properties">Member
2742 function <code>properties</code>()</link>
2743 </bridgehead>
2744 </para>
2745 <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>
2746 </programlisting>
2747 <variablelist>
2748 <title></title>
2749 <varlistentry>
2750 <term>Returns:</term>
2751 <listitem>
2752 <para>
2753 the <code><phrase role="identifier">PROPS</phrase></code> instance associated
2754 with fiber <code><phrase role="identifier">f</phrase></code>.
2755 </para>
2756 </listitem>
2757 </varlistentry>
2758 <varlistentry>
2759 <term>Throws:</term>
2760 <listitem>
2761 <para>
2762 Nothing.
2763 </para>
2764 </listitem>
2765 </varlistentry>
2766 <varlistentry>
2767 <term>Note:</term>
2768 <listitem>
2769 <para>
2770 The fiber&#8217;s associated <code><phrase role="identifier">PROPS</phrase></code>
2771 instance is already passed to <link linkend="algorithm_with_properties_awakened"><code>algorithm_with_properties::awakened()</code></link> and
2772 <link linkend="algorithm_with_properties_property_change"><code>algorithm_with_properties::property_change()</code></link>.
2773 However, every <link linkend="class_algorithm"><code>algorithm</code></link> subclass is expected to track
2774 a collection of ready <link linkend="class_context"><code>context</code></link> instances. This method allows
2775 your custom scheduler to retrieve the <link linkend="class_fiber_properties"><code>fiber_properties</code></link> subclass
2776 instance for any <code><phrase role="identifier">context</phrase></code>
2777 in its collection.
2778 </para>
2779 </listitem>
2780 </varlistentry>
2781 </variablelist>
2782 <para>
2783 <bridgehead renderas="sect4" id="algorithm_with_properties_property_change_bridgehead">
2784 <phrase id="algorithm_with_properties_property_change"/>
2785 <link linkend="algorithm_with_properties_property_change">Member
2786 function <code>property_change</code>()</link>
2787 </bridgehead>
2788 </para>
2789 <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>
2790 </programlisting>
2791 <variablelist>
2792 <title></title>
2793 <varlistentry>
2794 <term>Effects:</term>
2795 <listitem>
2796 <para>
2797 Notify the custom scheduler of a possibly-relevant change to a property
2798 belonging to fiber <code><phrase role="identifier">f</phrase></code>.
2799 <code><phrase role="identifier">properties</phrase></code> contains the
2800 new values of all relevant properties.
2801 </para>
2802 </listitem>
2803 </varlistentry>
2804 <varlistentry>
2805 <term>Throws:</term>
2806 <listitem>
2807 <para>
2808 Nothing.
2809 </para>
2810 </listitem>
2811 </varlistentry>
2812 <varlistentry>
2813 <term>Note:</term>
2814 <listitem>
2815 <para>
2816 This method is only called when a custom <link linkend="class_fiber_properties"><code>fiber_properties</code></link> subclass
2817 explicitly calls <link linkend="fiber_properties_notify"><code>fiber_properties::notify()</code></link>.
2818 </para>
2819 </listitem>
2820 </varlistentry>
2821 </variablelist>
2822 <para>
2823 <bridgehead renderas="sect4" id="algorithm_with_properties_new_properties_bridgehead">
2824 <phrase id="algorithm_with_properties_new_properties"/>
2825 <link linkend="algorithm_with_properties_new_properties">Member
2826 function <code>new_properties</code>()</link>
2827 </bridgehead>
2828 </para>
2829 <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>
2830 </programlisting>
2831 <variablelist>
2832 <title></title>
2833 <varlistentry>
2834 <term>Returns:</term>
2835 <listitem>
2836 <para>
2837 A new instance of <link linkend="class_fiber_properties"><code>fiber_properties</code></link> subclass <code><phrase
2838 role="identifier">PROPS</phrase></code>.
2839 </para>
2840 </listitem>
2841 </varlistentry>
2842 <varlistentry>
2843 <term>Note:</term>
2844 <listitem>
2845 <para>
2846 By default, <code><phrase role="identifier">algorithm_with_properties</phrase><phrase
2847 role="special">&lt;&gt;::</phrase><phrase role="identifier">new_properties</phrase><phrase
2848 role="special">()</phrase></code> simply returns <code><phrase role="keyword">new</phrase>
2849 <phrase role="identifier">PROPS</phrase><phrase role="special">(</phrase><phrase
2850 role="identifier">f</phrase><phrase role="special">)</phrase></code>,
2851 placing the <code><phrase role="identifier">PROPS</phrase></code> instance
2852 on the heap. Override this method to allocate <code><phrase role="identifier">PROPS</phrase></code>
2853 some other way. The returned <code><phrase role="identifier">fiber_properties</phrase></code>
2854 pointer must point to the <code><phrase role="identifier">PROPS</phrase></code>
2855 instance to be associated with fiber <code><phrase role="identifier">f</phrase></code>.
2856 </para>
2857 </listitem>
2858 </varlistentry>
2859 </variablelist>
2860 <para>
2861 <anchor id="context"/><bridgehead renderas="sect4" id="class_context_bridgehead">
2862 <phrase id="class_context"/>
2863 <link linkend="class_context">Class
2864 <code>context</code></link>
2865 </bridgehead>
2866 </para>
2867 <para>
2868 While you are free to treat <code><phrase role="identifier">context</phrase><phrase
2869 role="special">*</phrase></code> as an opaque token, certain <code><phrase
2870 role="identifier">context</phrase></code> members may be useful to a custom
2871 scheduler implementation.
2872 </para>
2873 <para>
2874 <anchor id="ready_queue_t"/>Of particular note is the fact that <code><phrase
2875 role="identifier">context</phrase></code> contains a hook to participate in
2876 a <ulink url="http://www.boost.org/doc/libs/release/doc/html/intrusive/list.html"><code><phrase
2877 role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">intrusive</phrase><phrase
2878 role="special">::</phrase><phrase role="identifier">list</phrase></code></ulink>
2879 <literal>typedef</literal>&#8217;ed as <code><phrase role="identifier">boost</phrase><phrase
2880 role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase
2881 role="special">::</phrase><phrase role="identifier">scheduler</phrase><phrase
2882 role="special">::</phrase><phrase role="identifier">ready_queue_t</phrase></code>.
2883 This hook is reserved for use by <link linkend="class_algorithm"><code>algorithm</code></link> implementations. (For
2884 instance, <link linkend="class_round_robin"><code>round_robin</code></link> contains a <code><phrase role="identifier">ready_queue_t</phrase></code>
2885 instance to manage its ready fibers.) See <link linkend="context_ready_is_linked"><code>context::ready_is_linked()</code></link>,
2886 <link linkend="context_ready_link"><code>context::ready_link()</code></link>, <link linkend="context_ready_unlink"><code>context::ready_unlink()</code></link>.
2887 </para>
2888 <para>
2889 Your <code><phrase role="identifier">algorithm</phrase></code> implementation
2890 may use any container you desire to manage passed <code><phrase role="identifier">context</phrase></code>
2891 instances. <code><phrase role="identifier">ready_queue_t</phrase></code> avoids
2892 some of the overhead of typical STL containers.
2893 </para>
2894 <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>
2895
2896 <phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase>
2897 <phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase>
2898
2899 <phrase role="keyword">enum</phrase> <phrase role="keyword">class</phrase> <phrase role="identifier">type</phrase> <phrase role="special">{</phrase>
2900 <phrase role="identifier">none</phrase> <phrase role="special">=</phrase> <emphasis>unspecified</emphasis><phrase role="special">,</phrase>
2901 <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>
2902 <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>
2903 <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>
2904 <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>
2905 <phrase role="special">};</phrase>
2906
2907 <phrase role="keyword">class</phrase> <phrase role="identifier">context</phrase> <phrase role="special">{</phrase>
2908 <phrase role="keyword">public</phrase><phrase role="special">:</phrase>
2909 <phrase role="keyword">class</phrase> <phrase role="identifier">id</phrase><phrase role="special">;</phrase>
2910
2911 <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>
2912
2913 <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>
2914 <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>
2915
2916 <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>
2917
2918 <phrase role="keyword">void</phrase> <phrase role="identifier">detach</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
2919 <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>
2920
2921 <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>
2922
2923 <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>
2924
2925 <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>
2926 <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>
2927 <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>
2928
2929 <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>
2930 <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>
2931 <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>
2932 <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>
2933 <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>
2934 <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>
2935
2936 <phrase role="keyword">void</phrase> <phrase role="identifier">ready_unlink</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
2937 <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>
2938 <phrase role="keyword">void</phrase> <phrase role="identifier">wait_unlink</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
2939
2940 <phrase role="keyword">void</phrase> <phrase role="identifier">suspend</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
2941 <phrase role="keyword">void</phrase> <phrase role="identifier">set_ready</phrase><phrase role="special">(</phrase> <phrase role="identifier">context</phrase> <phrase role="special">*)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
2942 <phrase role="special">};</phrase>
2943
2944 <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>
2945
2946 <phrase role="special">}}</phrase>
2947 </programlisting>
2948 <para>
2949 <bridgehead renderas="sect4" id="context_active_bridgehead">
2950 <phrase id="context_active"/>
2951 <link linkend="context_active">Static member function
2952 <code>active</code>()</link>
2953 </bridgehead>
2954 </para>
2955 <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>
2956 </programlisting>
2957 <variablelist>
2958 <title></title>
2959 <varlistentry>
2960 <term>Returns:</term>
2961 <listitem>
2962 <para>
2963 Pointer to instance of current fiber.
2964 </para>
2965 </listitem>
2966 </varlistentry>
2967 <varlistentry>
2968 <term>Throws:</term>
2969 <listitem>
2970 <para>
2971 Nothing
2972 </para>
2973 </listitem>
2974 </varlistentry>
2975 </variablelist>
2976 <para>
2977 <bridgehead renderas="sect4" id="context_get_id_bridgehead">
2978 <phrase id="context_get_id"/>
2979 <link linkend="context_get_id">Member function <code>get_id</code>()</link>
2980 </bridgehead>
2981 </para>
2982 <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>
2983 </programlisting>
2984 <variablelist>
2985 <title></title>
2986 <varlistentry>
2987 <term>Returns:</term>
2988 <listitem>
2989 <para>
2990 If <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>
2991 refers to a fiber of execution, an instance of <link linkend="class_fiber_id"><code><phrase
2992 role="identifier">fiber</phrase><phrase role="special">::</phrase><phrase
2993 role="identifier">id</phrase></code></link> that represents that fiber. Otherwise
2994 returns a default-constructed <link linkend="class_fiber_id"><code><phrase role="identifier">fiber</phrase><phrase
2995 role="special">::</phrase><phrase role="identifier">id</phrase></code></link>.
2996 </para>
2997 </listitem>
2998 </varlistentry>
2999 <varlistentry>
3000 <term>Throws:</term>
3001 <listitem>
3002 <para>
3003 Nothing
3004 </para>
3005 </listitem>
3006 </varlistentry>
3007 <varlistentry>
3008 <term>See also:</term>
3009 <listitem>
3010 <para>
3011 <link linkend="fiber_get_id"><code>fiber::get_id()</code></link>
3012 </para>
3013 </listitem>
3014 </varlistentry>
3015 </variablelist>
3016 <para>
3017 <bridgehead renderas="sect4" id="context_attach_bridgehead">
3018 <phrase id="context_attach"/>
3019 <link linkend="context_attach">Member function <code>attach</code>()</link>
3020 </bridgehead>
3021 </para>
3022 <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>
3023 </programlisting>
3024 <variablelist>
3025 <title></title>
3026 <varlistentry>
3027 <term>Precondition:</term>
3028 <listitem>
3029 <para>
3030 <code><phrase role="keyword">this</phrase><phrase role="special">-&gt;</phrase><phrase
3031 role="identifier">get_scheduler</phrase><phrase role="special">()</phrase>
3032 <phrase role="special">==</phrase> <phrase role="keyword">nullptr</phrase></code>
3033 </para>
3034 </listitem>
3035 </varlistentry>
3036 <varlistentry>
3037 <term>Effects:</term>
3038 <listitem>
3039 <para>
3040 Attach fiber <code><phrase role="identifier">f</phrase></code> to scheduler
3041 running <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>.
3042 </para>
3043 </listitem>
3044 </varlistentry>
3045 <varlistentry>
3046 <term>Postcondition:</term>
3047 <listitem>
3048 <para>
3049 <code><phrase role="keyword">this</phrase><phrase role="special">-&gt;</phrase><phrase
3050 role="identifier">get_scheduler</phrase><phrase role="special">()</phrase>
3051 <phrase role="special">!=</phrase> <phrase role="keyword">nullptr</phrase></code>
3052 </para>
3053 </listitem>
3054 </varlistentry>
3055 <varlistentry>
3056 <term>Throws:</term>
3057 <listitem>
3058 <para>
3059 Nothing
3060 </para>
3061 </listitem>
3062 </varlistentry>
3063 <varlistentry>
3064 <term>Note:</term>
3065 <listitem>
3066 <para>
3067 A typical call: <code><phrase role="identifier">boost</phrase><phrase
3068 role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase
3069 role="special">::</phrase><phrase role="identifier">context</phrase><phrase
3070 role="special">::</phrase><phrase role="identifier">active</phrase><phrase
3071 role="special">()-&gt;</phrase><phrase role="identifier">attach</phrase><phrase
3072 role="special">(</phrase><phrase role="identifier">f</phrase><phrase
3073 role="special">);</phrase></code>
3074 </para>
3075 </listitem>
3076 </varlistentry>
3077 <varlistentry>
3078 <term>Note:</term>
3079 <listitem>
3080 <para>
3081 <code><phrase role="identifier">f</phrase></code> must not be the running
3082 fiber&#8217;s context. It must not be <link linkend="blocking"><emphasis>blocked</emphasis></link>
3083 or terminated. It must not be a <code><phrase role="identifier">pinned_context</phrase></code>.
3084 It must be currently detached. It must not currently be linked into an
3085 <link linkend="class_algorithm"><code>algorithm</code></link> implementation&#8217;s ready queue. Most of these conditions
3086 are implied by <code><phrase role="identifier">f</phrase></code> being
3087 owned by an <code><phrase role="identifier">algorithm</phrase></code>
3088 implementation: that is, it has been passed to <link linkend="algorithm_awakened"><code>algorithm::awakened()</code></link> but
3089 has not yet been returned by <link linkend="algorithm_pick_next"><code>algorithm::pick_next()</code></link>.
3090 Typically a <code><phrase role="identifier">pick_next</phrase><phrase
3091 role="special">()</phrase></code> implementation would call <code><phrase
3092 role="identifier">attach</phrase><phrase role="special">()</phrase></code>
3093 with the <code><phrase role="identifier">context</phrase><phrase role="special">*</phrase></code>
3094 it is about to return. It must first remove <code><phrase role="identifier">f</phrase></code>
3095 from its ready queue. You should never pass a <code><phrase role="identifier">pinned_context</phrase></code>
3096 to <code><phrase role="identifier">attach</phrase><phrase role="special">()</phrase></code>
3097 because you should never have called its <code><phrase role="identifier">detach</phrase><phrase
3098 role="special">()</phrase></code> method in the first place.
3099 </para>
3100 </listitem>
3101 </varlistentry>
3102 </variablelist>
3103 <para>
3104 <bridgehead renderas="sect4" id="context_detach_bridgehead">
3105 <phrase id="context_detach"/>
3106 <link linkend="context_detach">Member function <code>detach</code>()</link>
3107 </bridgehead>
3108 </para>
3109 <programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">detach</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
3110 </programlisting>
3111 <variablelist>
3112 <title></title>
3113 <varlistentry>
3114 <term>Precondition:</term>
3115 <listitem>
3116 <para>
3117 <code><phrase role="special">(</phrase><phrase role="keyword">this</phrase><phrase
3118 role="special">-&gt;</phrase><phrase role="identifier">get_scheduler</phrase><phrase
3119 role="special">()</phrase> <phrase role="special">!=</phrase> <phrase
3120 role="keyword">nullptr</phrase><phrase role="special">)</phrase> <phrase
3121 role="special">&amp;&amp;</phrase> <phrase role="special">!</phrase>
3122 <phrase role="keyword">this</phrase><phrase role="special">-&gt;</phrase><phrase
3123 role="identifier">is_context</phrase><phrase role="special">(</phrase><phrase
3124 role="identifier">pinned_context</phrase><phrase role="special">)</phrase></code>
3125 </para>
3126 </listitem>
3127 </varlistentry>
3128 <varlistentry>
3129 <term>Effects:</term>
3130 <listitem>
3131 <para>
3132 Detach fiber <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>
3133 from its scheduler running <code><phrase role="special">*</phrase><phrase
3134 role="keyword">this</phrase></code>.
3135 </para>
3136 </listitem>
3137 </varlistentry>
3138 <varlistentry>
3139 <term>Throws:</term>
3140 <listitem>
3141 <para>
3142 Nothing
3143 </para>
3144 </listitem>
3145 </varlistentry>
3146 <varlistentry>
3147 <term>Postcondition:</term>
3148 <listitem>
3149 <para>
3150 <code><phrase role="keyword">this</phrase><phrase role="special">-&gt;</phrase><phrase
3151 role="identifier">get_scheduler</phrase><phrase role="special">()</phrase>
3152 <phrase role="special">==</phrase> <phrase role="keyword">nullptr</phrase></code>
3153 </para>
3154 </listitem>
3155 </varlistentry>
3156 <varlistentry>
3157 <term>Note:</term>
3158 <listitem>
3159 <para>
3160 This method must be called on the thread with which the fiber is currently
3161 associated. <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>
3162 must not be the running fiber&#8217;s context. It must not be <link linkend="blocking"><emphasis>blocked</emphasis></link>
3163 or terminated. It must not be a <code><phrase role="identifier">pinned_context</phrase></code>.
3164 It must not be detached already. It must not already be linked into an
3165 <link linkend="class_algorithm"><code>algorithm</code></link> implementation&#8217;s ready queue. Most of these conditions
3166 are implied by <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>
3167 being passed to <link linkend="algorithm_awakened"><code>algorithm::awakened()</code></link>; an <code><phrase
3168 role="identifier">awakened</phrase><phrase role="special">()</phrase></code>
3169 implementation must, however, test for <code><phrase role="identifier">pinned_context</phrase></code>.
3170 It must call <code><phrase role="identifier">detach</phrase><phrase role="special">()</phrase></code>
3171 <emphasis>before</emphasis> linking <code><phrase role="special">*</phrase><phrase
3172 role="keyword">this</phrase></code> into its ready queue.
3173 </para>
3174 </listitem>
3175 </varlistentry>
3176 <varlistentry>
3177 <term>Note:</term>
3178 <listitem>
3179 <para>
3180 In particular, it is erroneous to attempt to migrate a fiber from one
3181 thread to another by calling both <code><phrase role="identifier">detach</phrase><phrase
3182 role="special">()</phrase></code> and <code><phrase role="identifier">attach</phrase><phrase
3183 role="special">()</phrase></code> in the <link linkend="algorithm_pick_next"><code>algorithm::pick_next()</code></link> method.
3184 <code><phrase role="identifier">pick_next</phrase><phrase role="special">()</phrase></code>
3185 is called on the intended destination thread. <code><phrase role="identifier">detach</phrase><phrase
3186 role="special">()</phrase></code> must be called on the fiber&#8217;s original
3187 thread. You must call <code><phrase role="identifier">detach</phrase><phrase
3188 role="special">()</phrase></code> in the corresponding <code><phrase
3189 role="identifier">awakened</phrase><phrase role="special">()</phrase></code>
3190 method.
3191 </para>
3192 </listitem>
3193 </varlistentry>
3194 <varlistentry>
3195 <term>Note:</term>
3196 <listitem>
3197 <para>
3198 Unless you intend make a fiber available for potential migration to a
3199 different thread, you should call neither <code><phrase role="identifier">detach</phrase><phrase
3200 role="special">()</phrase></code> nor <code><phrase role="identifier">attach</phrase><phrase
3201 role="special">()</phrase></code> with its <code><phrase role="identifier">context</phrase></code>.
3202 </para>
3203 </listitem>
3204 </varlistentry>
3205 </variablelist>
3206 <para>
3207 <bridgehead renderas="sect4" id="context_is_context_bridgehead">
3208 <phrase id="context_is_context"/>
3209 <link linkend="context_is_context">Member function
3210 <code>is_context</code>()</link>
3211 </bridgehead>
3212 </para>
3213 <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>
3214 </programlisting>
3215 <variablelist>
3216 <title></title>
3217 <varlistentry>
3218 <term>Returns:</term>
3219 <listitem>
3220 <para>
3221 <code><phrase role="keyword">true</phrase></code> if <code><phrase role="special">*</phrase><phrase
3222 role="keyword">this</phrase></code> is of the specified type.
3223 </para>
3224 </listitem>
3225 </varlistentry>
3226 <varlistentry>
3227 <term>Throws:</term>
3228 <listitem>
3229 <para>
3230 Nothing
3231 </para>
3232 </listitem>
3233 </varlistentry>
3234 <varlistentry>
3235 <term>Note:</term>
3236 <listitem>
3237 <para>
3238 <code><phrase role="identifier">type</phrase><phrase role="special">::</phrase><phrase
3239 role="identifier">worker_context</phrase></code> here means any fiber
3240 not special to the library. For <code><phrase role="identifier">type</phrase><phrase
3241 role="special">::</phrase><phrase role="identifier">main_context</phrase></code>
3242 the <code><phrase role="identifier">context</phrase></code> is associated
3243 with the <quote>main</quote> fiber of the thread: the one implicitly
3244 created by the thread itself, rather than one explicitly created by
3245 <emphasis role="bold">Boost.Fiber</emphasis>. For <code><phrase role="identifier">type</phrase><phrase
3246 role="special">::</phrase><phrase role="identifier">dispatcher_context</phrase></code>
3247 the <code><phrase role="identifier">context</phrase></code> is associated
3248 with a <quote>dispatching</quote> fiber, responsible for dispatching
3249 awakened fibers to a scheduler&#8217;s ready-queue. The <quote>dispatching</quote>
3250 fiber is an implementation detail of the fiber manager. The context of
3251 the <quote>main</quote> or <quote>dispatching</quote> fiber &mdash; any fiber
3252 for which <code><phrase role="identifier">is_context</phrase><phrase
3253 role="special">(</phrase><phrase role="identifier">pinned_context</phrase><phrase
3254 role="special">)</phrase></code> is <code><phrase role="keyword">true</phrase></code>
3255 &mdash; must never be passed to <link linkend="context_detach"><code>context::detach()</code></link>.
3256 </para>
3257 </listitem>
3258 </varlistentry>
3259 </variablelist>
3260 <para>
3261 <bridgehead renderas="sect4" id="context_is_terminated_bridgehead">
3262 <phrase id="context_is_terminated"/>
3263 <link linkend="context_is_terminated">Member
3264 function <code>is_terminated</code>()</link>
3265 </bridgehead>
3266 </para>
3267 <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>
3268 </programlisting>
3269 <variablelist>
3270 <title></title>
3271 <varlistentry>
3272 <term>Returns:</term>
3273 <listitem>
3274 <para>
3275 <code><phrase role="keyword">true</phrase></code> if <code><phrase role="special">*</phrase><phrase
3276 role="keyword">this</phrase></code> is no longer a valid context.
3277 </para>
3278 </listitem>
3279 </varlistentry>
3280 <varlistentry>
3281 <term>Throws:</term>
3282 <listitem>
3283 <para>
3284 Nothing
3285 </para>
3286 </listitem>
3287 </varlistentry>
3288 <varlistentry>
3289 <term>Note:</term>
3290 <listitem>
3291 <para>
3292 The <code><phrase role="identifier">context</phrase></code> has returned
3293 from its fiber-function and is no longer considered a valid context.
3294 </para>
3295 </listitem>
3296 </varlistentry>
3297 </variablelist>
3298 <para>
3299 <bridgehead renderas="sect4" id="context_ready_is_linked_bridgehead">
3300 <phrase id="context_ready_is_linked"/>
3301 <link linkend="context_ready_is_linked">Member
3302 function <code>ready_is_linked</code>()</link>
3303 </bridgehead>
3304 </para>
3305 <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>
3306 </programlisting>
3307 <variablelist>
3308 <title></title>
3309 <varlistentry>
3310 <term>Returns:</term>
3311 <listitem>
3312 <para>
3313 <code><phrase role="keyword">true</phrase></code> if <code><phrase role="special">*</phrase><phrase
3314 role="keyword">this</phrase></code> is stored in an <link linkend="class_algorithm"><code>algorithm</code></link>
3315 implementation&#8217;s
3316 ready-queue.
3317 </para>
3318 </listitem>
3319 </varlistentry>
3320 <varlistentry>
3321 <term>Throws:</term>
3322 <listitem>
3323 <para>
3324 Nothing
3325 </para>
3326 </listitem>
3327 </varlistentry>
3328 <varlistentry>
3329 <term>Note:</term>
3330 <listitem>
3331 <para>
3332 Specifically, this method indicates whether <link linkend="context_ready_link"><code>context::ready_link()</code></link> has
3333 been called on <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>.
3334 <code><phrase role="identifier">ready_is_linked</phrase><phrase role="special">()</phrase></code>
3335 has no information about participation in any other containers.
3336 </para>
3337 </listitem>
3338 </varlistentry>
3339 </variablelist>
3340 <para>
3341 <bridgehead renderas="sect4" id="context_remote_ready_is_linked_bridgehead">
3342 <phrase id="context_remote_ready_is_linked"/>
3343 <link linkend="context_remote_ready_is_linked">Member
3344 function <code>remote_ready_is_linked</code>()</link>
3345 </bridgehead>
3346 </para>
3347 <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>
3348 </programlisting>
3349 <variablelist>
3350 <title></title>
3351 <varlistentry>
3352 <term>Returns:</term>
3353 <listitem>
3354 <para>
3355 <code><phrase role="keyword">true</phrase></code> if <code><phrase role="special">*</phrase><phrase
3356 role="keyword">this</phrase></code> is stored in the fiber manager&#8217;s remote-ready-queue.
3357 </para>
3358 </listitem>
3359 </varlistentry>
3360 <varlistentry>
3361 <term>Throws:</term>
3362 <listitem>
3363 <para>
3364 Nothing
3365 </para>
3366 </listitem>
3367 </varlistentry>
3368 <varlistentry>
3369 <term>Note:</term>
3370 <listitem>
3371 <para>
3372 A <code><phrase role="identifier">context</phrase></code> signaled as
3373 ready by another thread is first stored in the fiber manager&#8217;s remote-ready-queue.
3374 This is the mechanism by which the fiber manager protects an <link linkend="class_algorithm"><code>algorithm</code></link> implementation
3375 from cross-thread <link linkend="algorithm_awakened"><code>algorithm::awakened()</code></link> calls.
3376 </para>
3377 </listitem>
3378 </varlistentry>
3379 </variablelist>
3380 <para>
3381 <bridgehead renderas="sect4" id="context_wait_is_linked_bridgehead">
3382 <phrase id="context_wait_is_linked"/>
3383 <link linkend="context_wait_is_linked">Member
3384 function <code>wait_is_linked</code>()</link>
3385 </bridgehead>
3386 </para>
3387 <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>
3388 </programlisting>
3389 <variablelist>
3390 <title></title>
3391 <varlistentry>
3392 <term>Returns:</term>
3393 <listitem>
3394 <para>
3395 <code><phrase role="keyword">true</phrase></code> if <code><phrase role="special">*</phrase><phrase
3396 role="keyword">this</phrase></code> is stored in the wait-queue of some
3397 synchronization object.
3398 </para>
3399 </listitem>
3400 </varlistentry>
3401 <varlistentry>
3402 <term>Throws:</term>
3403 <listitem>
3404 <para>
3405 Nothing
3406 </para>
3407 </listitem>
3408 </varlistentry>
3409 <varlistentry>
3410 <term>Note:</term>
3411 <listitem>
3412 <para>
3413 The <code><phrase role="identifier">context</phrase></code> of a fiber
3414 waiting on a synchronization object (e.g. <code><phrase role="identifier">mutex</phrase></code>,
3415 <code><phrase role="identifier">condition_variable</phrase></code> etc.)
3416 is stored in the wait-queue of that synchronization object.
3417 </para>
3418 </listitem>
3419 </varlistentry>
3420 </variablelist>
3421 <para>
3422 <bridgehead renderas="sect4" id="context_ready_link_bridgehead">
3423 <phrase id="context_ready_link"/>
3424 <link linkend="context_ready_link">Member function
3425 <code>ready_link</code>()</link>
3426 </bridgehead>
3427 </para>
3428 <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>
3429 <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>
3430 </programlisting>
3431 <variablelist>
3432 <title></title>
3433 <varlistentry>
3434 <term>Effects:</term>
3435 <listitem>
3436 <para>
3437 Stores <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>
3438 in ready-queue <code><phrase role="identifier">lst</phrase></code>.
3439 </para>
3440 </listitem>
3441 </varlistentry>
3442 <varlistentry>
3443 <term>Throws:</term>
3444 <listitem>
3445 <para>
3446 Nothing
3447 </para>
3448 </listitem>
3449 </varlistentry>
3450 <varlistentry>
3451 <term>Note:</term>
3452 <listitem>
3453 <para>
3454 Argument <code><phrase role="identifier">lst</phrase></code> must be
3455 a doubly-linked list from <ulink url="http://www.boost.org/doc/libs/release/libs/intrusive/index.html">Boost.Intrusive</ulink>,
3456 e.g. an instance of <code><phrase role="identifier">boost</phrase><phrase
3457 role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase
3458 role="special">::</phrase><phrase role="identifier">scheduler</phrase><phrase
3459 role="special">::</phrase><phrase role="identifier">ready_queue_t</phrase></code>.
3460 Specifically, it must be a <ulink url="http://www.boost.org/doc/libs/release/doc/html/intrusive/list.html"><code><phrase
3461 role="identifier">boost</phrase><phrase role="special">::</phrase><phrase
3462 role="identifier">intrusive</phrase><phrase role="special">::</phrase><phrase
3463 role="identifier">list</phrase></code></ulink> compatible with the <code><phrase
3464 role="identifier">list_member_hook</phrase></code> stored in the <code><phrase
3465 role="identifier">context</phrase></code> object.
3466 </para>
3467 </listitem>
3468 </varlistentry>
3469 </variablelist>
3470 <para>
3471 <bridgehead renderas="sect4" id="context_remote_ready_link_bridgehead">
3472 <phrase id="context_remote_ready_link"/>
3473 <link linkend="context_remote_ready_link">Member
3474 function <code>remote_ready_link</code>()</link>
3475 </bridgehead>
3476 </para>
3477 <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>
3478 <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>
3479 </programlisting>
3480 <variablelist>
3481 <title></title>
3482 <varlistentry>
3483 <term>Effects:</term>
3484 <listitem>
3485 <para>
3486 Stores <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>
3487 in remote-ready-queue <code><phrase role="identifier">lst</phrase></code>.
3488 </para>
3489 </listitem>
3490 </varlistentry>
3491 <varlistentry>
3492 <term>Throws:</term>
3493 <listitem>
3494 <para>
3495 Nothing
3496 </para>
3497 </listitem>
3498 </varlistentry>
3499 <varlistentry>
3500 <term>Note:</term>
3501 <listitem>
3502 <para>
3503 Argument <code><phrase role="identifier">lst</phrase></code> must be
3504 a doubly-linked list from <ulink url="http://www.boost.org/doc/libs/release/libs/intrusive/index.html">Boost.Intrusive</ulink>.
3505 </para>
3506 </listitem>
3507 </varlistentry>
3508 </variablelist>
3509 <para>
3510 <bridgehead renderas="sect4" id="context_wait_link_bridgehead">
3511 <phrase id="context_wait_link"/>
3512 <link linkend="context_wait_link">Member function
3513 <code>wait_link</code>()</link>
3514 </bridgehead>
3515 </para>
3516 <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>
3517 <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>
3518 </programlisting>
3519 <variablelist>
3520 <title></title>
3521 <varlistentry>
3522 <term>Effects:</term>
3523 <listitem>
3524 <para>
3525 Stores <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>
3526 in wait-queue <code><phrase role="identifier">lst</phrase></code>.
3527 </para>
3528 </listitem>
3529 </varlistentry>
3530 <varlistentry>
3531 <term>Throws:</term>
3532 <listitem>
3533 <para>
3534 Nothing
3535 </para>
3536 </listitem>
3537 </varlistentry>
3538 <varlistentry>
3539 <term>Note:</term>
3540 <listitem>
3541 <para>
3542 Argument <code><phrase role="identifier">lst</phrase></code> must be
3543 a doubly-linked list from <ulink url="http://www.boost.org/doc/libs/release/libs/intrusive/index.html">Boost.Intrusive</ulink>.
3544 </para>
3545 </listitem>
3546 </varlistentry>
3547 </variablelist>
3548 <para>
3549 <bridgehead renderas="sect4" id="context_ready_unlink_bridgehead">
3550 <phrase id="context_ready_unlink"/>
3551 <link linkend="context_ready_unlink">Member
3552 function <code>ready_unlink</code>()</link>
3553 </bridgehead>
3554 </para>
3555 <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>
3556 </programlisting>
3557 <variablelist>
3558 <title></title>
3559 <varlistentry>
3560 <term>Effects:</term>
3561 <listitem>
3562 <para>
3563 Removes <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>
3564 from ready-queue: undoes the effect of <link linkend="context_ready_link"><code>context::ready_link()</code></link>.
3565 </para>
3566 </listitem>
3567 </varlistentry>
3568 <varlistentry>
3569 <term>Throws:</term>
3570 <listitem>
3571 <para>
3572 Nothing
3573 </para>
3574 </listitem>
3575 </varlistentry>
3576 </variablelist>
3577 <para>
3578 <bridgehead renderas="sect4" id="context_remote_ready_unlink_bridgehead">
3579 <phrase id="context_remote_ready_unlink"/>
3580 <link linkend="context_remote_ready_unlink">Member
3581 function <code>remote_ready_unlink</code>()</link>
3582 </bridgehead>
3583 </para>
3584 <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>
3585 </programlisting>
3586 <variablelist>
3587 <title></title>
3588 <varlistentry>
3589 <term>Effects:</term>
3590 <listitem>
3591 <para>
3592 Removes <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>
3593 from remote-ready-queue.
3594 </para>
3595 </listitem>
3596 </varlistentry>
3597 <varlistentry>
3598 <term>Throws:</term>
3599 <listitem>
3600 <para>
3601 Nothing
3602 </para>
3603 </listitem>
3604 </varlistentry>
3605 </variablelist>
3606 <para>
3607 <bridgehead renderas="sect4" id="context_wait_unlink_bridgehead">
3608 <phrase id="context_wait_unlink"/>
3609 <link linkend="context_wait_unlink">Member
3610 function <code>wait_unlink</code>()</link>
3611 </bridgehead>
3612 </para>
3613 <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>
3614 </programlisting>
3615 <variablelist>
3616 <title></title>
3617 <varlistentry>
3618 <term>Effects:</term>
3619 <listitem>
3620 <para>
3621 Removes <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>
3622 from wait-queue.
3623 </para>
3624 </listitem>
3625 </varlistentry>
3626 <varlistentry>
3627 <term>Throws:</term>
3628 <listitem>
3629 <para>
3630 Nothing
3631 </para>
3632 </listitem>
3633 </varlistentry>
3634 </variablelist>
3635 <para>
3636 <bridgehead renderas="sect4" id="context_suspend_bridgehead">
3637 <phrase id="context_suspend"/>
3638 <link linkend="context_suspend">Member function <code>suspend</code>()</link>
3639 </bridgehead>
3640 </para>
3641 <programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">suspend</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
3642 </programlisting>
3643 <variablelist>
3644 <title></title>
3645 <varlistentry>
3646 <term>Effects:</term>
3647 <listitem>
3648 <para>
3649 Suspends the running fiber (the fiber associated with <code><phrase role="special">*</phrase><phrase
3650 role="keyword">this</phrase></code>) until some other fiber passes <code><phrase
3651 role="keyword">this</phrase></code> to <link linkend="context_set_ready"><code>context::set_ready()</code></link>.
3652 <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>
3653 is marked as not-ready, and control passes to the scheduler to select
3654 another fiber to run.
3655 </para>
3656 </listitem>
3657 </varlistentry>
3658 <varlistentry>
3659 <term>Throws:</term>
3660 <listitem>
3661 <para>
3662 Nothing
3663 </para>
3664 </listitem>
3665 </varlistentry>
3666 <varlistentry>
3667 <term>Note:</term>
3668 <listitem>
3669 <para>
3670 This is a low-level API potentially useful for integration with other
3671 frameworks. It is not intended to be directly invoked by a typical application
3672 program.
3673 </para>
3674 </listitem>
3675 </varlistentry>
3676 <varlistentry>
3677 <term>Note:</term>
3678 <listitem>
3679 <para>
3680 The burden is on the caller to arrange for a call to <code><phrase role="identifier">set_ready</phrase><phrase
3681 role="special">()</phrase></code> with a pointer to <code><phrase role="keyword">this</phrase></code>
3682 at some future time.
3683 </para>
3684 </listitem>
3685 </varlistentry>
3686 </variablelist>
3687 <para>
3688 <bridgehead renderas="sect4" id="context_set_ready_bridgehead">
3689 <phrase id="context_set_ready"/>
3690 <link linkend="context_set_ready">Member function
3691 <code>set_ready</code>()</link>
3692 </bridgehead>
3693 </para>
3694 <programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">set_ready</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>
3695 </programlisting>
3696 <variablelist>
3697 <title></title>
3698 <varlistentry>
3699 <term>Effects:</term>
3700 <listitem>
3701 <para>
3702 Mark the fiber associated with context <code><phrase role="special">*</phrase><phrase
3703 role="identifier">ctx</phrase></code> as being ready to run. This does
3704 not immediately resume that fiber; rather it passes the fiber to the
3705 scheduler for subsequent resumption. If the scheduler is idle (has not
3706 returned from a call to <link linkend="algorithm_suspend_until"><code>algorithm::suspend_until()</code></link>),
3707 <link linkend="algorithm_notify"><code>algorithm::notify()</code></link> is called to wake it up.
3708 </para>
3709 </listitem>
3710 </varlistentry>
3711 <varlistentry>
3712 <term>Throws:</term>
3713 <listitem>
3714 <para>
3715 Nothing
3716 </para>
3717 </listitem>
3718 </varlistentry>
3719 <varlistentry>
3720 <term>Note:</term>
3721 <listitem>
3722 <para>
3723 This is a low-level API potentially useful for integration with other
3724 frameworks. It is not intended to be directly invoked by a typical application
3725 program.
3726 </para>
3727 </listitem>
3728 </varlistentry>
3729 <varlistentry>
3730 <term>Note:</term>
3731 <listitem>
3732 <para>
3733 It is explicitly supported to call <code><phrase role="identifier">set_ready</phrase><phrase
3734 role="special">(</phrase><phrase role="identifier">ctx</phrase><phrase
3735 role="special">)</phrase></code> from a thread other than the one on
3736 which <code><phrase role="special">*</phrase><phrase role="identifier">ctx</phrase></code>
3737 is currently suspended. The corresponding fiber will be resumed on its
3738 original thread in due course.
3739 </para>
3740 </listitem>
3741 </varlistentry>
3742 </variablelist>
3743 <para>
3744 <bridgehead renderas="sect4" id="context_less_bridgehead">
3745 <phrase id="context_less"/>
3746 <link linkend="context_less">Non-member function <code>operator&lt;()</code></link>
3747 </bridgehead>
3748 </para>
3749 <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>
3750 </programlisting>
3751 <variablelist>
3752 <title></title>
3753 <varlistentry>
3754 <term>Returns:</term>
3755 <listitem>
3756 <para>
3757 <code><phrase role="keyword">true</phrase></code> if <code><phrase role="identifier">l</phrase><phrase
3758 role="special">.</phrase><phrase role="identifier">get_id</phrase><phrase
3759 role="special">()</phrase> <phrase role="special">&lt;</phrase> <phrase
3760 role="identifier">r</phrase><phrase role="special">.</phrase><phrase
3761 role="identifier">get_id</phrase><phrase role="special">()</phrase></code>
3762 is <code><phrase role="keyword">true</phrase></code>, <code><phrase role="keyword">false</phrase></code>
3763 otherwise.
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 </variablelist>
3776 </section>
3777 <section id="fiber.stack">
3778 <title><anchor id="stack"/><link linkend="fiber.stack">Stack allocation</link></title>
3779 <para>
3780 A <link linkend="class_fiber"><code>fiber</code></link> uses internally an <ulink url="http://www.boost.org/doc/libs/release/libs/context/doc/html/context/econtext.html"><emphasis>execution_context</emphasis></ulink>
3781 which manages a set of registers and a stack. The memory used by the stack
3782 is allocated/deallocated via a <emphasis>stack_allocator</emphasis> which is
3783 required to model a <link linkend="stack_allocator_concept"><emphasis>stack-allocator
3784 concept</emphasis></link>.
3785 </para>
3786 <para>
3787 A <emphasis>stack_allocator</emphasis> can be passed to <link linkend="fiber_fiber"><code><phrase
3788 role="identifier">fiber</phrase><phrase role="special">::</phrase><phrase role="identifier">fiber</phrase><phrase
3789 role="special">()</phrase></code></link> or to <link linkend="fibers_async"><code>fibers::async()</code></link>.
3790 </para>
3791 <anchor id="stack_allocator_concept"/>
3792 <bridgehead renderas="sect3" id="fiber.stack.h0">
3793 <phrase id="fiber.stack.stack_allocator_concept"/><link linkend="fiber.stack.stack_allocator_concept">stack-allocator
3794 concept</link>
3795 </bridgehead>
3796 <para>
3797 A <emphasis>stack_allocator</emphasis> must satisfy the <emphasis>stack-allocator
3798 concept</emphasis> requirements shown in the following table, in which <code><phrase
3799 role="identifier">a</phrase></code> is an object of a <emphasis>stack_allocator</emphasis>
3800 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
3801 role="identifier">stack_context</phrase></code></ulink>, and <code><phrase
3802 role="identifier">size</phrase></code> is a <code><phrase role="identifier">std</phrase><phrase
3803 role="special">::</phrase><phrase role="identifier">size_t</phrase></code>:
3804 </para>
3805 <informaltable frame="all">
3806 <tgroup cols="3">
3807 <thead>
3808 <row>
3809 <entry>
3810 <para>
3811 expression
3812 </para>
3813 </entry>
3814 <entry>
3815 <para>
3816 return type
3817 </para>
3818 </entry>
3819 <entry>
3820 <para>
3821 notes
3822 </para>
3823 </entry>
3824 </row>
3825 </thead>
3826 <tbody>
3827 <row>
3828 <entry>
3829 <para>
3830 <code><phrase role="identifier">a</phrase><phrase role="special">(</phrase><phrase
3831 role="identifier">size</phrase><phrase role="special">)</phrase></code>
3832 </para>
3833 </entry>
3834 <entry>
3835 </entry>
3836 <entry>
3837 <para>
3838 creates a stack allocator
3839 </para>
3840 </entry>
3841 </row>
3842 <row>
3843 <entry>
3844 <para>
3845 <code><phrase role="identifier">a</phrase><phrase role="special">.</phrase><phrase
3846 role="identifier">allocate</phrase><phrase role="special">()</phrase></code>
3847 </para>
3848 </entry>
3849 <entry>
3850 <para>
3851 <ulink url="http://www.boost.org/doc/libs/release/libs/context/doc/html/context/stack/stack_context.html"><code><phrase
3852 role="identifier">stack_context</phrase></code></ulink>
3853 </para>
3854 </entry>
3855 <entry>
3856 <para>
3857 creates a stack
3858 </para>
3859 </entry>
3860 </row>
3861 <row>
3862 <entry>
3863 <para>
3864 <code><phrase role="identifier">a</phrase><phrase role="special">.</phrase><phrase
3865 role="identifier">deallocate</phrase><phrase role="special">(</phrase>
3866 <phrase role="identifier">sctx</phrase><phrase role="special">)</phrase></code>
3867 </para>
3868 </entry>
3869 <entry>
3870 <para>
3871 <code><phrase role="keyword">void</phrase></code>
3872 </para>
3873 </entry>
3874 <entry>
3875 <para>
3876 deallocates the stack created by <code><phrase role="identifier">a</phrase><phrase
3877 role="special">.</phrase><phrase role="identifier">allocate</phrase><phrase
3878 role="special">()</phrase></code>
3879 </para>
3880 </entry>
3881 </row>
3882 </tbody>
3883 </tgroup>
3884 </informaltable>
3885 <important>
3886 <para>
3887 The implementation of <code><phrase role="identifier">allocate</phrase><phrase
3888 role="special">()</phrase></code> might include logic to protect against
3889 exceeding the context's available stack size rather than leaving it as undefined
3890 behaviour.
3891 </para>
3892 </important>
3893 <important>
3894 <para>
3895 Calling <code><phrase role="identifier">deallocate</phrase><phrase role="special">()</phrase></code>
3896 with a <ulink url="http://www.boost.org/doc/libs/release/libs/context/doc/html/context/stack/stack_context.html"><code><phrase
3897 role="identifier">stack_context</phrase></code></ulink> not obtained from
3898 <code><phrase role="identifier">allocate</phrase><phrase role="special">()</phrase></code>
3899 results in undefined behaviour.
3900 </para>
3901 </important>
3902 <note>
3903 <para>
3904 The memory for the stack is not required to be aligned; alignment takes place
3905 inside <ulink url="http://www.boost.org/doc/libs/release/libs/context/doc/html/context/econtext.html"><emphasis>execution_context</emphasis></ulink>.
3906 </para>
3907 </note>
3908 <para>
3909 See also <ulink url="http://www.boost.org/doc/libs/release/libs/context/doc/html/context/stack.html">Boost.Context
3910 stack allocation</ulink>. In particular, <code><phrase role="identifier">traits_type</phrase></code>
3911 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
3912 role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">context</phrase><phrase
3913 role="special">::</phrase><phrase role="identifier">stack_traits</phrase></code></ulink>.
3914 </para>
3915 <para>
3916 <bridgehead renderas="sect4" id="class_protected_fixedsize_stack_bridgehead">
3917 <phrase id="class_protected_fixedsize_stack"/>
3918 <link linkend="class_protected_fixedsize_stack">Class
3919 <code>protected_fixedsize_stack</code></link>
3920 </bridgehead>
3921 </para>
3922 <para>
3923 <emphasis role="bold">Boost.Fiber</emphasis> provides the class <link linkend="class_protected_fixedsize_stack"><code>protected_fixedsize_stack</code></link> which
3924 models the <link linkend="stack_allocator_concept"><emphasis>stack-allocator
3925 concept</emphasis></link>. It appends a guard page at the end of each stack
3926 to protect against exceeding the stack. If the guard page is accessed (read
3927 or write operation) a segmentation fault/access violation is generated by the
3928 operating system.
3929 </para>
3930 <important>
3931 <para>
3932 Using <link linkend="class_protected_fixedsize_stack"><code>protected_fixedsize_stack</code></link> is expensive.
3933 Launching a new fiber with a stack of this type incurs the overhead of setting
3934 the memory protection; once allocated, this stack is just as efficient to
3935 use as <link linkend="class_fixedsize_stack"><code>fixedsize_stack</code></link>.
3936 </para>
3937 </important>
3938 <note>
3939 <para>
3940 The appended <code><phrase role="identifier">guard</phrase> <phrase role="identifier">page</phrase></code>
3941 is <emphasis role="bold">not</emphasis> mapped to physical memory, only virtual
3942 addresses are used.
3943 </para>
3944 </note>
3945 <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>
3946
3947 <phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase>
3948 <phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase>
3949
3950 <phrase role="keyword">struct</phrase> <phrase role="identifier">protected_fixedsize</phrase> <phrase role="special">{</phrase>
3951 <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>
3952
3953 <phrase role="identifier">stack_context</phrase> <phrase role="identifier">allocate</phrase><phrase role="special">();</phrase>
3954
3955 <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>
3956 <phrase role="special">}</phrase>
3957
3958 <phrase role="special">}}</phrase>
3959 </programlisting>
3960 <para>
3961 <bridgehead renderas="sect4" id="protected_fixedsize_allocate_bridgehead">
3962 <phrase id="protected_fixedsize_allocate"/>
3963 <link linkend="protected_fixedsize_allocate">Member
3964 function <code>allocate</code>()</link>
3965 </bridgehead>
3966 </para>
3967 <programlisting><phrase role="identifier">stack_context</phrase> <phrase role="identifier">allocate</phrase><phrase role="special">();</phrase>
3968 </programlisting>
3969 <variablelist>
3970 <title></title>
3971 <varlistentry>
3972 <term>Preconditions:</term>
3973 <listitem>
3974 <para>
3975 <code><phrase role="identifier">traits_type</phrase><phrase role="special">::</phrase><phrase
3976 role="identifier">minimum_size</phrase><phrase role="special">()</phrase>
3977 <phrase role="special">&lt;=</phrase> <phrase role="identifier">size</phrase></code>
3978 and <code><phrase role="identifier">traits_type</phrase><phrase role="special">::</phrase><phrase
3979 role="identifier">is_unbounded</phrase><phrase role="special">()</phrase>
3980 <phrase role="special">||</phrase> <phrase role="special">(</phrase>
3981 <phrase role="identifier">size</phrase> <phrase role="special">&lt;=</phrase>
3982 <phrase role="identifier">traits_type</phrase><phrase role="special">::</phrase><phrase
3983 role="identifier">maximum_size</phrase><phrase role="special">()</phrase>
3984 <phrase role="special">)</phrase></code>.
3985 </para>
3986 </listitem>
3987 </varlistentry>
3988 <varlistentry>
3989 <term>Effects:</term>
3990 <listitem>
3991 <para>
3992 Allocates memory of at least <code><phrase role="identifier">size</phrase></code>
3993 bytes and stores a pointer to the stack and its actual size in <code><phrase
3994 role="identifier">sctx</phrase></code>. Depending on the architecture
3995 (the stack grows downwards/upwards) the stored address is the highest/lowest
3996 address of the stack.
3997 </para>
3998 </listitem>
3999 </varlistentry>
4000 </variablelist>
4001 <para>
4002 <bridgehead renderas="sect4" id="protected_fixesize_deallocate_bridgehead">
4003 <phrase id="protected_fixesize_deallocate"/>
4004 <link linkend="protected_fixesize_deallocate">Member
4005 function <code>deallocate</code>()</link>
4006 </bridgehead>
4007 </para>
4008 <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>
4009 </programlisting>
4010 <variablelist>
4011 <title></title>
4012 <varlistentry>
4013 <term>Preconditions:</term>
4014 <listitem>
4015 <para>
4016 <code><phrase role="identifier">sctx</phrase><phrase role="special">.</phrase><phrase
4017 role="identifier">sp</phrase></code> is valid, <code><phrase role="identifier">traits_type</phrase><phrase
4018 role="special">::</phrase><phrase role="identifier">minimum_size</phrase><phrase
4019 role="special">()</phrase> <phrase role="special">&lt;=</phrase> <phrase
4020 role="identifier">sctx</phrase><phrase role="special">.</phrase><phrase
4021 role="identifier">size</phrase></code> and <code><phrase role="identifier">traits_type</phrase><phrase
4022 role="special">::</phrase><phrase role="identifier">is_unbounded</phrase><phrase
4023 role="special">()</phrase> <phrase role="special">||</phrase> <phrase
4024 role="special">(</phrase> <phrase role="identifier">sctx</phrase><phrase
4025 role="special">.</phrase><phrase role="identifier">size</phrase> <phrase
4026 role="special">&lt;=</phrase> <phrase role="identifier">traits_type</phrase><phrase
4027 role="special">::</phrase><phrase role="identifier">maximum_size</phrase><phrase
4028 role="special">()</phrase> <phrase role="special">)</phrase></code>.
4029 </para>
4030 </listitem>
4031 </varlistentry>
4032 <varlistentry>
4033 <term>Effects:</term>
4034 <listitem>
4035 <para>
4036 Deallocates the stack space.
4037 </para>
4038 </listitem>
4039 </varlistentry>
4040 </variablelist>
4041 <para>
4042 <bridgehead renderas="sect4" id="class_pooled_fixedsize_stack_bridgehead">
4043 <phrase id="class_pooled_fixedsize_stack"/>
4044 <link linkend="class_pooled_fixedsize_stack">Class
4045 <code>pooled_fixedsize_stack</code></link>
4046 </bridgehead>
4047 </para>
4048 <para>
4049 <emphasis role="bold">Boost.Fiber</emphasis> provides the class <link linkend="class_pooled_fixedsize_stack"><code>pooled_fixedsize_stack</code></link> which
4050 models the <link linkend="stack_allocator_concept"><emphasis>stack-allocator
4051 concept</emphasis></link>. In contrast to <link linkend="class_protected_fixedsize_stack"><code>protected_fixedsize_stack</code></link> it
4052 does not append a guard page at the end of each stack. The memory is managed
4053 internally by <ulink url="http://www.boost.org/doc/libs/release/libs/pool/doc/html/boost/pool.html"><code><phrase
4054 role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">pool</phrase><phrase
4055 role="special">&lt;&gt;</phrase></code></ulink>.
4056 </para>
4057 <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>
4058
4059 <phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase>
4060 <phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase>
4061
4062 <phrase role="keyword">struct</phrase> <phrase role="identifier">pooled_fixedsize_stack</phrase> <phrase role="special">{</phrase>
4063 <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>
4064
4065 <phrase role="identifier">stack_context</phrase> <phrase role="identifier">allocate</phrase><phrase role="special">();</phrase>
4066
4067 <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>
4068 <phrase role="special">}</phrase>
4069
4070 <phrase role="special">}}</phrase>
4071 </programlisting>
4072 <para>
4073 <bridgehead renderas="sect4" id="pooled_fixedsize_bridgehead">
4074 <phrase id="pooled_fixedsize"/>
4075 <link linkend="pooled_fixedsize">Constructor</link>
4076 </bridgehead>
4077 </para>
4078 <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>
4079 </programlisting>
4080 <variablelist>
4081 <title></title>
4082 <varlistentry>
4083 <term>Preconditions:</term>
4084 <listitem>
4085 <para>
4086 <code><phrase role="identifier">traits_type</phrase><phrase role="special">::</phrase><phrase
4087 role="identifier">is_unbounded</phrase><phrase role="special">()</phrase>
4088 <phrase role="special">||</phrase> <phrase role="special">(</phrase>
4089 <phrase role="identifier">traits_type</phrase><phrase role="special">::</phrase><phrase
4090 role="identifier">maximum_size</phrase><phrase role="special">()</phrase>
4091 <phrase role="special">&gt;=</phrase> <phrase role="identifier">stack_size</phrase><phrase
4092 role="special">)</phrase></code> and <code><phrase role="number">0</phrase>
4093 <phrase role="special">&lt;</phrase> <phrase role="identifier">next_size</phrase></code>.
4094 </para>
4095 </listitem>
4096 </varlistentry>
4097 <varlistentry>
4098 <term>Effects:</term>
4099 <listitem>
4100 <para>
4101 Allocates memory of at least <code><phrase role="identifier">stack_size</phrase></code>
4102 bytes and stores a pointer to the stack and its actual size in <code><phrase
4103 role="identifier">sctx</phrase></code>. Depending on the architecture
4104 (the stack grows downwards/upwards) the stored address is the highest/lowest
4105 address of the stack. Argument <code><phrase role="identifier">next_size</phrase></code>
4106 determines the number of stacks to request from the system the first
4107 time that <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>
4108 needs to allocate system memory. The third argument <code><phrase role="identifier">max_size</phrase></code>
4109 controls how much memory might be allocated for stacks &mdash; a value of zero
4110 means no upper limit.
4111 </para>
4112 </listitem>
4113 </varlistentry>
4114 </variablelist>
4115 <para>
4116 <bridgehead renderas="sect4" id="pooled_fixedsize_allocate_bridgehead">
4117 <phrase id="pooled_fixedsize_allocate"/>
4118 <link linkend="pooled_fixedsize_allocate">Member
4119 function <code>allocate</code>()</link>
4120 </bridgehead>
4121 </para>
4122 <programlisting><phrase role="identifier">stack_context</phrase> <phrase role="identifier">allocate</phrase><phrase role="special">();</phrase>
4123 </programlisting>
4124 <variablelist>
4125 <title></title>
4126 <varlistentry>
4127 <term>Preconditions:</term>
4128 <listitem>
4129 <para>
4130 <code><phrase role="identifier">traits_type</phrase><phrase role="special">::</phrase><phrase
4131 role="identifier">is_unbounded</phrase><phrase role="special">()</phrase>
4132 <phrase role="special">||</phrase> <phrase role="special">(</phrase>
4133 <phrase role="identifier">traits_type</phrase><phrase role="special">::</phrase><phrase
4134 role="identifier">maximum_size</phrase><phrase role="special">()</phrase>
4135 <phrase role="special">&gt;=</phrase> <phrase role="identifier">stack_size</phrase><phrase
4136 role="special">)</phrase></code>.
4137 </para>
4138 </listitem>
4139 </varlistentry>
4140 <varlistentry>
4141 <term>Effects:</term>
4142 <listitem>
4143 <para>
4144 Allocates memory of at least <code><phrase role="identifier">stack_size</phrase></code>
4145 bytes and stores a pointer to the stack and its actual size in <code><phrase
4146 role="identifier">sctx</phrase></code>. Depending on the architecture
4147 (the stack grows downwards/upwards) the stored address is the highest/lowest
4148 address of the stack.
4149 </para>
4150 </listitem>
4151 </varlistentry>
4152 </variablelist>
4153 <para>
4154 <bridgehead renderas="sect4" id="pooled_fixesize_deallocate_bridgehead">
4155 <phrase id="pooled_fixesize_deallocate"/>
4156 <link linkend="pooled_fixesize_deallocate">Member
4157 function <code>deallocate</code>()</link>
4158 </bridgehead>
4159 </para>
4160 <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>
4161 </programlisting>
4162 <variablelist>
4163 <title></title>
4164 <varlistentry>
4165 <term>Preconditions:</term>
4166 <listitem>
4167 <para>
4168 <code><phrase role="identifier">sctx</phrase><phrase role="special">.</phrase><phrase
4169 role="identifier">sp</phrase></code> is valid, <code><phrase role="identifier">traits_type</phrase><phrase
4170 role="special">::</phrase><phrase role="identifier">is_unbounded</phrase><phrase
4171 role="special">()</phrase> <phrase role="special">||</phrase> <phrase
4172 role="special">(</phrase> <phrase role="identifier">traits_type</phrase><phrase
4173 role="special">::</phrase><phrase role="identifier">maximum_size</phrase><phrase
4174 role="special">()</phrase> <phrase role="special">&gt;=</phrase> <phrase
4175 role="identifier">sctx</phrase><phrase role="special">.</phrase><phrase
4176 role="identifier">size</phrase><phrase role="special">)</phrase></code>.
4177 </para>
4178 </listitem>
4179 </varlistentry>
4180 <varlistentry>
4181 <term>Effects:</term>
4182 <listitem>
4183 <para>
4184 Deallocates the stack space.
4185 </para>
4186 </listitem>
4187 </varlistentry>
4188 </variablelist>
4189 <note>
4190 <para>
4191 This stack allocator is not thread safe.
4192 </para>
4193 </note>
4194 <para>
4195 <bridgehead renderas="sect4" id="class_fixedsize_stack_bridgehead">
4196 <phrase id="class_fixedsize_stack"/>
4197 <link linkend="class_fixedsize_stack">Class
4198 <code>fixedsize_stack</code></link>
4199 </bridgehead>
4200 </para>
4201 <para>
4202 <emphasis role="bold">Boost.Fiber</emphasis> provides the class <link linkend="class_fixedsize_stack"><code>fixedsize_stack</code></link> which
4203 models the <link linkend="stack_allocator_concept"><emphasis>stack-allocator
4204 concept</emphasis></link>. In contrast to <link linkend="class_protected_fixedsize_stack"><code>protected_fixedsize_stack</code></link> it
4205 does not append a guard page at the end of each stack. The memory is simply
4206 managed by <code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase
4207 role="identifier">malloc</phrase><phrase role="special">()</phrase></code>
4208 and <code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase
4209 role="identifier">free</phrase><phrase role="special">()</phrase></code>.
4210 </para>
4211 <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>
4212
4213 <phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase>
4214 <phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase>
4215
4216 <phrase role="keyword">struct</phrase> <phrase role="identifier">fixedsize_stack</phrase> <phrase role="special">{</phrase>
4217 <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>
4218
4219 <phrase role="identifier">stack_context</phrase> <phrase role="identifier">allocate</phrase><phrase role="special">();</phrase>
4220
4221 <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>
4222 <phrase role="special">}</phrase>
4223
4224 <phrase role="special">}}</phrase>
4225 </programlisting>
4226 <para>
4227 <bridgehead renderas="sect4" id="fixedsize_allocate_bridgehead">
4228 <phrase id="fixedsize_allocate"/>
4229 <link linkend="fixedsize_allocate">Member function
4230 <code>allocate</code>()</link>
4231 </bridgehead>
4232 </para>
4233 <programlisting><phrase role="identifier">stack_context</phrase> <phrase role="identifier">allocate</phrase><phrase role="special">();</phrase>
4234 </programlisting>
4235 <variablelist>
4236 <title></title>
4237 <varlistentry>
4238 <term>Preconditions:</term>
4239 <listitem>
4240 <para>
4241 <code><phrase role="identifier">traits_type</phrase><phrase role="special">::</phrase><phrase
4242 role="identifier">minimum_size</phrase><phrase role="special">()</phrase>
4243 <phrase role="special">&lt;=</phrase> <phrase role="identifier">size</phrase></code>
4244 and <code><phrase role="identifier">traits_type</phrase><phrase role="special">::</phrase><phrase
4245 role="identifier">is_unbounded</phrase><phrase role="special">()</phrase>
4246 <phrase role="special">||</phrase> <phrase role="special">(</phrase>
4247 <phrase role="identifier">traits_type</phrase><phrase role="special">::</phrase><phrase
4248 role="identifier">maximum_size</phrase><phrase role="special">()</phrase>
4249 <phrase role="special">&gt;=</phrase> <phrase role="identifier">size</phrase><phrase
4250 role="special">)</phrase></code>.
4251 </para>
4252 </listitem>
4253 </varlistentry>
4254 <varlistentry>
4255 <term>Effects:</term>
4256 <listitem>
4257 <para>
4258 Allocates memory of at least <code><phrase role="identifier">size</phrase></code>
4259 bytes and stores a pointer to the stack and its actual size in <code><phrase
4260 role="identifier">sctx</phrase></code>. Depending on the architecture
4261 (the stack grows downwards/upwards) the stored address is the highest/lowest
4262 address of the stack.
4263 </para>
4264 </listitem>
4265 </varlistentry>
4266 </variablelist>
4267 <para>
4268 <bridgehead renderas="sect4" id="fixesize_deallocate_bridgehead">
4269 <phrase id="fixesize_deallocate"/>
4270 <link linkend="fixesize_deallocate">Member
4271 function <code>deallocate</code>()</link>
4272 </bridgehead>
4273 </para>
4274 <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>
4275 </programlisting>
4276 <variablelist>
4277 <title></title>
4278 <varlistentry>
4279 <term>Preconditions:</term>
4280 <listitem>
4281 <para>
4282 <code><phrase role="identifier">sctx</phrase><phrase role="special">.</phrase><phrase
4283 role="identifier">sp</phrase></code> is valid, <code><phrase role="identifier">traits_type</phrase><phrase
4284 role="special">::</phrase><phrase role="identifier">minimum_size</phrase><phrase
4285 role="special">()</phrase> <phrase role="special">&lt;=</phrase> <phrase
4286 role="identifier">sctx</phrase><phrase role="special">.</phrase><phrase
4287 role="identifier">size</phrase></code> and <code><phrase role="identifier">traits_type</phrase><phrase
4288 role="special">::</phrase><phrase role="identifier">is_unbounded</phrase><phrase
4289 role="special">()</phrase> <phrase role="special">||</phrase> <phrase
4290 role="special">(</phrase> <phrase role="identifier">traits_type</phrase><phrase
4291 role="special">::</phrase><phrase role="identifier">maximum_size</phrase><phrase
4292 role="special">()</phrase> <phrase role="special">&gt;=</phrase> <phrase
4293 role="identifier">sctx</phrase><phrase role="special">.</phrase><phrase
4294 role="identifier">size</phrase><phrase role="special">)</phrase></code>.
4295 </para>
4296 </listitem>
4297 </varlistentry>
4298 <varlistentry>
4299 <term>Effects:</term>
4300 <listitem>
4301 <para>
4302 Deallocates the stack space.
4303 </para>
4304 </listitem>
4305 </varlistentry>
4306 </variablelist>
4307 <para>
4308 <bridgehead renderas="sect4" id="class_segmented_stack_bridgehead">
4309 <phrase id="class_segmented_stack"/>
4310 <link linkend="class_segmented_stack">Class
4311 <code>segmented_stack</code></link>
4312 </bridgehead>
4313 </para>
4314 <para>
4315 <emphasis role="bold">Boost.Fiber</emphasis> supports usage of a <link linkend="class_segmented_stack"><code>segmented_stack</code></link>,
4316 i.e. the stack grows on demand. The fiber is created with a minimal stack size
4317 which will be increased as required. Class <link linkend="class_segmented_stack"><code>segmented_stack</code></link> models
4318 the <link linkend="stack_allocator_concept"><emphasis>stack-allocator concept</emphasis></link>.
4319 In contrast to <link linkend="class_protected_fixedsize_stack"><code>protected_fixedsize_stack</code></link> and
4320 <link linkend="class_fixedsize_stack"><code>fixedsize_stack</code></link> it creates a stack which grows on demand.
4321 </para>
4322 <note>
4323 <para>
4324 Segmented stacks are currently only supported by <emphasis role="bold">gcc</emphasis>
4325 from version <emphasis role="bold">4.7</emphasis> and <emphasis role="bold">clang</emphasis>
4326 from version <emphasis role="bold">3.4</emphasis> onwards. In order to use
4327 a <link linkend="class_segmented_stack"><code>segmented_stack</code></link> <emphasis role="bold">Boost.Fiber</emphasis>
4328 must be built with property <code><phrase role="identifier">segmented</phrase><phrase
4329 role="special">-</phrase><phrase role="identifier">stacks</phrase></code>,
4330 e.g. <emphasis role="bold">toolset=gcc segmented-stacks=on</emphasis> at
4331 b2/bjam command line.
4332 </para>
4333 </note>
4334 <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>
4335
4336 <phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase>
4337 <phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase>
4338
4339 <phrase role="keyword">struct</phrase> <phrase role="identifier">segmented_stack</phrase> <phrase role="special">{</phrase>
4340 <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>
4341
4342 <phrase role="identifier">stack_context</phrase> <phrase role="identifier">allocate</phrase><phrase role="special">();</phrase>
4343
4344 <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>
4345 <phrase role="special">}</phrase>
4346
4347 <phrase role="special">}}</phrase>
4348 </programlisting>
4349 <para>
4350 <bridgehead renderas="sect4" id="segmented_allocate_bridgehead">
4351 <phrase id="segmented_allocate"/>
4352 <link linkend="segmented_allocate">Member function
4353 <code>allocate</code>()</link>
4354 </bridgehead>
4355 </para>
4356 <programlisting><phrase role="identifier">stack_context</phrase> <phrase role="identifier">allocate</phrase><phrase role="special">();</phrase>
4357 </programlisting>
4358 <variablelist>
4359 <title></title>
4360 <varlistentry>
4361 <term>Preconditions:</term>
4362 <listitem>
4363 <para>
4364 <code><phrase role="identifier">traits_type</phrase><phrase role="special">::</phrase><phrase
4365 role="identifier">minimum_size</phrase><phrase role="special">()</phrase>
4366 <phrase role="special">&lt;=</phrase> <phrase role="identifier">size</phrase></code>
4367 and <code><phrase role="identifier">traits_type</phrase><phrase role="special">::</phrase><phrase
4368 role="identifier">is_unbounded</phrase><phrase role="special">()</phrase>
4369 <phrase role="special">||</phrase> <phrase role="special">(</phrase>
4370 <phrase role="identifier">traits_type</phrase><phrase role="special">::</phrase><phrase
4371 role="identifier">maximum_size</phrase><phrase role="special">()</phrase>
4372 <phrase role="special">&gt;=</phrase> <phrase role="identifier">size</phrase><phrase
4373 role="special">)</phrase></code>.
4374 </para>
4375 </listitem>
4376 </varlistentry>
4377 <varlistentry>
4378 <term>Effects:</term>
4379 <listitem>
4380 <para>
4381 Allocates memory of at least <code><phrase role="identifier">size</phrase></code>
4382 bytes and stores a pointer to the stack and its actual size in <code><phrase
4383 role="identifier">sctx</phrase></code>. Depending on the architecture
4384 (the stack grows downwards/upwards) the stored address is the highest/lowest
4385 address of the stack.
4386 </para>
4387 </listitem>
4388 </varlistentry>
4389 </variablelist>
4390 <para>
4391 <bridgehead renderas="sect4" id="segmented_deallocate_bridgehead">
4392 <phrase id="segmented_deallocate"/>
4393 <link linkend="segmented_deallocate">Member
4394 function <code>deallocate</code>()</link>
4395 </bridgehead>
4396 </para>
4397 <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>
4398 </programlisting>
4399 <variablelist>
4400 <title></title>
4401 <varlistentry>
4402 <term>Preconditions:</term>
4403 <listitem>
4404 <para>
4405 <code><phrase role="identifier">sctx</phrase><phrase role="special">.</phrase><phrase
4406 role="identifier">sp</phrase></code> is valid, <code><phrase role="identifier">traits_type</phrase><phrase
4407 role="special">::</phrase><phrase role="identifier">minimum_size</phrase><phrase
4408 role="special">()</phrase> <phrase role="special">&lt;=</phrase> <phrase
4409 role="identifier">sctx</phrase><phrase role="special">.</phrase><phrase
4410 role="identifier">size</phrase></code> and <code><phrase role="identifier">traits_type</phrase><phrase
4411 role="special">::</phrase><phrase role="identifier">is_unbounded</phrase><phrase
4412 role="special">()</phrase> <phrase role="special">||</phrase> <phrase
4413 role="special">(</phrase> <phrase role="identifier">traits_type</phrase><phrase
4414 role="special">::</phrase><phrase role="identifier">maximum_size</phrase><phrase
4415 role="special">()</phrase> <phrase role="special">&gt;=</phrase> <phrase
4416 role="identifier">sctx</phrase><phrase role="special">.</phrase><phrase
4417 role="identifier">size</phrase><phrase role="special">)</phrase></code>.
4418 </para>
4419 </listitem>
4420 </varlistentry>
4421 <varlistentry>
4422 <term>Effects:</term>
4423 <listitem>
4424 <para>
4425 Deallocates the stack space.
4426 </para>
4427 </listitem>
4428 </varlistentry>
4429 </variablelist>
4430 <note>
4431 <para>
4432 If the library is compiled for segmented stacks, <link linkend="class_segmented_stack"><code>segmented_stack</code></link> is
4433 the only available stack allocator.
4434 </para>
4435 </note>
4436 </section>
4437 <section id="fiber.synchronization">
4438 <title><anchor id="synchronization"/><link linkend="fiber.synchronization">Synchronization</link></title>
4439 <para>
4440 In general, <emphasis role="bold">Boost.Fiber</emphasis> synchronization objects
4441 can neither be moved nor copied. A synchronization object acts as a mutually-agreed
4442 rendezvous point between different fibers. If such an object were copied somewhere
4443 else, the new copy would have no consumers. If such an object were <emphasis>moved</emphasis>
4444 somewhere else, leaving the original instance in an unspecified state, existing
4445 consumers would behave strangely.
4446 </para>
4447 <para>
4448 The fiber synchronization objects provided by this library will, by default,
4449 safely synchronize fibers running on different threads. However, this level
4450 of synchronization can be removed (for performance) by building the library
4451 with <emphasis role="bold"><code><phrase role="identifier">BOOST_FIBERS_NO_ATOMICS</phrase></code></emphasis>
4452 defined. When the library is built with that macro, you must ensure that all
4453 the fibers referencing a particular synchronization object are running in the
4454 same thread.
4455 </para>
4456 <section id="fiber.synchronization.mutex_types">
4457 <title><link linkend="fiber.synchronization.mutex_types">Mutex Types</link></title>
4458 <para>
4459 <bridgehead renderas="sect4" id="class_mutex_bridgehead">
4460 <phrase id="class_mutex"/>
4461 <link linkend="class_mutex">Class <code>mutex</code></link>
4462 </bridgehead>
4463 </para>
4464 <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>
4465
4466 <phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase>
4467 <phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase>
4468
4469 <phrase role="keyword">class</phrase> <phrase role="identifier">mutex</phrase> <phrase role="special">{</phrase>
4470 <phrase role="keyword">public</phrase><phrase role="special">:</phrase>
4471 <phrase role="identifier">mutex</phrase><phrase role="special">();</phrase>
4472 <phrase role="special">~</phrase><phrase role="identifier">mutex</phrase><phrase role="special">();</phrase>
4473
4474 <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>
4475 <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>
4476
4477 <phrase role="keyword">void</phrase> <phrase role="identifier">lock</phrase><phrase role="special">();</phrase>
4478 <phrase role="keyword">bool</phrase> <phrase role="identifier">try_lock</phrase><phrase role="special">();</phrase>
4479 <phrase role="keyword">void</phrase> <phrase role="identifier">unlock</phrase><phrase role="special">();</phrase>
4480 <phrase role="special">};</phrase>
4481
4482 <phrase role="special">}}</phrase>
4483 </programlisting>
4484 <para>
4485 <link linkend="class_mutex"><code>mutex</code></link> provides an exclusive-ownership mutex. At most one fiber
4486 can own the lock on a given instance of <link linkend="class_mutex"><code>mutex</code></link> at any time. Multiple
4487 concurrent calls to <code><phrase role="identifier">lock</phrase><phrase
4488 role="special">()</phrase></code>, <code><phrase role="identifier">try_lock</phrase><phrase
4489 role="special">()</phrase></code> and <code><phrase role="identifier">unlock</phrase><phrase
4490 role="special">()</phrase></code> shall be permitted.
4491 </para>
4492 <para>
4493 Any fiber blocked in <code><phrase role="identifier">lock</phrase><phrase
4494 role="special">()</phrase></code> is suspended until the owning fiber releases
4495 the lock by calling <code><phrase role="identifier">unlock</phrase><phrase
4496 role="special">()</phrase></code>.
4497 </para>
4498 <para>
4499 <bridgehead renderas="sect4" id="mutex_lock_bridgehead">
4500 <phrase id="mutex_lock"/>
4501 <link linkend="mutex_lock">Member function <code>lock</code>()</link>
4502 </bridgehead>
4503 </para>
4504 <programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">lock</phrase><phrase role="special">();</phrase>
4505 </programlisting>
4506 <variablelist>
4507 <title></title>
4508 <varlistentry>
4509 <term>Precondition:</term>
4510 <listitem>
4511 <para>
4512 The calling fiber doesn't own the mutex.
4513 </para>
4514 </listitem>
4515 </varlistentry>
4516 <varlistentry>
4517 <term>Effects:</term>
4518 <listitem>
4519 <para>
4520 The current fiber blocks until ownership can be obtained.
4521 </para>
4522 </listitem>
4523 </varlistentry>
4524 <varlistentry>
4525 <term>Throws:</term>
4526 <listitem>
4527 <para>
4528 <code><phrase role="identifier">lock_error</phrase></code>
4529 </para>
4530 </listitem>
4531 </varlistentry>
4532 <varlistentry>
4533 <term>Error Conditions:</term>
4534 <listitem>
4535 <para>
4536 <emphasis role="bold">resource_deadlock_would_occur</emphasis>: if
4537 <code><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase
4538 role="identifier">this_fiber</phrase><phrase role="special">::</phrase><phrase
4539 role="identifier">get_id</phrase><phrase role="special">()</phrase></code>
4540 already owns the mutex.
4541 </para>
4542 </listitem>
4543 </varlistentry>
4544 </variablelist>
4545 <para>
4546 <bridgehead renderas="sect4" id="mutex_try_lock_bridgehead">
4547 <phrase id="mutex_try_lock"/>
4548 <link linkend="mutex_try_lock">Member function <code>try_lock</code>()</link>
4549 </bridgehead>
4550 </para>
4551 <programlisting><phrase role="keyword">bool</phrase> <phrase role="identifier">try_lock</phrase><phrase role="special">();</phrase>
4552 </programlisting>
4553 <variablelist>
4554 <title></title>
4555 <varlistentry>
4556 <term>Precondition:</term>
4557 <listitem>
4558 <para>
4559 The calling fiber doesn't own the mutex.
4560 </para>
4561 </listitem>
4562 </varlistentry>
4563 <varlistentry>
4564 <term>Effects:</term>
4565 <listitem>
4566 <para>
4567 Attempt to obtain ownership for the current fiber without blocking.
4568 </para>
4569 </listitem>
4570 </varlistentry>
4571 <varlistentry>
4572 <term>Returns:</term>
4573 <listitem>
4574 <para>
4575 <code><phrase role="keyword">true</phrase></code> if ownership was
4576 obtained for the current fiber, <code><phrase role="keyword">false</phrase></code>
4577 otherwise.
4578 </para>
4579 </listitem>
4580 </varlistentry>
4581 <varlistentry>
4582 <term>Throws:</term>
4583 <listitem>
4584 <para>
4585 <code><phrase role="identifier">lock_error</phrase></code>
4586 </para>
4587 </listitem>
4588 </varlistentry>
4589 <varlistentry>
4590 <term>Error Conditions:</term>
4591 <listitem>
4592 <para>
4593 <emphasis role="bold">resource_deadlock_would_occur</emphasis>: if
4594 <code><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase
4595 role="identifier">this_fiber</phrase><phrase role="special">::</phrase><phrase
4596 role="identifier">get_id</phrase><phrase role="special">()</phrase></code>
4597 already owns the mutex.
4598 </para>
4599 </listitem>
4600 </varlistentry>
4601 </variablelist>
4602 <para>
4603 <bridgehead renderas="sect4" id="mutex_unlock_bridgehead">
4604 <phrase id="mutex_unlock"/>
4605 <link linkend="mutex_unlock">Member function <code>unlock</code>()</link>
4606 </bridgehead>
4607 </para>
4608 <programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">unlock</phrase><phrase role="special">();</phrase>
4609 </programlisting>
4610 <variablelist>
4611 <title></title>
4612 <varlistentry>
4613 <term>Precondition:</term>
4614 <listitem>
4615 <para>
4616 The current fiber owns <code><phrase role="special">*</phrase><phrase
4617 role="keyword">this</phrase></code>.
4618 </para>
4619 </listitem>
4620 </varlistentry>
4621 <varlistentry>
4622 <term>Effects:</term>
4623 <listitem>
4624 <para>
4625 Releases a lock on <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>
4626 by the current fiber.
4627 </para>
4628 </listitem>
4629 </varlistentry>
4630 <varlistentry>
4631 <term>Throws:</term>
4632 <listitem>
4633 <para>
4634 <code><phrase role="identifier">lock_error</phrase></code>
4635 </para>
4636 </listitem>
4637 </varlistentry>
4638 <varlistentry>
4639 <term>Error Conditions:</term>
4640 <listitem>
4641 <para>
4642 <emphasis role="bold">operation_not_permitted</emphasis>: if <code><phrase
4643 role="identifier">boost</phrase><phrase role="special">::</phrase><phrase
4644 role="identifier">this_fiber</phrase><phrase role="special">::</phrase><phrase
4645 role="identifier">get_id</phrase><phrase role="special">()</phrase></code>
4646 does not own the mutex.
4647 </para>
4648 </listitem>
4649 </varlistentry>
4650 </variablelist>
4651 <para>
4652 <bridgehead renderas="sect4" id="class_timed_mutex_bridgehead">
4653 <phrase id="class_timed_mutex"/>
4654 <link linkend="class_timed_mutex">Class <code>timed_mutex</code></link>
4655 </bridgehead>
4656 </para>
4657 <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>
4658
4659 <phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase>
4660 <phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase>
4661
4662 <phrase role="keyword">class</phrase> <phrase role="identifier">timed_mutex</phrase> <phrase role="special">{</phrase>
4663 <phrase role="keyword">public</phrase><phrase role="special">:</phrase>
4664 <phrase role="identifier">timed_mutex</phrase><phrase role="special">();</phrase>
4665 <phrase role="special">~</phrase><phrase role="identifier">timed_mutex</phrase><phrase role="special">();</phrase>
4666
4667 <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>
4668 <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>
4669
4670 <phrase role="keyword">void</phrase> <phrase role="identifier">lock</phrase><phrase role="special">();</phrase>
4671 <phrase role="keyword">bool</phrase> <phrase role="identifier">try_lock</phrase><phrase role="special">();</phrase>
4672 <phrase role="keyword">void</phrase> <phrase role="identifier">unlock</phrase><phrase role="special">();</phrase>
4673
4674 <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>
4675 <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>
4676 <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>
4677 <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>
4678 <phrase role="special">};</phrase>
4679
4680 <phrase role="special">}}</phrase>
4681 </programlisting>
4682 <para>
4683 <link linkend="class_timed_mutex"><code>timed_mutex</code></link> provides an exclusive-ownership mutex. At most
4684 one fiber can own the lock on a given instance of <link linkend="class_timed_mutex"><code>timed_mutex</code></link> at
4685 any time. Multiple concurrent calls to <code><phrase role="identifier">lock</phrase><phrase
4686 role="special">()</phrase></code>, <code><phrase role="identifier">try_lock</phrase><phrase
4687 role="special">()</phrase></code>, <code><phrase role="identifier">try_lock_until</phrase><phrase
4688 role="special">()</phrase></code>, <code><phrase role="identifier">try_lock_for</phrase><phrase
4689 role="special">()</phrase></code> and <code><phrase role="identifier">unlock</phrase><phrase
4690 role="special">()</phrase></code> shall be permitted.
4691 </para>
4692 <para>
4693 <bridgehead renderas="sect4" id="timed_mutex_lock_bridgehead">
4694 <phrase id="timed_mutex_lock"/>
4695 <link linkend="timed_mutex_lock">Member function
4696 <code>lock</code>()</link>
4697 </bridgehead>
4698 </para>
4699 <programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">lock</phrase><phrase role="special">();</phrase>
4700 </programlisting>
4701 <variablelist>
4702 <title></title>
4703 <varlistentry>
4704 <term>Precondition:</term>
4705 <listitem>
4706 <para>
4707 The calling fiber doesn't own the mutex.
4708 </para>
4709 </listitem>
4710 </varlistentry>
4711 <varlistentry>
4712 <term>Effects:</term>
4713 <listitem>
4714 <para>
4715 The current fiber blocks until ownership can be obtained.
4716 </para>
4717 </listitem>
4718 </varlistentry>
4719 <varlistentry>
4720 <term>Throws:</term>
4721 <listitem>
4722 <para>
4723 <code><phrase role="identifier">lock_error</phrase></code>
4724 </para>
4725 </listitem>
4726 </varlistentry>
4727 <varlistentry>
4728 <term>Error Conditions:</term>
4729 <listitem>
4730 <para>
4731 <emphasis role="bold">resource_deadlock_would_occur</emphasis>: if
4732 <code><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase
4733 role="identifier">this_fiber</phrase><phrase role="special">::</phrase><phrase
4734 role="identifier">get_id</phrase><phrase role="special">()</phrase></code>
4735 already owns the mutex.
4736 </para>
4737 </listitem>
4738 </varlistentry>
4739 </variablelist>
4740 <para>
4741 <bridgehead renderas="sect4" id="timed_mutex_try_lock_bridgehead">
4742 <phrase id="timed_mutex_try_lock"/>
4743 <link linkend="timed_mutex_try_lock">Member
4744 function <code>try_lock</code>()</link>
4745 </bridgehead>
4746 </para>
4747 <programlisting><phrase role="keyword">bool</phrase> <phrase role="identifier">try_lock</phrase><phrase role="special">();</phrase>
4748 </programlisting>
4749 <variablelist>
4750 <title></title>
4751 <varlistentry>
4752 <term>Precondition:</term>
4753 <listitem>
4754 <para>
4755 The calling fiber doesn't own the mutex.
4756 </para>
4757 </listitem>
4758 </varlistentry>
4759 <varlistentry>
4760 <term>Effects:</term>
4761 <listitem>
4762 <para>
4763 Attempt to obtain ownership for the current fiber without blocking.
4764 </para>
4765 </listitem>
4766 </varlistentry>
4767 <varlistentry>
4768 <term>Returns:</term>
4769 <listitem>
4770 <para>
4771 <code><phrase role="keyword">true</phrase></code> if ownership was
4772 obtained for the current fiber, <code><phrase role="keyword">false</phrase></code>
4773 otherwise.
4774 </para>
4775 </listitem>
4776 </varlistentry>
4777 <varlistentry>
4778 <term>Throws:</term>
4779 <listitem>
4780 <para>
4781 <code><phrase role="identifier">lock_error</phrase></code>
4782 </para>
4783 </listitem>
4784 </varlistentry>
4785 <varlistentry>
4786 <term>Error Conditions:</term>
4787 <listitem>
4788 <para>
4789 <emphasis role="bold">resource_deadlock_would_occur</emphasis>: if
4790 <code><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase
4791 role="identifier">this_fiber</phrase><phrase role="special">::</phrase><phrase
4792 role="identifier">get_id</phrase><phrase role="special">()</phrase></code>
4793 already owns the mutex.
4794 </para>
4795 </listitem>
4796 </varlistentry>
4797 </variablelist>
4798 <para>
4799 <bridgehead renderas="sect4" id="timed_mutex_unlock_bridgehead">
4800 <phrase id="timed_mutex_unlock"/>
4801 <link linkend="timed_mutex_unlock">Member function
4802 <code>unlock</code>()</link>
4803 </bridgehead>
4804 </para>
4805 <programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">unlock</phrase><phrase role="special">();</phrase>
4806 </programlisting>
4807 <variablelist>
4808 <title></title>
4809 <varlistentry>
4810 <term>Precondition:</term>
4811 <listitem>
4812 <para>
4813 The current fiber owns <code><phrase role="special">*</phrase><phrase
4814 role="keyword">this</phrase></code>.
4815 </para>
4816 </listitem>
4817 </varlistentry>
4818 <varlistentry>
4819 <term>Effects:</term>
4820 <listitem>
4821 <para>
4822 Releases a lock on <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>
4823 by the current fiber.
4824 </para>
4825 </listitem>
4826 </varlistentry>
4827 <varlistentry>
4828 <term>Throws:</term>
4829 <listitem>
4830 <para>
4831 <code><phrase role="identifier">lock_error</phrase></code>
4832 </para>
4833 </listitem>
4834 </varlistentry>
4835 <varlistentry>
4836 <term>Error Conditions:</term>
4837 <listitem>
4838 <para>
4839 <emphasis role="bold">operation_not_permitted</emphasis>: if <code><phrase
4840 role="identifier">boost</phrase><phrase role="special">::</phrase><phrase
4841 role="identifier">this_fiber</phrase><phrase role="special">::</phrase><phrase
4842 role="identifier">get_id</phrase><phrase role="special">()</phrase></code>
4843 does not own the mutex.
4844 </para>
4845 </listitem>
4846 </varlistentry>
4847 </variablelist>
4848 <para>
4849 <bridgehead renderas="sect4" id="timed_mutex_try_lock_until_bridgehead">
4850 <phrase id="timed_mutex_try_lock_until"/>
4851 <link linkend="timed_mutex_try_lock_until">Templated
4852 member function <code>try_lock_until</code>()</link>
4853 </bridgehead>
4854 </para>
4855 <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>
4856 <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>
4857 </programlisting>
4858 <variablelist>
4859 <title></title>
4860 <varlistentry>
4861 <term>Precondition:</term>
4862 <listitem>
4863 <para>
4864 The calling fiber doesn't own the mutex.
4865 </para>
4866 </listitem>
4867 </varlistentry>
4868 <varlistentry>
4869 <term>Effects:</term>
4870 <listitem>
4871 <para>
4872 Attempt to obtain ownership for the current fiber. Blocks until ownership
4873 can be obtained, or the specified time is reached. If the specified
4874 time has already passed, behaves as <link linkend="timed_mutex_try_lock"><code>timed_mutex::try_lock()</code></link>.
4875 </para>
4876 </listitem>
4877 </varlistentry>
4878 <varlistentry>
4879 <term>Returns:</term>
4880 <listitem>
4881 <para>
4882 <code><phrase role="keyword">true</phrase></code> if ownership was
4883 obtained for the current fiber, <code><phrase role="keyword">false</phrase></code>
4884 otherwise.
4885 </para>
4886 </listitem>
4887 </varlistentry>
4888 <varlistentry>
4889 <term>Throws:</term>
4890 <listitem>
4891 <para>
4892 <code><phrase role="identifier">lock_error</phrase></code>, timeout-related
4893 exceptions.
4894 </para>
4895 </listitem>
4896 </varlistentry>
4897 <varlistentry>
4898 <term>Error Conditions:</term>
4899 <listitem>
4900 <para>
4901 <emphasis role="bold">resource_deadlock_would_occur</emphasis>: if
4902 <code><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase
4903 role="identifier">this_fiber</phrase><phrase role="special">::</phrase><phrase
4904 role="identifier">get_id</phrase><phrase role="special">()</phrase></code>
4905 already owns the mutex.
4906 </para>
4907 </listitem>
4908 </varlistentry>
4909 </variablelist>
4910 <para>
4911 <bridgehead renderas="sect4" id="timed_mutex_try_lock_for_bridgehead">
4912 <phrase id="timed_mutex_try_lock_for"/>
4913 <link linkend="timed_mutex_try_lock_for">Templated
4914 member function <code>try_lock_for</code>()</link>
4915 </bridgehead>
4916 </para>
4917 <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>
4918 <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>
4919 </programlisting>
4920 <variablelist>
4921 <title></title>
4922 <varlistentry>
4923 <term>Precondition:</term>
4924 <listitem>
4925 <para>
4926 The calling fiber doesn't own the mutex.
4927 </para>
4928 </listitem>
4929 </varlistentry>
4930 <varlistentry>
4931 <term>Effects:</term>
4932 <listitem>
4933 <para>
4934 Attempt to obtain ownership for the current fiber. Blocks until ownership
4935 can be obtained, or the specified time is reached. If the specified
4936 time has already passed, behaves as <link linkend="timed_mutex_try_lock"><code>timed_mutex::try_lock()</code></link>.
4937 </para>
4938 </listitem>
4939 </varlistentry>
4940 <varlistentry>
4941 <term>Returns:</term>
4942 <listitem>
4943 <para>
4944 <code><phrase role="keyword">true</phrase></code> if ownership was
4945 obtained for the current fiber, <code><phrase role="keyword">false</phrase></code>
4946 otherwise.
4947 </para>
4948 </listitem>
4949 </varlistentry>
4950 <varlistentry>
4951 <term>Throws:</term>
4952 <listitem>
4953 <para>
4954 <code><phrase role="identifier">lock_error</phrase></code>, timeout-related
4955 exceptions.
4956 </para>
4957 </listitem>
4958 </varlistentry>
4959 <varlistentry>
4960 <term>Error Conditions:</term>
4961 <listitem>
4962 <para>
4963 <emphasis role="bold">resource_deadlock_would_occur</emphasis>: if
4964 <code><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase
4965 role="identifier">this_fiber</phrase><phrase role="special">::</phrase><phrase
4966 role="identifier">get_id</phrase><phrase role="special">()</phrase></code>
4967 already owns the mutex.
4968 </para>
4969 </listitem>
4970 </varlistentry>
4971 </variablelist>
4972 <para>
4973 <bridgehead renderas="sect4" id="class_recursive_mutex_bridgehead">
4974 <phrase id="class_recursive_mutex"/>
4975 <link linkend="class_recursive_mutex">Class
4976 <code>recursive_mutex</code></link>
4977 </bridgehead>
4978 </para>
4979 <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>
4980
4981 <phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase>
4982 <phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase>
4983
4984 <phrase role="keyword">class</phrase> <phrase role="identifier">recursive_mutex</phrase> <phrase role="special">{</phrase>
4985 <phrase role="keyword">public</phrase><phrase role="special">:</phrase>
4986 <phrase role="identifier">recursive_mutex</phrase><phrase role="special">();</phrase>
4987 <phrase role="special">~</phrase><phrase role="identifier">recursive_mutex</phrase><phrase role="special">();</phrase>
4988
4989 <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>
4990 <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>
4991
4992 <phrase role="keyword">void</phrase> <phrase role="identifier">lock</phrase><phrase role="special">();</phrase>
4993 <phrase role="keyword">bool</phrase> <phrase role="identifier">try_lock</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
4994 <phrase role="keyword">void</phrase> <phrase role="identifier">unlock</phrase><phrase role="special">();</phrase>
4995 <phrase role="special">};</phrase>
4996
4997 <phrase role="special">}}</phrase>
4998 </programlisting>
4999 <para>
5000 <link linkend="class_recursive_mutex"><code>recursive_mutex</code></link> provides an exclusive-ownership recursive
5001 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
5002 any time. Multiple concurrent calls to <code><phrase role="identifier">lock</phrase><phrase
5003 role="special">()</phrase></code>, <code><phrase role="identifier">try_lock</phrase><phrase
5004 role="special">()</phrase></code> and <code><phrase role="identifier">unlock</phrase><phrase
5005 role="special">()</phrase></code> shall be permitted. A fiber that already
5006 has exclusive ownership of a given <link linkend="class_recursive_mutex"><code>recursive_mutex</code></link> instance
5007 can call <code><phrase role="identifier">lock</phrase><phrase role="special">()</phrase></code>
5008 or <code><phrase role="identifier">try_lock</phrase><phrase role="special">()</phrase></code>
5009 to acquire an additional level of ownership of the mutex. <code><phrase role="identifier">unlock</phrase><phrase
5010 role="special">()</phrase></code> must be called once for each level of ownership
5011 acquired by a single fiber before ownership can be acquired by another fiber.
5012 </para>
5013 <para>
5014 <bridgehead renderas="sect4" id="recursive_mutex_lock_bridgehead">
5015 <phrase id="recursive_mutex_lock"/>
5016 <link linkend="recursive_mutex_lock">Member
5017 function <code>lock</code>()</link>
5018 </bridgehead>
5019 </para>
5020 <programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">lock</phrase><phrase role="special">();</phrase>
5021 </programlisting>
5022 <variablelist>
5023 <title></title>
5024 <varlistentry>
5025 <term>Effects:</term>
5026 <listitem>
5027 <para>
5028 The current fiber blocks until ownership can be obtained.
5029 </para>
5030 </listitem>
5031 </varlistentry>
5032 <varlistentry>
5033 <term>Throws:</term>
5034 <listitem>
5035 <para>
5036 Nothing
5037 </para>
5038 </listitem>
5039 </varlistentry>
5040 </variablelist>
5041 <para>
5042 <bridgehead renderas="sect4" id="recursive_mutex_try_lock_bridgehead">
5043 <phrase id="recursive_mutex_try_lock"/>
5044 <link linkend="recursive_mutex_try_lock">Member
5045 function <code>try_lock</code>()</link>
5046 </bridgehead>
5047 </para>
5048 <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>
5049 </programlisting>
5050 <variablelist>
5051 <title></title>
5052 <varlistentry>
5053 <term>Effects:</term>
5054 <listitem>
5055 <para>
5056 Attempt to obtain ownership for the current fiber without blocking.
5057 </para>
5058 </listitem>
5059 </varlistentry>
5060 <varlistentry>
5061 <term>Returns:</term>
5062 <listitem>
5063 <para>
5064 <code><phrase role="keyword">true</phrase></code> if ownership was
5065 obtained for the current fiber, <code><phrase role="keyword">false</phrase></code>
5066 otherwise.
5067 </para>
5068 </listitem>
5069 </varlistentry>
5070 <varlistentry>
5071 <term>Throws:</term>
5072 <listitem>
5073 <para>
5074 Nothing.
5075 </para>
5076 </listitem>
5077 </varlistentry>
5078 </variablelist>
5079 <para>
5080 <bridgehead renderas="sect4" id="recursive_mutex_unlock_bridgehead">
5081 <phrase id="recursive_mutex_unlock"/>
5082 <link linkend="recursive_mutex_unlock">Member
5083 function <code>unlock</code>()</link>
5084 </bridgehead>
5085 </para>
5086 <programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">unlock</phrase><phrase role="special">();</phrase>
5087 </programlisting>
5088 <variablelist>
5089 <title></title>
5090 <varlistentry>
5091 <term>Effects:</term>
5092 <listitem>
5093 <para>
5094 Releases a lock on <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>
5095 by the current fiber.
5096 </para>
5097 </listitem>
5098 </varlistentry>
5099 <varlistentry>
5100 <term>Throws:</term>
5101 <listitem>
5102 <para>
5103 <code><phrase role="identifier">lock_error</phrase></code>
5104 </para>
5105 </listitem>
5106 </varlistentry>
5107 <varlistentry>
5108 <term>Error Conditions:</term>
5109 <listitem>
5110 <para>
5111 <emphasis role="bold">operation_not_permitted</emphasis>: if <code><phrase
5112 role="identifier">boost</phrase><phrase role="special">::</phrase><phrase
5113 role="identifier">this_fiber</phrase><phrase role="special">::</phrase><phrase
5114 role="identifier">get_id</phrase><phrase role="special">()</phrase></code>
5115 does not own the mutex.
5116 </para>
5117 </listitem>
5118 </varlistentry>
5119 </variablelist>
5120 <para>
5121 <bridgehead renderas="sect4" id="class_recursive_timed_mutex_bridgehead">
5122 <phrase id="class_recursive_timed_mutex"/>
5123 <link linkend="class_recursive_timed_mutex">Class
5124 <code>recursive_timed_mutex</code></link>
5125 </bridgehead>
5126 </para>
5127 <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>
5128
5129 <phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase>
5130 <phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase>
5131
5132 <phrase role="keyword">class</phrase> <phrase role="identifier">recursive_timed_mutex</phrase> <phrase role="special">{</phrase>
5133 <phrase role="keyword">public</phrase><phrase role="special">:</phrase>
5134 <phrase role="identifier">recursive_timed_mutex</phrase><phrase role="special">();</phrase>
5135 <phrase role="special">~</phrase><phrase role="identifier">recursive_timed_mutex</phrase><phrase role="special">();</phrase>
5136
5137 <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>
5138 <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>
5139
5140 <phrase role="keyword">void</phrase> <phrase role="identifier">lock</phrase><phrase role="special">();</phrase>
5141 <phrase role="keyword">bool</phrase> <phrase role="identifier">try_lock</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
5142 <phrase role="keyword">void</phrase> <phrase role="identifier">unlock</phrase><phrase role="special">();</phrase>
5143
5144 <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>
5145 <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>
5146 <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>
5147 <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>
5148 <phrase role="special">};</phrase>
5149
5150 <phrase role="special">}}</phrase>
5151 </programlisting>
5152 <para>
5153 <link linkend="class_recursive_timed_mutex"><code>recursive_timed_mutex</code></link> provides an exclusive-ownership
5154 recursive mutex. At most one fiber can own the lock on a given instance of
5155 <link linkend="class_recursive_timed_mutex"><code>recursive_timed_mutex</code></link> at any time. Multiple concurrent
5156 calls to <code><phrase role="identifier">lock</phrase><phrase role="special">()</phrase></code>,
5157 <code><phrase role="identifier">try_lock</phrase><phrase role="special">()</phrase></code>,
5158 <code><phrase role="identifier">try_lock_for</phrase><phrase role="special">()</phrase></code>,
5159 <code><phrase role="identifier">try_lock_until</phrase><phrase role="special">()</phrase></code>
5160 and <code><phrase role="identifier">unlock</phrase><phrase role="special">()</phrase></code>
5161 shall be permitted. A fiber that already has exclusive ownership of a given
5162 <link linkend="class_recursive_timed_mutex"><code>recursive_timed_mutex</code></link> instance can call <code><phrase
5163 role="identifier">lock</phrase><phrase role="special">()</phrase></code>,
5164 <code><phrase role="identifier">try_lock</phrase><phrase role="special">()</phrase></code>,
5165 <code><phrase role="identifier">try_lock_for</phrase><phrase role="special">()</phrase></code>
5166 or <code><phrase role="identifier">try_lock_until</phrase><phrase role="special">()</phrase></code>
5167 to acquire an additional level of ownership of the mutex. <code><phrase role="identifier">unlock</phrase><phrase
5168 role="special">()</phrase></code> must be called once for each level of ownership
5169 acquired by a single fiber before ownership can be acquired by another fiber.
5170 </para>
5171 <para>
5172 <bridgehead renderas="sect4" id="recursive_timed_mutex_lock_bridgehead">
5173 <phrase id="recursive_timed_mutex_lock"/>
5174 <link linkend="recursive_timed_mutex_lock">Member
5175 function <code>lock</code>()</link>
5176 </bridgehead>
5177 </para>
5178 <programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">lock</phrase><phrase role="special">();</phrase>
5179 </programlisting>
5180 <variablelist>
5181 <title></title>
5182 <varlistentry>
5183 <term>Effects:</term>
5184 <listitem>
5185 <para>
5186 The current fiber blocks until ownership can be obtained.
5187 </para>
5188 </listitem>
5189 </varlistentry>
5190 <varlistentry>
5191 <term>Throws:</term>
5192 <listitem>
5193 <para>
5194 Nothing
5195 </para>
5196 </listitem>
5197 </varlistentry>
5198 </variablelist>
5199 <para>
5200 <bridgehead renderas="sect4" id="recursive_timed_mutex_try_lock_bridgehead">
5201 <phrase id="recursive_timed_mutex_try_lock"/>
5202 <link linkend="recursive_timed_mutex_try_lock">Member
5203 function <code>try_lock</code>()</link>
5204 </bridgehead>
5205 </para>
5206 <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>
5207 </programlisting>
5208 <variablelist>
5209 <title></title>
5210 <varlistentry>
5211 <term>Effects:</term>
5212 <listitem>
5213 <para>
5214 Attempt to obtain ownership for the current fiber without blocking.
5215 </para>
5216 </listitem>
5217 </varlistentry>
5218 <varlistentry>
5219 <term>Returns:</term>
5220 <listitem>
5221 <para>
5222 <code><phrase role="keyword">true</phrase></code> if ownership was
5223 obtained for the current fiber, <code><phrase role="keyword">false</phrase></code>
5224 otherwise.
5225 </para>
5226 </listitem>
5227 </varlistentry>
5228 <varlistentry>
5229 <term>Throws:</term>
5230 <listitem>
5231 <para>
5232 Nothing.
5233 </para>
5234 </listitem>
5235 </varlistentry>
5236 </variablelist>
5237 <para>
5238 <bridgehead renderas="sect4" id="recursive_timed_mutex_unlock_bridgehead">
5239 <phrase id="recursive_timed_mutex_unlock"/>
5240 <link linkend="recursive_timed_mutex_unlock">Member
5241 function <code>unlock</code>()</link>
5242 </bridgehead>
5243 </para>
5244 <programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">unlock</phrase><phrase role="special">();</phrase>
5245 </programlisting>
5246 <variablelist>
5247 <title></title>
5248 <varlistentry>
5249 <term>Effects:</term>
5250 <listitem>
5251 <para>
5252 Releases a lock on <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>
5253 by the current fiber.
5254 </para>
5255 </listitem>
5256 </varlistentry>
5257 <varlistentry>
5258 <term>Throws:</term>
5259 <listitem>
5260 <para>
5261 <code><phrase role="identifier">lock_error</phrase></code>
5262 </para>
5263 </listitem>
5264 </varlistentry>
5265 <varlistentry>
5266 <term>Error Conditions:</term>
5267 <listitem>
5268 <para>
5269 <emphasis role="bold">operation_not_permitted</emphasis>: if <code><phrase
5270 role="identifier">boost</phrase><phrase role="special">::</phrase><phrase
5271 role="identifier">this_fiber</phrase><phrase role="special">::</phrase><phrase
5272 role="identifier">get_id</phrase><phrase role="special">()</phrase></code>
5273 does not own the mutex.
5274 </para>
5275 </listitem>
5276 </varlistentry>
5277 </variablelist>
5278 <para>
5279 <bridgehead renderas="sect4" id="recursive_timed_mutex_try_lock_until_bridgehead">
5280 <phrase id="recursive_timed_mutex_try_lock_until"/>
5281 <link linkend="recursive_timed_mutex_try_lock_until">Templated
5282 member function <code>try_lock_until</code>()</link>
5283 </bridgehead>
5284 </para>
5285 <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>
5286 <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>
5287 </programlisting>
5288 <variablelist>
5289 <title></title>
5290 <varlistentry>
5291 <term>Effects:</term>
5292 <listitem>
5293 <para>
5294 Attempt to obtain ownership for the current fiber. Blocks until ownership
5295 can be obtained, or the specified time is reached. If the specified
5296 time has already passed, behaves as <link linkend="recursive_timed_mutex_try_lock"><code>recursive_timed_mutex::try_lock()</code></link>.
5297 </para>
5298 </listitem>
5299 </varlistentry>
5300 <varlistentry>
5301 <term>Returns:</term>
5302 <listitem>
5303 <para>
5304 <code><phrase role="keyword">true</phrase></code> if ownership was
5305 obtained for the current fiber, <code><phrase role="keyword">false</phrase></code>
5306 otherwise.
5307 </para>
5308 </listitem>
5309 </varlistentry>
5310 <varlistentry>
5311 <term>Throws:</term>
5312 <listitem>
5313 <para>
5314 Timeout-related exceptions.
5315 </para>
5316 </listitem>
5317 </varlistentry>
5318 </variablelist>
5319 <para>
5320 <bridgehead renderas="sect4" id="recursive_timed_mutex_try_lock_for_bridgehead">
5321 <phrase id="recursive_timed_mutex_try_lock_for"/>
5322 <link linkend="recursive_timed_mutex_try_lock_for">Templated
5323 member function <code>try_lock_for</code>()</link>
5324 </bridgehead>
5325 </para>
5326 <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>
5327 <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>
5328 </programlisting>
5329 <variablelist>
5330 <title></title>
5331 <varlistentry>
5332 <term>Effects:</term>
5333 <listitem>
5334 <para>
5335 Attempt to obtain ownership for the current fiber. Blocks until ownership
5336 can be obtained, or the specified time is reached. If the specified
5337 time has already passed, behaves as <link linkend="recursive_timed_mutex_try_lock"><code>recursive_timed_mutex::try_lock()</code></link>.
5338 </para>
5339 </listitem>
5340 </varlistentry>
5341 <varlistentry>
5342 <term>Returns:</term>
5343 <listitem>
5344 <para>
5345 <code><phrase role="keyword">true</phrase></code> if ownership was
5346 obtained for the current fiber, <code><phrase role="keyword">false</phrase></code>
5347 otherwise.
5348 </para>
5349 </listitem>
5350 </varlistentry>
5351 <varlistentry>
5352 <term>Throws:</term>
5353 <listitem>
5354 <para>
5355 Timeout-related exceptions.
5356 </para>
5357 </listitem>
5358 </varlistentry>
5359 </variablelist>
5360 </section>
5361 <section id="fiber.synchronization.conditions">
5362 <title><link linkend="fiber.synchronization.conditions">Condition Variables</link></title>
5363 <bridgehead renderas="sect4" id="fiber.synchronization.conditions.h0">
5364 <phrase id="fiber.synchronization.conditions.synopsis"/><link linkend="fiber.synchronization.conditions.synopsis">Synopsis</link>
5365 </bridgehead>
5366 <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>
5367 <phrase role="identifier">no_timeout</phrase><phrase role="special">,</phrase>
5368 <phrase role="identifier">timeout</phrase>
5369 <phrase role="special">};</phrase>
5370
5371 <phrase role="keyword">class</phrase> <phrase role="identifier">condition_variable</phrase><phrase role="special">;</phrase>
5372 <phrase role="keyword">class</phrase> <phrase role="identifier">condition_variable_any</phrase><phrase role="special">;</phrase>
5373 </programlisting>
5374 <para>
5375 The class <link linkend="class_condition_variable"><code>condition_variable</code></link> provides a mechanism
5376 for a fiber to wait for notification from another fiber. When the fiber awakens
5377 from the wait, then it checks to see if the appropriate condition is now
5378 true, and continues if so. If the condition is not true, then the fiber calls
5379 <code><phrase role="identifier">wait</phrase></code> again to resume waiting.
5380 In the simplest case, this condition is just a boolean variable:
5381 </para>
5382 <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>
5383 <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>
5384 <phrase role="keyword">bool</phrase> <phrase role="identifier">data_ready</phrase> <phrase role="special">=</phrase> <phrase role="keyword">false</phrase><phrase role="special">;</phrase>
5385
5386 <phrase role="keyword">void</phrase> <phrase role="identifier">process_data</phrase><phrase role="special">();</phrase>
5387
5388 <phrase role="keyword">void</phrase> <phrase role="identifier">wait_for_data_to_process</phrase><phrase role="special">()</phrase> <phrase role="special">{</phrase>
5389 <phrase role="special">{</phrase>
5390 <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>
5391 <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>
5392 <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>
5393 <phrase role="special">}</phrase>
5394 <phrase role="special">}</phrase> <phrase role="comment">// release lk</phrase>
5395 <phrase role="identifier">process_data</phrase><phrase role="special">();</phrase>
5396 <phrase role="special">}</phrase>
5397 </programlisting>
5398 <para>
5399 Notice that the <code><phrase role="identifier">lk</phrase></code> is passed
5400 to <link linkend="condition_variable_wait"><code>condition_variable::wait()</code></link>: <code><phrase role="identifier">wait</phrase><phrase
5401 role="special">()</phrase></code> will atomically add the fiber to the set
5402 of fibers waiting on the condition variable, and unlock the <link linkend="class_mutex"><code>mutex</code></link>.
5403 When the fiber is awakened, the <code><phrase role="identifier">mutex</phrase></code>
5404 will be locked again before the call to <code><phrase role="identifier">wait</phrase><phrase
5405 role="special">()</phrase></code> returns. This allows other fibers to acquire
5406 the <code><phrase role="identifier">mutex</phrase></code> in order to update
5407 the shared data, and ensures that the data associated with the condition
5408 is correctly synchronized.
5409 </para>
5410 <para>
5411 <code><phrase role="identifier">wait_for_data_to_process</phrase><phrase
5412 role="special">()</phrase></code> could equivalently be written:
5413 </para>
5414 <programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">wait_for_data_to_process</phrase><phrase role="special">()</phrase> <phrase role="special">{</phrase>
5415 <phrase role="special">{</phrase>
5416 <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>
5417 <phrase role="comment">// make condition_variable::wait() perform the loop</phrase>
5418 <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>
5419 <phrase role="special">}</phrase> <phrase role="comment">// release lk</phrase>
5420 <phrase role="identifier">process_data</phrase><phrase role="special">();</phrase>
5421 <phrase role="special">}</phrase>
5422 </programlisting>
5423 <para>
5424 In the meantime, another fiber sets <code><phrase role="identifier">data_ready</phrase></code>
5425 to <code><phrase role="keyword">true</phrase></code>, and then calls either
5426 <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
5427 the <link linkend="class_condition_variable"><code>condition_variable</code></link> <code><phrase role="identifier">cond</phrase></code>
5428 to wake one waiting fiber or all the waiting fibers respectively.
5429 </para>
5430 <programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">retrieve_data</phrase><phrase role="special">();</phrase>
5431 <phrase role="keyword">void</phrase> <phrase role="identifier">prepare_data</phrase><phrase role="special">();</phrase>
5432
5433 <phrase role="keyword">void</phrase> <phrase role="identifier">prepare_data_for_processing</phrase><phrase role="special">()</phrase> <phrase role="special">{</phrase>
5434 <phrase role="identifier">retrieve_data</phrase><phrase role="special">();</phrase>
5435 <phrase role="identifier">prepare_data</phrase><phrase role="special">();</phrase>
5436 <phrase role="special">{</phrase>
5437 <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>
5438 <phrase role="identifier">data_ready</phrase> <phrase role="special">=</phrase> <phrase role="keyword">true</phrase><phrase role="special">;</phrase>
5439 <phrase role="special">}</phrase>
5440 <phrase role="identifier">cond</phrase><phrase role="special">.</phrase><phrase role="identifier">notify_one</phrase><phrase role="special">();</phrase>
5441 <phrase role="special">}</phrase>
5442 </programlisting>
5443 <para>
5444 Note that the same <link linkend="class_mutex"><code>mutex</code></link> is locked before the shared data is updated,
5445 but that the <code><phrase role="identifier">mutex</phrase></code> does not
5446 have to be locked across the call to <link linkend="condition_variable_notify_one"><code>condition_variable::notify_one()</code></link>.
5447 </para>
5448 <para>
5449 Locking is important because the synchronization objects provided by <emphasis
5450 role="bold">Boost.Fiber</emphasis> can be used to synchronize fibers running
5451 on different threads.
5452 </para>
5453 <para>
5454 <emphasis role="bold">Boost.Fiber</emphasis> provides both <link linkend="class_condition_variable"><code>condition_variable</code></link> and
5455 <link linkend="class_condition_variable_any"><code>condition_variable_any</code></link>. <code><phrase role="identifier">boost</phrase><phrase
5456 role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase
5457 role="special">::</phrase><phrase role="identifier">condition_variable</phrase></code>
5458 can only wait on <ulink url="http://en.cppreference.com/w/cpp/thread/unique_lock"><code><phrase
5459 role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">unique_lock</phrase></code></ulink><code><phrase
5460 role="special">&lt;</phrase> <phrase role="identifier">boost</phrase><phrase
5461 role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase
5462 role="special">::</phrase></code><link linkend="class_mutex"><code>mutex</code></link><code> <phrase role="special">&gt;</phrase></code>
5463 while <code><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase
5464 role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase
5465 role="identifier">condition_variable_any</phrase></code> can wait on user-defined
5466 lock types.
5467 </para>
5468 <anchor id="condition_variable_spurious_wakeups"/>
5469 <bridgehead renderas="sect4" id="fiber.synchronization.conditions.h1">
5470 <phrase id="fiber.synchronization.conditions.no_spurious_wakeups"/><link
5471 linkend="fiber.synchronization.conditions.no_spurious_wakeups">No Spurious
5472 Wakeups</link>
5473 </bridgehead>
5474 <para>
5475 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
5476 subject to spurious wakeup: <link linkend="condition_variable_wait"><code>condition_variable::wait()</code></link> can
5477 only wake up when <link linkend="condition_variable_notify_one"><code>condition_variable::notify_one()</code></link> or
5478 <link linkend="condition_variable_notify_all"><code>condition_variable::notify_all()</code></link> is called. Even
5479 so, it is prudent to use one of the <code><phrase role="identifier">wait</phrase><phrase
5480 role="special">(</phrase> <phrase role="identifier">lock</phrase><phrase
5481 role="special">,</phrase> <phrase role="identifier">predicate</phrase> <phrase
5482 role="special">)</phrase></code> overloads.
5483 </para>
5484 <para>
5485 Consider a set of consumer fibers processing items from a <ulink url="http://en.cppreference.com/w/cpp/container/queue"><code><phrase
5486 role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">queue</phrase></code></ulink>.
5487 The queue is continually populated by a set of producer fibers.
5488 </para>
5489 <para>
5490 The consumer fibers might reasonably wait on a <code><phrase role="identifier">condition_variable</phrase></code>
5491 as long as the queue remains <ulink url="http://en.cppreference.com/w/cpp/container/queue/empty"><code><phrase
5492 role="identifier">empty</phrase><phrase role="special">()</phrase></code></ulink>.
5493 </para>
5494 <para>
5495 Because producer fibers might <ulink url="http://en.cppreference.com/w/cpp/container/queue/push"><code><phrase
5496 role="identifier">push</phrase><phrase role="special">()</phrase></code></ulink>
5497 items to the queue in bursts, they call <link linkend="condition_variable_notify_all"><code>condition_variable::notify_all()</code></link> rather
5498 than <link linkend="condition_variable_notify_one"><code>condition_variable::notify_one()</code></link>.
5499 </para>
5500 <para>
5501 But a given consumer fiber might well wake up from <link linkend="condition_variable_wait"><code>condition_variable::wait()</code></link> and
5502 find the queue <code><phrase role="identifier">empty</phrase><phrase role="special">()</phrase></code>,
5503 because other consumer fibers might already have processed all pending items.
5504 </para>
5505 <para>
5506 (See also <link linkend="spurious_wakeup">spurious wakeup</link>.)
5507 </para>
5508 <anchor id="class_cv_status"/>
5509 <bridgehead renderas="sect4" id="fiber.synchronization.conditions.h2">
5510 <phrase id="fiber.synchronization.conditions.enumeration__code__phrase_role__identifier__cv_status__phrase___code_"/><link
5511 linkend="fiber.synchronization.conditions.enumeration__code__phrase_role__identifier__cv_status__phrase___code_">Enumeration
5512 <code><phrase role="identifier">cv_status</phrase></code></link>
5513 </bridgehead>
5514 <para>
5515 A timed wait operation might return because of timeout or not.
5516 </para>
5517 <programlisting><phrase role="keyword">enum</phrase> <phrase role="keyword">class</phrase> <phrase role="identifier">cv_status</phrase> <phrase role="special">{</phrase>
5518 <phrase role="identifier">no_timeout</phrase><phrase role="special">,</phrase>
5519 <phrase role="identifier">timeout</phrase>
5520 <phrase role="special">};</phrase>
5521 </programlisting>
5522 <bridgehead renderas="sect4" id="fiber.synchronization.conditions.h3">
5523 <phrase id="fiber.synchronization.conditions._code__phrase_role__identifier__no_timeout__phrase___code_"/><link
5524 linkend="fiber.synchronization.conditions._code__phrase_role__identifier__no_timeout__phrase___code_"><code><phrase
5525 role="identifier">no_timeout</phrase></code></link>
5526 </bridgehead>
5527 <variablelist>
5528 <title></title>
5529 <varlistentry>
5530 <term>Effects:</term>
5531 <listitem>
5532 <para>
5533 The condition variable was awakened with <code><phrase role="identifier">notify_one</phrase></code>
5534 or <code><phrase role="identifier">notify_all</phrase></code>.
5535 </para>
5536 </listitem>
5537 </varlistentry>
5538 </variablelist>
5539 <bridgehead renderas="sect4" id="fiber.synchronization.conditions.h4">
5540 <phrase id="fiber.synchronization.conditions._code__phrase_role__identifier__timeout__phrase___code_"/><link
5541 linkend="fiber.synchronization.conditions._code__phrase_role__identifier__timeout__phrase___code_"><code><phrase
5542 role="identifier">timeout</phrase></code></link>
5543 </bridgehead>
5544 <variablelist>
5545 <title></title>
5546 <varlistentry>
5547 <term>Effects:</term>
5548 <listitem>
5549 <para>
5550 The condition variable was awakened by timeout.
5551 </para>
5552 </listitem>
5553 </varlistentry>
5554 </variablelist>
5555 <para>
5556 <bridgehead renderas="sect4" id="class_condition_variable_any_bridgehead">
5557 <phrase id="class_condition_variable_any"/>
5558 <link linkend="class_condition_variable_any">Class
5559 <code>condition_variable_any</code></link>
5560 </bridgehead>
5561 </para>
5562 <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>
5563
5564 <phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase>
5565 <phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase>
5566
5567 <phrase role="keyword">class</phrase> condition_variable_any <phrase role="special">{</phrase>
5568 <phrase role="keyword">public</phrase><phrase role="special">:</phrase>
5569 condition_variable_any<phrase role="special">();</phrase>
5570 <phrase role="special">~</phrase>condition_variable_any<phrase role="special">();</phrase>
5571
5572 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>
5573 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>
5574
5575 <phrase role="keyword">void</phrase> <phrase role="identifier">notify_one</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
5576 <phrase role="keyword">void</phrase> <phrase role="identifier">notify_all</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
5577
5578 template&lt; typename LockType &gt;
5579 void <phrase role="identifier">wait</phrase><phrase role="special">(</phrase> LockType <phrase role="special">&amp;);</phrase>
5580
5581 <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> typename LockType, typename <phrase role="identifier">Pred</phrase> <phrase role="special">&gt;</phrase>
5582 <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>
5583
5584 <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>
5585 <phrase role="identifier">cv_status</phrase> <phrase role="identifier">wait_until</phrase><phrase role="special">(</phrase> LockType <phrase role="special">&amp;,</phrase>
5586 <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>
5587
5588 <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>
5589 <phrase role="keyword">bool</phrase> <phrase role="identifier">wait_until</phrase><phrase role="special">(</phrase> LockType <phrase role="special">&amp;,</phrase>
5590 <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>
5591 <phrase role="identifier">Pred</phrase><phrase role="special">);</phrase>
5592
5593 <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>
5594 <phrase role="identifier">cv_status</phrase> <phrase role="identifier">wait_for</phrase><phrase role="special">(</phrase> LockType <phrase role="special">&amp;,</phrase>
5595 <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>
5596
5597 <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>
5598 <phrase role="keyword">bool</phrase> <phrase role="identifier">wait_for</phrase><phrase role="special">(</phrase> LockType <phrase role="special">&amp;,</phrase>
5599 <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>
5600 <phrase role="identifier">Pred</phrase><phrase role="special">);</phrase>
5601 <phrase role="special">};</phrase>
5602
5603 <phrase role="special">}}</phrase>
5604 </programlisting>
5605 <bridgehead renderas="sect4" id="fiber.synchronization.conditions.h5">
5606 <phrase id="fiber.synchronization.conditions.constructor"/><link linkend="fiber.synchronization.conditions.constructor">Constructor</link>
5607 </bridgehead>
5608 <programlisting>condition_variable_any<phrase role="special">()</phrase>
5609 </programlisting>
5610 <variablelist>
5611 <title></title>
5612 <varlistentry>
5613 <term>Effects:</term>
5614 <listitem>
5615 <para>
5616 Creates the object.
5617 </para>
5618 </listitem>
5619 </varlistentry>
5620 <varlistentry>
5621 <term>Throws:</term>
5622 <listitem>
5623 <para>
5624 Nothing.
5625 </para>
5626 </listitem>
5627 </varlistentry>
5628 </variablelist>
5629 <bridgehead renderas="sect4" id="fiber.synchronization.conditions.h6">
5630 <phrase id="fiber.synchronization.conditions.destructor"/><link linkend="fiber.synchronization.conditions.destructor">Destructor</link>
5631 </bridgehead>
5632 <programlisting><phrase role="special">~</phrase>condition_variable_any<phrase role="special">()</phrase>
5633 </programlisting>
5634 <variablelist>
5635 <title></title>
5636 <varlistentry>
5637 <term>Precondition:</term>
5638 <listitem>
5639 <para>
5640 All fibers waiting on <code><phrase role="special">*</phrase><phrase
5641 role="keyword">this</phrase></code> have been notified by a call to
5642 <code><phrase role="identifier">notify_one</phrase></code> or <code><phrase
5643 role="identifier">notify_all</phrase></code> (though the respective
5644 calls to <code><phrase role="identifier">wait</phrase></code>, <code><phrase
5645 role="identifier">wait_for</phrase></code> or <code><phrase role="identifier">wait_until</phrase></code>
5646 need not have returned).
5647 </para>
5648 </listitem>
5649 </varlistentry>
5650 <varlistentry>
5651 <term>Effects:</term>
5652 <listitem>
5653 <para>
5654 Destroys the object.
5655 </para>
5656 </listitem>
5657 </varlistentry>
5658 </variablelist>
5659 <para>
5660 <bridgehead renderas="sect4" id="condition_variable_any_notify_one_bridgehead">
5661 <phrase id="condition_variable_any_notify_one"/>
5662 <link linkend="condition_variable_any_notify_one">Member
5663 function <code>notify_one</code>()</link>
5664 </bridgehead>
5665 </para>
5666 <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>
5667 </programlisting>
5668 <variablelist>
5669 <title></title>
5670 <varlistentry>
5671 <term>Effects:</term>
5672 <listitem>
5673 <para>
5674 If any fibers are currently <link linkend="blocking"><emphasis>blocked</emphasis></link>
5675 waiting on <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>
5676 in a call to <code><phrase role="identifier">wait</phrase></code>,
5677 <code><phrase role="identifier">wait_for</phrase></code> or <code><phrase
5678 role="identifier">wait_until</phrase></code>, unblocks one of those
5679 fibers.
5680 </para>
5681 </listitem>
5682 </varlistentry>
5683 <varlistentry>
5684 <term>Throws:</term>
5685 <listitem>
5686 <para>
5687 Nothing.
5688 </para>
5689 </listitem>
5690 </varlistentry>
5691 <varlistentry>
5692 <term>Note:</term>
5693 <listitem>
5694 <para>
5695 It is arbitrary which waiting fiber is resumed.
5696 </para>
5697 </listitem>
5698 </varlistentry>
5699 </variablelist>
5700 <para>
5701 <bridgehead renderas="sect4" id="condition_variable_any_notify_all_bridgehead">
5702 <phrase id="condition_variable_any_notify_all"/>
5703 <link linkend="condition_variable_any_notify_all">Member
5704 function <code>notify_all</code>()</link>
5705 </bridgehead>
5706 </para>
5707 <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>
5708 </programlisting>
5709 <variablelist>
5710 <title></title>
5711 <varlistentry>
5712 <term>Effects:</term>
5713 <listitem>
5714 <para>
5715 If any fibers are currently <link linkend="blocking"><emphasis>blocked</emphasis></link>
5716 waiting on <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>
5717 in a call to <code><phrase role="identifier">wait</phrase></code>,
5718 <code><phrase role="identifier">wait_for</phrase></code> or <code><phrase
5719 role="identifier">wait_until</phrase></code>, unblocks all of those
5720 fibers.
5721 </para>
5722 </listitem>
5723 </varlistentry>
5724 <varlistentry>
5725 <term>Throws:</term>
5726 <listitem>
5727 <para>
5728 Nothing.
5729 </para>
5730 </listitem>
5731 </varlistentry>
5732 <varlistentry>
5733 <term>Note:</term>
5734 <listitem>
5735 <para>
5736 This is why a waiting fiber must <emphasis>also</emphasis> check for
5737 the desired program state using a mechanism external to the <code>condition_variable_any</code>,
5738 and retry the wait until that state is reached. A fiber waiting on
5739 a <code>condition_variable_any</code> might well wake up a number of times before
5740 the desired state is reached.
5741 </para>
5742 </listitem>
5743 </varlistentry>
5744 </variablelist>
5745 <para>
5746 <bridgehead renderas="sect4" id="condition_variable_any_wait_bridgehead">
5747 <phrase id="condition_variable_any_wait"/>
5748 <link linkend="condition_variable_any_wait">Templated
5749 member function <code>wait</code>()</link>
5750 </bridgehead>
5751 </para>
5752 <programlisting>template&lt; typename LockType &gt;
5753 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>
5754
5755 <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> typename LockType, typename <phrase role="identifier">Pred</phrase> <phrase role="special">&gt;</phrase>
5756 <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>
5757 </programlisting>
5758 <variablelist>
5759 <title></title>
5760 <varlistentry>
5761 <term>Precondition:</term>
5762 <listitem>
5763 <para>
5764 <code><phrase role="identifier">lk</phrase></code> is locked by the
5765 current fiber, and either no other fiber is currently waiting on <code><phrase
5766 role="special">*</phrase><phrase role="keyword">this</phrase></code>,
5767 or the execution of the <ulink url="http://en.cppreference.com/w/cpp/thread/unique_lock/mutex"><code><phrase
5768 role="identifier">mutex</phrase><phrase role="special">()</phrase></code></ulink>
5769 member function on the <code><phrase role="identifier">lk</phrase></code>
5770 objects supplied in the calls to <code><phrase role="identifier">wait</phrase></code>
5771 in all the fibers currently waiting on <code><phrase role="special">*</phrase><phrase
5772 role="keyword">this</phrase></code> would return the same value as
5773 <code><phrase role="identifier">lk</phrase><phrase role="special">-&gt;</phrase><phrase
5774 role="identifier">mutex</phrase><phrase role="special">()</phrase></code>
5775 for this call to <code><phrase role="identifier">wait</phrase></code>.
5776 </para>
5777 </listitem>
5778 </varlistentry>
5779 <varlistentry>
5780 <term>Effects:</term>
5781 <listitem>
5782 <para>
5783 Atomically call <code><phrase role="identifier">lk</phrase><phrase
5784 role="special">.</phrase><phrase role="identifier">unlock</phrase><phrase
5785 role="special">()</phrase></code> and blocks the current fiber. The
5786 fiber will unblock when notified by a call to <code><phrase role="keyword">this</phrase><phrase
5787 role="special">-&gt;</phrase><phrase role="identifier">notify_one</phrase><phrase
5788 role="special">()</phrase></code> or <code><phrase role="keyword">this</phrase><phrase
5789 role="special">-&gt;</phrase><phrase role="identifier">notify_all</phrase><phrase
5790 role="special">()</phrase></code>. When the fiber is unblocked (for
5791 whatever reason), the lock is reacquired by invoking <code><phrase
5792 role="identifier">lk</phrase><phrase role="special">.</phrase><phrase
5793 role="identifier">lock</phrase><phrase role="special">()</phrase></code>
5794 before the call to <code><phrase role="identifier">wait</phrase></code>
5795 returns. The lock is also reacquired by invoking <code><phrase role="identifier">lk</phrase><phrase
5796 role="special">.</phrase><phrase role="identifier">lock</phrase><phrase
5797 role="special">()</phrase></code> if the function exits with an exception.
5798 The member function accepting <code><phrase role="identifier">pred</phrase></code>
5799 is shorthand for:
5800 <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>
5801 <phrase role="identifier">wait</phrase><phrase role="special">(</phrase> <phrase role="identifier">lk</phrase><phrase role="special">);</phrase>
5802 <phrase role="special">}</phrase>
5803 </programlisting>
5804 </para>
5805 </listitem>
5806 </varlistentry>
5807 <varlistentry>
5808 <term>Postcondition:</term>
5809 <listitem>
5810 <para>
5811 <code><phrase role="identifier">lk</phrase></code> is locked by the
5812 current fiber.
5813 </para>
5814 </listitem>
5815 </varlistentry>
5816 <varlistentry>
5817 <term>Throws:</term>
5818 <listitem>
5819 <para>
5820 <code><phrase role="identifier">fiber_error</phrase></code> if an error
5821 occurs.
5822 </para>
5823 </listitem>
5824 </varlistentry>
5825 <varlistentry>
5826 <term>Note:</term>
5827 <listitem>
5828 <para>
5829 The Precondition is a bit dense. It merely states that all the fibers
5830 concurrently calling <code><phrase role="identifier">wait</phrase></code>
5831 on <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>
5832 must wait on <code><phrase role="identifier">lk</phrase></code> objects
5833 governing the <emphasis>same</emphasis> <link linkend="class_mutex"><code>mutex</code></link>. Three distinct
5834 objects are involved in any <code>condition_variable_any::wait()</code> call: the
5835 <code>condition_variable_any</code> itself, the <code><phrase role="identifier">mutex</phrase></code>
5836 coordinating access between fibers and a local lock object (e.g. <ulink
5837 url="http://en.cppreference.com/w/cpp/thread/unique_lock"><code><phrase
5838 role="identifier">std</phrase><phrase role="special">::</phrase><phrase
5839 role="identifier">unique_lock</phrase></code></ulink>). In general,
5840 you can partition the lifespan of a given <code>condition_variable_any</code> instance
5841 into periods with one or more fibers waiting on it, separated by periods
5842 when no fibers are waiting on it. When more than one fiber is waiting
5843 on that <code>condition_variable_any</code>, all must pass lock objects referencing
5844 the <emphasis>same</emphasis> <code><phrase role="identifier">mutex</phrase></code>
5845 instance.
5846 </para>
5847 </listitem>
5848 </varlistentry>
5849 </variablelist>
5850 <para>
5851 <bridgehead renderas="sect4" id="condition_variable_any_wait_until_bridgehead">
5852 <phrase id="condition_variable_any_wait_until"/>
5853 <link linkend="condition_variable_any_wait_until">Templated
5854 member function <code>wait_until</code>()</link>
5855 </bridgehead>
5856 </para>
5857 <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>
5858 <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>
5859 <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>
5860
5861 <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>
5862 <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>
5863 <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>
5864 <phrase role="identifier">Pred</phrase> <phrase role="identifier">pred</phrase><phrase role="special">);</phrase>
5865 </programlisting>
5866 <variablelist>
5867 <title></title>
5868 <varlistentry>
5869 <term>Precondition:</term>
5870 <listitem>
5871 <para>
5872 <code><phrase role="identifier">lk</phrase></code> is locked by the
5873 current fiber, and either no other fiber is currently waiting on <code><phrase
5874 role="special">*</phrase><phrase role="keyword">this</phrase></code>,
5875 or the execution of the <code><phrase role="identifier">mutex</phrase><phrase
5876 role="special">()</phrase></code> member function on the <code><phrase
5877 role="identifier">lk</phrase></code> objects supplied in the calls
5878 to <code><phrase role="identifier">wait</phrase></code>, <code><phrase
5879 role="identifier">wait_for</phrase></code> or <code><phrase role="identifier">wait_until</phrase></code>
5880 in all the fibers currently waiting on <code><phrase role="special">*</phrase><phrase
5881 role="keyword">this</phrase></code> would return the same value as
5882 <code><phrase role="identifier">lk</phrase><phrase role="special">.</phrase><phrase
5883 role="identifier">mutex</phrase><phrase role="special">()</phrase></code>
5884 for this call to <code><phrase role="identifier">wait_until</phrase></code>.
5885 </para>
5886 </listitem>
5887 </varlistentry>
5888 <varlistentry>
5889 <term>Effects:</term>
5890 <listitem>
5891 <para>
5892 Atomically call <code><phrase role="identifier">lk</phrase><phrase
5893 role="special">.</phrase><phrase role="identifier">unlock</phrase><phrase
5894 role="special">()</phrase></code> and blocks the current fiber. The
5895 fiber will unblock when notified by a call to <code><phrase role="keyword">this</phrase><phrase
5896 role="special">-&gt;</phrase><phrase role="identifier">notify_one</phrase><phrase
5897 role="special">()</phrase></code> or <code><phrase role="keyword">this</phrase><phrase
5898 role="special">-&gt;</phrase><phrase role="identifier">notify_all</phrase><phrase
5899 role="special">()</phrase></code>, when the system time would be equal
5900 to or later than the specified <code><phrase role="identifier">abs_time</phrase></code>.
5901 When the fiber is unblocked (for whatever reason), the lock is reacquired
5902 by invoking <code><phrase role="identifier">lk</phrase><phrase role="special">.</phrase><phrase
5903 role="identifier">lock</phrase><phrase role="special">()</phrase></code>
5904 before the call to <code><phrase role="identifier">wait_until</phrase></code>
5905 returns. The lock is also reacquired by invoking <code><phrase role="identifier">lk</phrase><phrase
5906 role="special">.</phrase><phrase role="identifier">lock</phrase><phrase
5907 role="special">()</phrase></code> if the function exits with an exception.
5908 The member function accepting <code><phrase role="identifier">pred</phrase></code>
5909 is shorthand for:
5910 <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>
5911 <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>
5912 <phrase role="keyword">return</phrase> <phrase role="identifier">pred</phrase><phrase role="special">();</phrase>
5913 <phrase role="special">}</phrase>
5914 <phrase role="keyword">return</phrase> <phrase role="keyword">true</phrase><phrase role="special">;</phrase>
5915 </programlisting>
5916 That is, even if <code><phrase role="identifier">wait_until</phrase><phrase
5917 role="special">()</phrase></code> times out, it can still return <code><phrase
5918 role="keyword">true</phrase></code> if <code><phrase role="identifier">pred</phrase><phrase
5919 role="special">()</phrase></code> returns <code><phrase role="keyword">true</phrase></code>
5920 at that time.
5921 </para>
5922 </listitem>
5923 </varlistentry>
5924 <varlistentry>
5925 <term>Postcondition:</term>
5926 <listitem>
5927 <para>
5928 <code><phrase role="identifier">lk</phrase></code> is locked by the
5929 current fiber.
5930 </para>
5931 </listitem>
5932 </varlistentry>
5933 <varlistentry>
5934 <term>Throws:</term>
5935 <listitem>
5936 <para>
5937 <code><phrase role="identifier">fiber_error</phrase></code> if an error
5938 occurs or timeout-related exceptions.
5939 </para>
5940 </listitem>
5941 </varlistentry>
5942 <varlistentry>
5943 <term>Returns:</term>
5944 <listitem>
5945 <para>
5946 The overload without <code><phrase role="identifier">pred</phrase></code>
5947 returns <code><phrase role="identifier">cv_status</phrase><phrase role="special">::</phrase><phrase
5948 role="identifier">no_timeout</phrase></code> if awakened by <code><phrase
5949 role="identifier">notify_one</phrase><phrase role="special">()</phrase></code>
5950 or <code><phrase role="identifier">notify_all</phrase><phrase role="special">()</phrase></code>,
5951 or <code><phrase role="identifier">cv_status</phrase><phrase role="special">::</phrase><phrase
5952 role="identifier">timeout</phrase></code> if awakened because the system
5953 time is past <code><phrase role="identifier">abs_time</phrase></code>.
5954 </para>
5955 </listitem>
5956 </varlistentry>
5957 <varlistentry>
5958 <term>Returns:</term>
5959 <listitem>
5960 <para>
5961 The overload accepting <code><phrase role="identifier">pred</phrase></code>
5962 returns <code><phrase role="keyword">false</phrase></code> if the call
5963 is returning because the time specified by <code><phrase role="identifier">abs_time</phrase></code>
5964 was reached and the predicate returns <code><phrase role="keyword">false</phrase></code>,
5965 <code><phrase role="keyword">true</phrase></code> otherwise.
5966 </para>
5967 </listitem>
5968 </varlistentry>
5969 <varlistentry>
5970 <term>Note:</term>
5971 <listitem>
5972 <para>
5973 See <emphasis role="bold">Note</emphasis> for <link linkend="condition_variable_any_wait"><code>condition_variable_any::wait()</code></link>.
5974 </para>
5975 </listitem>
5976 </varlistentry>
5977 </variablelist>
5978 <para>
5979 <bridgehead renderas="sect4" id="condition_variable_any_wait_for_bridgehead">
5980 <phrase id="condition_variable_any_wait_for"/>
5981 <link linkend="condition_variable_any_wait_for">Templated
5982 member function <code>wait_for</code>()</link>
5983 </bridgehead>
5984 </para>
5985 <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>
5986 <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>
5987 <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>
5988
5989 <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>
5990 <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>
5991 <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>
5992 <phrase role="identifier">Pred</phrase> <phrase role="identifier">pred</phrase><phrase role="special">);</phrase>
5993 </programlisting>
5994 <variablelist>
5995 <title></title>
5996 <varlistentry>
5997 <term>Precondition:</term>
5998 <listitem>
5999 <para>
6000 <code><phrase role="identifier">lk</phrase></code> is locked by the
6001 current fiber, and either no other fiber is currently waiting on <code><phrase
6002 role="special">*</phrase><phrase role="keyword">this</phrase></code>,
6003 or the execution of the <code><phrase role="identifier">mutex</phrase><phrase
6004 role="special">()</phrase></code> member function on the <code><phrase
6005 role="identifier">lk</phrase></code> objects supplied in the calls
6006 to <code><phrase role="identifier">wait</phrase></code>, <code><phrase
6007 role="identifier">wait_for</phrase></code> or <code><phrase role="identifier">wait_until</phrase></code>
6008 in all the fibers currently waiting on <code><phrase role="special">*</phrase><phrase
6009 role="keyword">this</phrase></code> would return the same value as
6010 <code><phrase role="identifier">lk</phrase><phrase role="special">.</phrase><phrase
6011 role="identifier">mutex</phrase><phrase role="special">()</phrase></code>
6012 for this call to <code><phrase role="identifier">wait_for</phrase></code>.
6013 </para>
6014 </listitem>
6015 </varlistentry>
6016 <varlistentry>
6017 <term>Effects:</term>
6018 <listitem>
6019 <para>
6020 Atomically call <code><phrase role="identifier">lk</phrase><phrase
6021 role="special">.</phrase><phrase role="identifier">unlock</phrase><phrase
6022 role="special">()</phrase></code> and blocks the current fiber. The
6023 fiber will unblock when notified by a call to <code><phrase role="keyword">this</phrase><phrase
6024 role="special">-&gt;</phrase><phrase role="identifier">notify_one</phrase><phrase
6025 role="special">()</phrase></code> or <code><phrase role="keyword">this</phrase><phrase
6026 role="special">-&gt;</phrase><phrase role="identifier">notify_all</phrase><phrase
6027 role="special">()</phrase></code>, when a time interval equal to or
6028 greater than the specified <code><phrase role="identifier">rel_time</phrase></code>
6029 has elapsed. When the fiber is unblocked (for whatever reason), the
6030 lock is reacquired by invoking <code><phrase role="identifier">lk</phrase><phrase
6031 role="special">.</phrase><phrase role="identifier">lock</phrase><phrase
6032 role="special">()</phrase></code> before the call to <code><phrase
6033 role="identifier">wait</phrase></code> returns. The lock is also reacquired
6034 by invoking <code><phrase role="identifier">lk</phrase><phrase role="special">.</phrase><phrase
6035 role="identifier">lock</phrase><phrase role="special">()</phrase></code>
6036 if the function exits with an exception. The <code><phrase role="identifier">wait_for</phrase><phrase
6037 role="special">()</phrase></code> member function accepting <code><phrase
6038 role="identifier">pred</phrase></code> is shorthand for:
6039 <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>
6040 <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>
6041 <phrase role="keyword">return</phrase> <phrase role="identifier">pred</phrase><phrase role="special">();</phrase>
6042 <phrase role="special">}</phrase>
6043 <phrase role="special">}</phrase>
6044 <phrase role="keyword">return</phrase> <phrase role="keyword">true</phrase><phrase role="special">;</phrase>
6045 </programlisting>
6046 (except of course that <code><phrase role="identifier">rel_time</phrase></code>
6047 is adjusted for each iteration). The point is that, even if <code><phrase
6048 role="identifier">wait_for</phrase><phrase role="special">()</phrase></code>
6049 times out, it can still return <code><phrase role="keyword">true</phrase></code>
6050 if <code><phrase role="identifier">pred</phrase><phrase role="special">()</phrase></code>
6051 returns <code><phrase role="keyword">true</phrase></code> at that time.
6052 </para>
6053 </listitem>
6054 </varlistentry>
6055 <varlistentry>
6056 <term>Postcondition:</term>
6057 <listitem>
6058 <para>
6059 <code><phrase role="identifier">lk</phrase></code> is locked by the
6060 current fiber.
6061 </para>
6062 </listitem>
6063 </varlistentry>
6064 <varlistentry>
6065 <term>Throws:</term>
6066 <listitem>
6067 <para>
6068 <code><phrase role="identifier">fiber_error</phrase></code> if an error
6069 occurs or timeout-related exceptions.
6070 </para>
6071 </listitem>
6072 </varlistentry>
6073 <varlistentry>
6074 <term>Returns:</term>
6075 <listitem>
6076 <para>
6077 The overload without <code><phrase role="identifier">pred</phrase></code>
6078 returns <code><phrase role="identifier">cv_status</phrase><phrase role="special">::</phrase><phrase
6079 role="identifier">no_timeout</phrase></code> if awakened by <code><phrase
6080 role="identifier">notify_one</phrase><phrase role="special">()</phrase></code>
6081 or <code><phrase role="identifier">notify_all</phrase><phrase role="special">()</phrase></code>,
6082 or <code><phrase role="identifier">cv_status</phrase><phrase role="special">::</phrase><phrase
6083 role="identifier">timeout</phrase></code> if awakened because at least
6084 <code><phrase role="identifier">rel_time</phrase></code> has elapsed.
6085 </para>
6086 </listitem>
6087 </varlistentry>
6088 <varlistentry>
6089 <term>Returns:</term>
6090 <listitem>
6091 <para>
6092 The overload accepting <code><phrase role="identifier">pred</phrase></code>
6093 returns <code><phrase role="keyword">false</phrase></code> if the call
6094 is returning because at least <code><phrase role="identifier">rel_time</phrase></code>
6095 has elapsed and the predicate returns <code><phrase role="keyword">false</phrase></code>,
6096 <code><phrase role="keyword">true</phrase></code> otherwise.
6097 </para>
6098 </listitem>
6099 </varlistentry>
6100 <varlistentry>
6101 <term>Note:</term>
6102 <listitem>
6103 <para>
6104 See <emphasis role="bold">Note</emphasis> for <link linkend="condition_variable_any_wait"><code>condition_variable_any::wait()</code></link>.
6105 </para>
6106 </listitem>
6107 </varlistentry>
6108 </variablelist>
6109 <para>
6110 <bridgehead renderas="sect4" id="class_condition_variable_bridgehead">
6111 <phrase id="class_condition_variable"/>
6112 <link linkend="class_condition_variable">Class
6113 <code>condition_variable</code></link>
6114 </bridgehead>
6115 </para>
6116 <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>
6117
6118 <phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase>
6119 <phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase>
6120
6121 <phrase role="keyword">class</phrase> condition_variable <phrase role="special">{</phrase>
6122 <phrase role="keyword">public</phrase><phrase role="special">:</phrase>
6123 condition_variable<phrase role="special">();</phrase>
6124 <phrase role="special">~</phrase>condition_variable<phrase role="special">();</phrase>
6125
6126 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>
6127 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>
6128
6129 <phrase role="keyword">void</phrase> <phrase role="identifier">notify_one</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
6130 <phrase role="keyword">void</phrase> <phrase role="identifier">notify_all</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
6131
6132 void <phrase role="identifier">wait</phrase><phrase role="special">(</phrase> std::unique_lock&lt; mutex &gt; <phrase role="special">&amp;);</phrase>
6133
6134 <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> typename <phrase role="identifier">Pred</phrase> <phrase role="special">&gt;</phrase>
6135 <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>
6136
6137 <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>
6138 <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>
6139 <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>
6140
6141 <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>
6142 <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>
6143 <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>
6144 <phrase role="identifier">Pred</phrase><phrase role="special">);</phrase>
6145
6146 <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>
6147 <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>
6148 <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>
6149
6150 <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>
6151 <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>
6152 <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>
6153 <phrase role="identifier">Pred</phrase><phrase role="special">);</phrase>
6154 <phrase role="special">};</phrase>
6155
6156 <phrase role="special">}}</phrase>
6157 </programlisting>
6158 <bridgehead renderas="sect4" id="fiber.synchronization.conditions.h7">
6159 <phrase id="fiber.synchronization.conditions.constructor0"/><link linkend="fiber.synchronization.conditions.constructor0">Constructor</link>
6160 </bridgehead>
6161 <programlisting>condition_variable<phrase role="special">()</phrase>
6162 </programlisting>
6163 <variablelist>
6164 <title></title>
6165 <varlistentry>
6166 <term>Effects:</term>
6167 <listitem>
6168 <para>
6169 Creates the object.
6170 </para>
6171 </listitem>
6172 </varlistentry>
6173 <varlistentry>
6174 <term>Throws:</term>
6175 <listitem>
6176 <para>
6177 Nothing.
6178 </para>
6179 </listitem>
6180 </varlistentry>
6181 </variablelist>
6182 <bridgehead renderas="sect4" id="fiber.synchronization.conditions.h8">
6183 <phrase id="fiber.synchronization.conditions.destructor0"/><link linkend="fiber.synchronization.conditions.destructor0">Destructor</link>
6184 </bridgehead>
6185 <programlisting><phrase role="special">~</phrase>condition_variable<phrase role="special">()</phrase>
6186 </programlisting>
6187 <variablelist>
6188 <title></title>
6189 <varlistentry>
6190 <term>Precondition:</term>
6191 <listitem>
6192 <para>
6193 All fibers waiting on <code><phrase role="special">*</phrase><phrase
6194 role="keyword">this</phrase></code> have been notified by a call to
6195 <code><phrase role="identifier">notify_one</phrase></code> or <code><phrase
6196 role="identifier">notify_all</phrase></code> (though the respective
6197 calls to <code><phrase role="identifier">wait</phrase></code>, <code><phrase
6198 role="identifier">wait_for</phrase></code> or <code><phrase role="identifier">wait_until</phrase></code>
6199 need not have returned).
6200 </para>
6201 </listitem>
6202 </varlistentry>
6203 <varlistentry>
6204 <term>Effects:</term>
6205 <listitem>
6206 <para>
6207 Destroys the object.
6208 </para>
6209 </listitem>
6210 </varlistentry>
6211 </variablelist>
6212 <para>
6213 <bridgehead renderas="sect4" id="condition_variable_notify_one_bridgehead">
6214 <phrase id="condition_variable_notify_one"/>
6215 <link linkend="condition_variable_notify_one">Member
6216 function <code>notify_one</code>()</link>
6217 </bridgehead>
6218 </para>
6219 <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>
6220 </programlisting>
6221 <variablelist>
6222 <title></title>
6223 <varlistentry>
6224 <term>Effects:</term>
6225 <listitem>
6226 <para>
6227 If any fibers are currently <link linkend="blocking"><emphasis>blocked</emphasis></link>
6228 waiting on <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>
6229 in a call to <code><phrase role="identifier">wait</phrase></code>,
6230 <code><phrase role="identifier">wait_for</phrase></code> or <code><phrase
6231 role="identifier">wait_until</phrase></code>, unblocks one of those
6232 fibers.
6233 </para>
6234 </listitem>
6235 </varlistentry>
6236 <varlistentry>
6237 <term>Throws:</term>
6238 <listitem>
6239 <para>
6240 Nothing.
6241 </para>
6242 </listitem>
6243 </varlistentry>
6244 <varlistentry>
6245 <term>Note:</term>
6246 <listitem>
6247 <para>
6248 It is arbitrary which waiting fiber is resumed.
6249 </para>
6250 </listitem>
6251 </varlistentry>
6252 </variablelist>
6253 <para>
6254 <bridgehead renderas="sect4" id="condition_variable_notify_all_bridgehead">
6255 <phrase id="condition_variable_notify_all"/>
6256 <link linkend="condition_variable_notify_all">Member
6257 function <code>notify_all</code>()</link>
6258 </bridgehead>
6259 </para>
6260 <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>
6261 </programlisting>
6262 <variablelist>
6263 <title></title>
6264 <varlistentry>
6265 <term>Effects:</term>
6266 <listitem>
6267 <para>
6268 If any fibers are currently <link linkend="blocking"><emphasis>blocked</emphasis></link>
6269 waiting on <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>
6270 in a call to <code><phrase role="identifier">wait</phrase></code>,
6271 <code><phrase role="identifier">wait_for</phrase></code> or <code><phrase
6272 role="identifier">wait_until</phrase></code>, unblocks all of those
6273 fibers.
6274 </para>
6275 </listitem>
6276 </varlistentry>
6277 <varlistentry>
6278 <term>Throws:</term>
6279 <listitem>
6280 <para>
6281 Nothing.
6282 </para>
6283 </listitem>
6284 </varlistentry>
6285 <varlistentry>
6286 <term>Note:</term>
6287 <listitem>
6288 <para>
6289 This is why a waiting fiber must <emphasis>also</emphasis> check for
6290 the desired program state using a mechanism external to the <code>condition_variable</code>,
6291 and retry the wait until that state is reached. A fiber waiting on
6292 a <code>condition_variable</code> might well wake up a number of times before the
6293 desired state is reached.
6294 </para>
6295 </listitem>
6296 </varlistentry>
6297 </variablelist>
6298 <para>
6299 <bridgehead renderas="sect4" id="condition_variable_wait_bridgehead">
6300 <phrase id="condition_variable_wait"/>
6301 <link linkend="condition_variable_wait">Templated
6302 member function <code>wait</code>()</link>
6303 </bridgehead>
6304 </para>
6305 <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>
6306
6307 <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> typename <phrase role="identifier">Pred</phrase> <phrase role="special">&gt;</phrase>
6308 <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>
6309 </programlisting>
6310 <variablelist>
6311 <title></title>
6312 <varlistentry>
6313 <term>Precondition:</term>
6314 <listitem>
6315 <para>
6316 <code><phrase role="identifier">lk</phrase></code> is locked by the
6317 current fiber, and either no other fiber is currently waiting on <code><phrase
6318 role="special">*</phrase><phrase role="keyword">this</phrase></code>,
6319 or the execution of the <ulink url="http://en.cppreference.com/w/cpp/thread/unique_lock/mutex"><code><phrase
6320 role="identifier">mutex</phrase><phrase role="special">()</phrase></code></ulink>
6321 member function on the <code><phrase role="identifier">lk</phrase></code>
6322 objects supplied in the calls to <code><phrase role="identifier">wait</phrase></code>
6323 in all the fibers currently waiting on <code><phrase role="special">*</phrase><phrase
6324 role="keyword">this</phrase></code> would return the same value as
6325 <code><phrase role="identifier">lk</phrase><phrase role="special">-&gt;</phrase><phrase
6326 role="identifier">mutex</phrase><phrase role="special">()</phrase></code>
6327 for this call to <code><phrase role="identifier">wait</phrase></code>.
6328 </para>
6329 </listitem>
6330 </varlistentry>
6331 <varlistentry>
6332 <term>Effects:</term>
6333 <listitem>
6334 <para>
6335 Atomically call <code><phrase role="identifier">lk</phrase><phrase
6336 role="special">.</phrase><phrase role="identifier">unlock</phrase><phrase
6337 role="special">()</phrase></code> and blocks the current fiber. The
6338 fiber will unblock when notified by a call to <code><phrase role="keyword">this</phrase><phrase
6339 role="special">-&gt;</phrase><phrase role="identifier">notify_one</phrase><phrase
6340 role="special">()</phrase></code> or <code><phrase role="keyword">this</phrase><phrase
6341 role="special">-&gt;</phrase><phrase role="identifier">notify_all</phrase><phrase
6342 role="special">()</phrase></code>. When the fiber is unblocked (for
6343 whatever reason), the lock is reacquired by invoking <code><phrase
6344 role="identifier">lk</phrase><phrase role="special">.</phrase><phrase
6345 role="identifier">lock</phrase><phrase role="special">()</phrase></code>
6346 before the call to <code><phrase role="identifier">wait</phrase></code>
6347 returns. The lock is also reacquired by invoking <code><phrase role="identifier">lk</phrase><phrase
6348 role="special">.</phrase><phrase role="identifier">lock</phrase><phrase
6349 role="special">()</phrase></code> if the function exits with an exception.
6350 The member function accepting <code><phrase role="identifier">pred</phrase></code>
6351 is shorthand for:
6352 <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>
6353 <phrase role="identifier">wait</phrase><phrase role="special">(</phrase> <phrase role="identifier">lk</phrase><phrase role="special">);</phrase>
6354 <phrase role="special">}</phrase>
6355 </programlisting>
6356 </para>
6357 </listitem>
6358 </varlistentry>
6359 <varlistentry>
6360 <term>Postcondition:</term>
6361 <listitem>
6362 <para>
6363 <code><phrase role="identifier">lk</phrase></code> is locked by the
6364 current fiber.
6365 </para>
6366 </listitem>
6367 </varlistentry>
6368 <varlistentry>
6369 <term>Throws:</term>
6370 <listitem>
6371 <para>
6372 <code><phrase role="identifier">fiber_error</phrase></code> if an error
6373 occurs.
6374 </para>
6375 </listitem>
6376 </varlistentry>
6377 <varlistentry>
6378 <term>Note:</term>
6379 <listitem>
6380 <para>
6381 The Precondition is a bit dense. It merely states that all the fibers
6382 concurrently calling <code><phrase role="identifier">wait</phrase></code>
6383 on <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>
6384 must wait on <code><phrase role="identifier">lk</phrase></code> objects
6385 governing the <emphasis>same</emphasis> <link linkend="class_mutex"><code>mutex</code></link>. Three distinct
6386 objects are involved in any <code>condition_variable::wait()</code> call: the <code>condition_variable</code> itself,
6387 the <code><phrase role="identifier">mutex</phrase></code> coordinating
6388 access between fibers and a local lock object (e.g. <ulink url="http://en.cppreference.com/w/cpp/thread/unique_lock"><code><phrase
6389 role="identifier">std</phrase><phrase role="special">::</phrase><phrase
6390 role="identifier">unique_lock</phrase></code></ulink>). In general,
6391 you can partition the lifespan of a given <code>condition_variable</code> instance
6392 into periods with one or more fibers waiting on it, separated by periods
6393 when no fibers are waiting on it. When more than one fiber is waiting
6394 on that <code>condition_variable</code>, all must pass lock objects referencing
6395 the <emphasis>same</emphasis> <code><phrase role="identifier">mutex</phrase></code>
6396 instance.
6397 </para>
6398 </listitem>
6399 </varlistentry>
6400 </variablelist>
6401 <para>
6402 <bridgehead renderas="sect4" id="condition_variable_wait_until_bridgehead">
6403 <phrase id="condition_variable_wait_until"/>
6404 <link linkend="condition_variable_wait_until">Templated
6405 member function <code>wait_until</code>()</link>
6406 </bridgehead>
6407 </para>
6408 <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>
6409 <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>
6410 <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>
6411
6412 <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>
6413 <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>
6414 <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>
6415 <phrase role="identifier">Pred</phrase> <phrase role="identifier">pred</phrase><phrase role="special">);</phrase>
6416 </programlisting>
6417 <variablelist>
6418 <title></title>
6419 <varlistentry>
6420 <term>Precondition:</term>
6421 <listitem>
6422 <para>
6423 <code><phrase role="identifier">lk</phrase></code> is locked by the
6424 current fiber, and either no other fiber is currently waiting on <code><phrase
6425 role="special">*</phrase><phrase role="keyword">this</phrase></code>,
6426 or the execution of the <code><phrase role="identifier">mutex</phrase><phrase
6427 role="special">()</phrase></code> member function on the <code><phrase
6428 role="identifier">lk</phrase></code> objects supplied in the calls
6429 to <code><phrase role="identifier">wait</phrase></code>, <code><phrase
6430 role="identifier">wait_for</phrase></code> or <code><phrase role="identifier">wait_until</phrase></code>
6431 in all the fibers currently waiting on <code><phrase role="special">*</phrase><phrase
6432 role="keyword">this</phrase></code> would return the same value as
6433 <code><phrase role="identifier">lk</phrase><phrase role="special">.</phrase><phrase
6434 role="identifier">mutex</phrase><phrase role="special">()</phrase></code>
6435 for this call to <code><phrase role="identifier">wait_until</phrase></code>.
6436 </para>
6437 </listitem>
6438 </varlistentry>
6439 <varlistentry>
6440 <term>Effects:</term>
6441 <listitem>
6442 <para>
6443 Atomically call <code><phrase role="identifier">lk</phrase><phrase
6444 role="special">.</phrase><phrase role="identifier">unlock</phrase><phrase
6445 role="special">()</phrase></code> and blocks the current fiber. The
6446 fiber will unblock when notified by a call to <code><phrase role="keyword">this</phrase><phrase
6447 role="special">-&gt;</phrase><phrase role="identifier">notify_one</phrase><phrase
6448 role="special">()</phrase></code> or <code><phrase role="keyword">this</phrase><phrase
6449 role="special">-&gt;</phrase><phrase role="identifier">notify_all</phrase><phrase
6450 role="special">()</phrase></code>, when the system time would be equal
6451 to or later than the specified <code><phrase role="identifier">abs_time</phrase></code>.
6452 When the fiber is unblocked (for whatever reason), the lock is reacquired
6453 by invoking <code><phrase role="identifier">lk</phrase><phrase role="special">.</phrase><phrase
6454 role="identifier">lock</phrase><phrase role="special">()</phrase></code>
6455 before the call to <code><phrase role="identifier">wait_until</phrase></code>
6456 returns. The lock is also reacquired by invoking <code><phrase role="identifier">lk</phrase><phrase
6457 role="special">.</phrase><phrase role="identifier">lock</phrase><phrase
6458 role="special">()</phrase></code> if the function exits with an exception.
6459 The member function accepting <code><phrase role="identifier">pred</phrase></code>
6460 is shorthand for:
6461 <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>
6462 <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>
6463 <phrase role="keyword">return</phrase> <phrase role="identifier">pred</phrase><phrase role="special">();</phrase>
6464 <phrase role="special">}</phrase>
6465 <phrase role="keyword">return</phrase> <phrase role="keyword">true</phrase><phrase role="special">;</phrase>
6466 </programlisting>
6467 That is, even if <code><phrase role="identifier">wait_until</phrase><phrase
6468 role="special">()</phrase></code> times out, it can still return <code><phrase
6469 role="keyword">true</phrase></code> if <code><phrase role="identifier">pred</phrase><phrase
6470 role="special">()</phrase></code> returns <code><phrase role="keyword">true</phrase></code>
6471 at that time.
6472 </para>
6473 </listitem>
6474 </varlistentry>
6475 <varlistentry>
6476 <term>Postcondition:</term>
6477 <listitem>
6478 <para>
6479 <code><phrase role="identifier">lk</phrase></code> is locked by the
6480 current fiber.
6481 </para>
6482 </listitem>
6483 </varlistentry>
6484 <varlistentry>
6485 <term>Throws:</term>
6486 <listitem>
6487 <para>
6488 <code><phrase role="identifier">fiber_error</phrase></code> if an error
6489 occurs or timeout-related exceptions.
6490 </para>
6491 </listitem>
6492 </varlistentry>
6493 <varlistentry>
6494 <term>Returns:</term>
6495 <listitem>
6496 <para>
6497 The overload without <code><phrase role="identifier">pred</phrase></code>
6498 returns <code><phrase role="identifier">cv_status</phrase><phrase role="special">::</phrase><phrase
6499 role="identifier">no_timeout</phrase></code> if awakened by <code><phrase
6500 role="identifier">notify_one</phrase><phrase role="special">()</phrase></code>
6501 or <code><phrase role="identifier">notify_all</phrase><phrase role="special">()</phrase></code>,
6502 or <code><phrase role="identifier">cv_status</phrase><phrase role="special">::</phrase><phrase
6503 role="identifier">timeout</phrase></code> if awakened because the system
6504 time is past <code><phrase role="identifier">abs_time</phrase></code>.
6505 </para>
6506 </listitem>
6507 </varlistentry>
6508 <varlistentry>
6509 <term>Returns:</term>
6510 <listitem>
6511 <para>
6512 The overload accepting <code><phrase role="identifier">pred</phrase></code>
6513 returns <code><phrase role="keyword">false</phrase></code> if the call
6514 is returning because the time specified by <code><phrase role="identifier">abs_time</phrase></code>
6515 was reached and the predicate returns <code><phrase role="keyword">false</phrase></code>,
6516 <code><phrase role="keyword">true</phrase></code> otherwise.
6517 </para>
6518 </listitem>
6519 </varlistentry>
6520 <varlistentry>
6521 <term>Note:</term>
6522 <listitem>
6523 <para>
6524 See <emphasis role="bold">Note</emphasis> for <link linkend="condition_variable_wait"><code>condition_variable::wait()</code></link>.
6525 </para>
6526 </listitem>
6527 </varlistentry>
6528 </variablelist>
6529 <para>
6530 <bridgehead renderas="sect4" id="condition_variable_wait_for_bridgehead">
6531 <phrase id="condition_variable_wait_for"/>
6532 <link linkend="condition_variable_wait_for">Templated
6533 member function <code>wait_for</code>()</link>
6534 </bridgehead>
6535 </para>
6536 <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>
6537 <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>
6538 <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>
6539
6540 <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>
6541 <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>
6542 <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>
6543 <phrase role="identifier">Pred</phrase> <phrase role="identifier">pred</phrase><phrase role="special">);</phrase>
6544 </programlisting>
6545 <variablelist>
6546 <title></title>
6547 <varlistentry>
6548 <term>Precondition:</term>
6549 <listitem>
6550 <para>
6551 <code><phrase role="identifier">lk</phrase></code> is locked by the
6552 current fiber, and either no other fiber is currently waiting on <code><phrase
6553 role="special">*</phrase><phrase role="keyword">this</phrase></code>,
6554 or the execution of the <code><phrase role="identifier">mutex</phrase><phrase
6555 role="special">()</phrase></code> member function on the <code><phrase
6556 role="identifier">lk</phrase></code> objects supplied in the calls
6557 to <code><phrase role="identifier">wait</phrase></code>, <code><phrase
6558 role="identifier">wait_for</phrase></code> or <code><phrase role="identifier">wait_until</phrase></code>
6559 in all the fibers currently waiting on <code><phrase role="special">*</phrase><phrase
6560 role="keyword">this</phrase></code> would return the same value as
6561 <code><phrase role="identifier">lk</phrase><phrase role="special">.</phrase><phrase
6562 role="identifier">mutex</phrase><phrase role="special">()</phrase></code>
6563 for this call to <code><phrase role="identifier">wait_for</phrase></code>.
6564 </para>
6565 </listitem>
6566 </varlistentry>
6567 <varlistentry>
6568 <term>Effects:</term>
6569 <listitem>
6570 <para>
6571 Atomically call <code><phrase role="identifier">lk</phrase><phrase
6572 role="special">.</phrase><phrase role="identifier">unlock</phrase><phrase
6573 role="special">()</phrase></code> and blocks the current fiber. The
6574 fiber will unblock when notified by a call to <code><phrase role="keyword">this</phrase><phrase
6575 role="special">-&gt;</phrase><phrase role="identifier">notify_one</phrase><phrase
6576 role="special">()</phrase></code> or <code><phrase role="keyword">this</phrase><phrase
6577 role="special">-&gt;</phrase><phrase role="identifier">notify_all</phrase><phrase
6578 role="special">()</phrase></code>, when a time interval equal to or
6579 greater than the specified <code><phrase role="identifier">rel_time</phrase></code>
6580 has elapsed. When the fiber is unblocked (for whatever reason), the
6581 lock is reacquired by invoking <code><phrase role="identifier">lk</phrase><phrase
6582 role="special">.</phrase><phrase role="identifier">lock</phrase><phrase
6583 role="special">()</phrase></code> before the call to <code><phrase
6584 role="identifier">wait</phrase></code> returns. The lock is also reacquired
6585 by invoking <code><phrase role="identifier">lk</phrase><phrase role="special">.</phrase><phrase
6586 role="identifier">lock</phrase><phrase role="special">()</phrase></code>
6587 if the function exits with an exception. The <code><phrase role="identifier">wait_for</phrase><phrase
6588 role="special">()</phrase></code> member function accepting <code><phrase
6589 role="identifier">pred</phrase></code> is shorthand for:
6590 <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>
6591 <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>
6592 <phrase role="keyword">return</phrase> <phrase role="identifier">pred</phrase><phrase role="special">();</phrase>
6593 <phrase role="special">}</phrase>
6594 <phrase role="special">}</phrase>
6595 <phrase role="keyword">return</phrase> <phrase role="keyword">true</phrase><phrase role="special">;</phrase>
6596 </programlisting>
6597 (except of course that <code><phrase role="identifier">rel_time</phrase></code>
6598 is adjusted for each iteration). The point is that, even if <code><phrase
6599 role="identifier">wait_for</phrase><phrase role="special">()</phrase></code>
6600 times out, it can still return <code><phrase role="keyword">true</phrase></code>
6601 if <code><phrase role="identifier">pred</phrase><phrase role="special">()</phrase></code>
6602 returns <code><phrase role="keyword">true</phrase></code> at that time.
6603 </para>
6604 </listitem>
6605 </varlistentry>
6606 <varlistentry>
6607 <term>Postcondition:</term>
6608 <listitem>
6609 <para>
6610 <code><phrase role="identifier">lk</phrase></code> is locked by the
6611 current fiber.
6612 </para>
6613 </listitem>
6614 </varlistentry>
6615 <varlistentry>
6616 <term>Throws:</term>
6617 <listitem>
6618 <para>
6619 <code><phrase role="identifier">fiber_error</phrase></code> if an error
6620 occurs or timeout-related exceptions.
6621 </para>
6622 </listitem>
6623 </varlistentry>
6624 <varlistentry>
6625 <term>Returns:</term>
6626 <listitem>
6627 <para>
6628 The overload without <code><phrase role="identifier">pred</phrase></code>
6629 returns <code><phrase role="identifier">cv_status</phrase><phrase role="special">::</phrase><phrase
6630 role="identifier">no_timeout</phrase></code> if awakened by <code><phrase
6631 role="identifier">notify_one</phrase><phrase role="special">()</phrase></code>
6632 or <code><phrase role="identifier">notify_all</phrase><phrase role="special">()</phrase></code>,
6633 or <code><phrase role="identifier">cv_status</phrase><phrase role="special">::</phrase><phrase
6634 role="identifier">timeout</phrase></code> if awakened because at least
6635 <code><phrase role="identifier">rel_time</phrase></code> has elapsed.
6636 </para>
6637 </listitem>
6638 </varlistentry>
6639 <varlistentry>
6640 <term>Returns:</term>
6641 <listitem>
6642 <para>
6643 The overload accepting <code><phrase role="identifier">pred</phrase></code>
6644 returns <code><phrase role="keyword">false</phrase></code> if the call
6645 is returning because at least <code><phrase role="identifier">rel_time</phrase></code>
6646 has elapsed and the predicate returns <code><phrase role="keyword">false</phrase></code>,
6647 <code><phrase role="keyword">true</phrase></code> otherwise.
6648 </para>
6649 </listitem>
6650 </varlistentry>
6651 <varlistentry>
6652 <term>Note:</term>
6653 <listitem>
6654 <para>
6655 See <emphasis role="bold">Note</emphasis> for <link linkend="condition_variable_wait"><code>condition_variable::wait()</code></link>.
6656 </para>
6657 </listitem>
6658 </varlistentry>
6659 </variablelist>
6660 </section>
6661 <section id="fiber.synchronization.barriers">
6662 <title><link linkend="fiber.synchronization.barriers">Barriers</link></title>
6663 <para>
6664 A barrier is a concept also known as a <emphasis>rendezvous</emphasis>, it
6665 is a synchronization point between multiple contexts of execution (fibers).
6666 The barrier is configured for a particular number of fibers (<code><phrase
6667 role="identifier">n</phrase></code>), and as fibers reach the barrier they
6668 must wait until all <code><phrase role="identifier">n</phrase></code> fibers
6669 have arrived. Once the <code><phrase role="identifier">n</phrase></code>-th
6670 fiber has reached the barrier, all the waiting fibers can proceed, and the
6671 barrier is reset.
6672 </para>
6673 <para>
6674 The fact that the barrier automatically resets is significant. Consider a
6675 case in which you launch some number of fibers and want to wait only until
6676 the first of them has completed. You might be tempted to use a <code><phrase
6677 role="identifier">barrier</phrase><phrase role="special">(</phrase><phrase
6678 role="number">2</phrase><phrase role="special">)</phrase></code> as the synchronization
6679 mechanism, making each new fiber call its <link linkend="barrier_wait"><code>barrier::wait()</code></link> method,
6680 then calling <code><phrase role="identifier">wait</phrase><phrase role="special">()</phrase></code>
6681 in the launching fiber to wait until the first other fiber completes.
6682 </para>
6683 <para>
6684 That will in fact unblock the launching fiber. The unfortunate part is that
6685 it will continue blocking the <emphasis>remaining</emphasis> fibers.
6686 </para>
6687 <para>
6688 Consider the following scenario:
6689 </para>
6690 <orderedlist>
6691 <listitem>
6692 <simpara>
6693 Fiber <quote>main</quote> launches fibers A, B, C and D, then calls
6694 <code><phrase role="identifier">barrier</phrase><phrase role="special">::</phrase><phrase
6695 role="identifier">wait</phrase><phrase role="special">()</phrase></code>.
6696 </simpara>
6697 </listitem>
6698 <listitem>
6699 <simpara>
6700 Fiber C finishes first and likewise calls <code><phrase role="identifier">barrier</phrase><phrase
6701 role="special">::</phrase><phrase role="identifier">wait</phrase><phrase
6702 role="special">()</phrase></code>.
6703 </simpara>
6704 </listitem>
6705 <listitem>
6706 <simpara>
6707 Fiber <quote>main</quote> is unblocked, as desired.
6708 </simpara>
6709 </listitem>
6710 <listitem>
6711 <simpara>
6712 Fiber B calls <code><phrase role="identifier">barrier</phrase><phrase
6713 role="special">::</phrase><phrase role="identifier">wait</phrase><phrase
6714 role="special">()</phrase></code>. Fiber B is <emphasis>blocked!</emphasis>
6715 </simpara>
6716 </listitem>
6717 <listitem>
6718 <simpara>
6719 Fiber A calls <code><phrase role="identifier">barrier</phrase><phrase
6720 role="special">::</phrase><phrase role="identifier">wait</phrase><phrase
6721 role="special">()</phrase></code>. Fibers A and B are unblocked.
6722 </simpara>
6723 </listitem>
6724 <listitem>
6725 <simpara>
6726 Fiber D calls <code><phrase role="identifier">barrier</phrase><phrase
6727 role="special">::</phrase><phrase role="identifier">wait</phrase><phrase
6728 role="special">()</phrase></code>. Fiber D is blocked indefinitely.
6729 </simpara>
6730 </listitem>
6731 </orderedlist>
6732 <para>
6733 (See also <link linkend="wait_first_simple_section">when_any, simple completion</link>.)
6734 </para>
6735 <note>
6736 <para>
6737 It is unwise to tie the lifespan of a barrier to any one of its participating
6738 fibers. Although conceptually all waiting fibers awaken <quote>simultaneously,</quote>
6739 because of the nature of fibers, in practice they will awaken one by one
6740 in indeterminate order.<footnote id="fiber.synchronization.barriers.f0">
6741 <para>
6742 The current implementation wakes fibers in FIFO order: the first to call
6743 <code><phrase role="identifier">wait</phrase><phrase role="special">()</phrase></code>
6744 wakes first, and so forth. But it is perilous to rely on the order in
6745 which the various fibers will reach the <code><phrase role="identifier">wait</phrase><phrase
6746 role="special">()</phrase></code> call.
6747 </para>
6748 </footnote> The rest of the waiting fibers will still be blocked in <code><phrase
6749 role="identifier">wait</phrase><phrase role="special">()</phrase></code>,
6750 which must, before returning, access data members in the barrier object.
6751 </para>
6752 </note>
6753 <para>
6754 <bridgehead renderas="sect4" id="class_barrier_bridgehead">
6755 <phrase id="class_barrier"/>
6756 <link linkend="class_barrier">Class <code>barrier</code></link>
6757 </bridgehead>
6758 </para>
6759 <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>
6760
6761 <phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase>
6762 <phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase>
6763
6764 <phrase role="keyword">class</phrase> <phrase role="identifier">barrier</phrase> <phrase role="special">{</phrase>
6765 <phrase role="keyword">public</phrase><phrase role="special">:</phrase>
6766 <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>
6767
6768 <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>
6769 <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>
6770
6771 <phrase role="keyword">bool</phrase> <phrase role="identifier">wait</phrase><phrase role="special">();</phrase>
6772 <phrase role="special">};</phrase>
6773
6774 <phrase role="special">}}</phrase>
6775 </programlisting>
6776 <para>
6777 Instances of <link linkend="class_barrier"><code>barrier</code></link> are not copyable or movable.
6778 </para>
6779 <bridgehead renderas="sect4" id="fiber.synchronization.barriers.h0">
6780 <phrase id="fiber.synchronization.barriers.constructor"/><link linkend="fiber.synchronization.barriers.constructor">Constructor</link>
6781 </bridgehead>
6782 <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>
6783 </programlisting>
6784 <variablelist>
6785 <title></title>
6786 <varlistentry>
6787 <term>Effects:</term>
6788 <listitem>
6789 <para>
6790 Construct a barrier for <code><phrase role="identifier">initial</phrase></code>
6791 fibers.
6792 </para>
6793 </listitem>
6794 </varlistentry>
6795 <varlistentry>
6796 <term>Throws:</term>
6797 <listitem>
6798 <para>
6799 <code><phrase role="identifier">fiber_error</phrase></code>
6800 </para>
6801 </listitem>
6802 </varlistentry>
6803 <varlistentry>
6804 <term>Error Conditions:</term>
6805 <listitem>
6806 <para>
6807 <emphasis role="bold">invalid_argument</emphasis>: if <code><phrase
6808 role="identifier">initial</phrase></code> is zero.
6809 </para>
6810 </listitem>
6811 </varlistentry>
6812 </variablelist>
6813 <para>
6814 <bridgehead renderas="sect4" id="barrier_wait_bridgehead">
6815 <phrase id="barrier_wait"/>
6816 <link linkend="barrier_wait">Member function <code>wait</code>()</link>
6817 </bridgehead>
6818 </para>
6819 <programlisting><phrase role="keyword">bool</phrase> <phrase role="identifier">wait</phrase><phrase role="special">();</phrase>
6820 </programlisting>
6821 <variablelist>
6822 <title></title>
6823 <varlistentry>
6824 <term>Effects:</term>
6825 <listitem>
6826 <para>
6827 Block until <code><phrase role="identifier">initial</phrase></code>
6828 fibers have called <code><phrase role="identifier">wait</phrase></code>
6829 on <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>.
6830 When the <code><phrase role="identifier">initial</phrase></code>-th
6831 fiber calls <code><phrase role="identifier">wait</phrase></code>, all
6832 waiting fibers are unblocked, and the barrier is reset.
6833 </para>
6834 </listitem>
6835 </varlistentry>
6836 <varlistentry>
6837 <term>Returns:</term>
6838 <listitem>
6839 <para>
6840 <code><phrase role="keyword">true</phrase></code> for exactly one fiber
6841 from each batch of waiting fibers, <code><phrase role="keyword">false</phrase></code>
6842 otherwise.
6843 </para>
6844 </listitem>
6845 </varlistentry>
6846 <varlistentry>
6847 <term>Throws:</term>
6848 <listitem>
6849 <para>
6850 <code><phrase role="identifier">fiber_error</phrase></code>
6851 </para>
6852 </listitem>
6853 </varlistentry>
6854 </variablelist>
6855 </section>
6856 <section id="fiber.synchronization.channels">
6857 <title><link linkend="fiber.synchronization.channels">Channels</link></title>
6858 <para>
6859 <emphasis role="bold">Boost.Fiber</emphasis> provides a bounded and a unbounded
6860 channel suitable to synchonize fibers via message passing.
6861 </para>
6862 <programlisting><phrase role="keyword">typedef</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">unbounded_channel</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">int</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">channel_t</phrase><phrase role="special">;</phrase>
6863
6864 <phrase role="keyword">void</phrase> <phrase role="identifier">send</phrase><phrase role="special">(</phrase> <phrase role="identifier">channel_t</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">channel</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
6865 <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>
6866 <phrase role="identifier">channel</phrase><phrase role="special">.</phrase><phrase role="identifier">push</phrase><phrase role="special">(</phrase> <phrase role="identifier">i</phrase><phrase role="special">);</phrase>
6867 <phrase role="special">}</phrase>
6868 <phrase role="identifier">channel</phrase><phrase role="special">.</phrase><phrase role="identifier">close</phrase><phrase role="special">();</phrase>
6869 <phrase role="special">}</phrase>
6870
6871 <phrase role="keyword">void</phrase> <phrase role="identifier">recv</phrase><phrase role="special">(</phrase> <phrase role="identifier">channel_t</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">channel</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
6872 <phrase role="keyword">int</phrase> <phrase role="identifier">i</phrase><phrase role="special">;</phrase>
6873 <phrase role="keyword">while</phrase> <phrase role="special">(</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">channel_op_status</phrase><phrase role="special">::</phrase><phrase role="identifier">success</phrase> <phrase role="special">==</phrase> <phrase role="identifier">channel</phrase><phrase role="special">.</phrase><phrase role="identifier">pop</phrase><phrase role="special">(</phrase><phrase role="identifier">i</phrase><phrase role="special">)</phrase> <phrase role="special">)</phrase> <phrase role="special">{</phrase>
6874 <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>
6875 <phrase role="special">}</phrase>
6876 <phrase role="special">}</phrase>
6877
6878 <phrase role="identifier">channel_t</phrase> <phrase role="identifier">channel</phrase><phrase role="special">;</phrase>
6879 <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">fiber</phrase> <phrase role="identifier">f1</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">bind</phrase><phrase role="special">(</phrase> <phrase role="identifier">send</phrase><phrase role="special">,</phrase> <phrase role="identifier">ref</phrase><phrase role="special">(</phrase> <phrase role="identifier">channel</phrase><phrase role="special">)</phrase> <phrase role="special">)</phrase> <phrase role="special">);</phrase>
6880 <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">fiber</phrase> <phrase role="identifier">f2</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">bind</phrase><phrase role="special">(</phrase> <phrase role="identifier">recv</phrase><phrase role="special">,</phrase> <phrase role="identifier">ref</phrase><phrase role="special">(</phrase> <phrase role="identifier">channel</phrase><phrase role="special">)</phrase> <phrase role="special">)</phrase> <phrase role="special">);</phrase>
6881
6882 <phrase role="identifier">f1</phrase><phrase role="special">.</phrase><phrase role="identifier">join</phrase><phrase role="special">();</phrase>
6883 <phrase role="identifier">f2</phrase><phrase role="special">.</phrase><phrase role="identifier">join</phrase><phrase role="special">();</phrase>
6884 </programlisting>
6885 <anchor id="class_channel_op_status"/>
6886 <bridgehead renderas="sect4" id="fiber.synchronization.channels.h0">
6887 <phrase id="fiber.synchronization.channels.enumeration__code__phrase_role__identifier__channel_op_status__phrase___code_"/><link
6888 linkend="fiber.synchronization.channels.enumeration__code__phrase_role__identifier__channel_op_status__phrase___code_">Enumeration
6889 <code><phrase role="identifier">channel_op_status</phrase></code></link>
6890 </bridgehead>
6891 <para>
6892 channel operations return the state of the channel.
6893 </para>
6894 <programlisting><phrase role="keyword">enum</phrase> <phrase role="keyword">class</phrase> <phrase role="identifier">channel_op_status</phrase> <phrase role="special">{</phrase>
6895 <phrase role="identifier">success</phrase><phrase role="special">,</phrase>
6896 <phrase role="identifier">empty</phrase><phrase role="special">,</phrase>
6897 <phrase role="identifier">full</phrase><phrase role="special">,</phrase>
6898 <phrase role="identifier">closed</phrase><phrase role="special">,</phrase>
6899 <phrase role="identifier">timeout</phrase>
6900 <phrase role="special">};</phrase>
6901 </programlisting>
6902 <bridgehead renderas="sect4" id="fiber.synchronization.channels.h1">
6903 <phrase id="fiber.synchronization.channels._code__phrase_role__identifier__success__phrase___code_"/><link
6904 linkend="fiber.synchronization.channels._code__phrase_role__identifier__success__phrase___code_"><code><phrase
6905 role="identifier">success</phrase></code></link>
6906 </bridgehead>
6907 <variablelist>
6908 <title></title>
6909 <varlistentry>
6910 <term>Effects:</term>
6911 <listitem>
6912 <para>
6913 Operation was successful.
6914 </para>
6915 </listitem>
6916 </varlistentry>
6917 </variablelist>
6918 <bridgehead renderas="sect4" id="fiber.synchronization.channels.h2">
6919 <phrase id="fiber.synchronization.channels._code__phrase_role__identifier__empty__phrase___code_"/><link
6920 linkend="fiber.synchronization.channels._code__phrase_role__identifier__empty__phrase___code_"><code><phrase
6921 role="identifier">empty</phrase></code></link>
6922 </bridgehead>
6923 <variablelist>
6924 <title></title>
6925 <varlistentry>
6926 <term>Effects:</term>
6927 <listitem>
6928 <para>
6929 channel is empty, operation failed.
6930 </para>
6931 </listitem>
6932 </varlistentry>
6933 </variablelist>
6934 <bridgehead renderas="sect4" id="fiber.synchronization.channels.h3">
6935 <phrase id="fiber.synchronization.channels._code__phrase_role__identifier__full__phrase___code_"/><link
6936 linkend="fiber.synchronization.channels._code__phrase_role__identifier__full__phrase___code_"><code><phrase
6937 role="identifier">full</phrase></code></link>
6938 </bridgehead>
6939 <variablelist>
6940 <title></title>
6941 <varlistentry>
6942 <term>Effects:</term>
6943 <listitem>
6944 <para>
6945 channel is full, operation failed.
6946 </para>
6947 </listitem>
6948 </varlistentry>
6949 </variablelist>
6950 <bridgehead renderas="sect4" id="fiber.synchronization.channels.h4">
6951 <phrase id="fiber.synchronization.channels._code__phrase_role__identifier__closed__phrase___code_"/><link
6952 linkend="fiber.synchronization.channels._code__phrase_role__identifier__closed__phrase___code_"><code><phrase
6953 role="identifier">closed</phrase></code></link>
6954 </bridgehead>
6955 <variablelist>
6956 <title></title>
6957 <varlistentry>
6958 <term>Effects:</term>
6959 <listitem>
6960 <para>
6961 channel is closed, operation failed.
6962 </para>
6963 </listitem>
6964 </varlistentry>
6965 </variablelist>
6966 <bridgehead renderas="sect4" id="fiber.synchronization.channels.h5">
6967 <phrase id="fiber.synchronization.channels._code__phrase_role__identifier__timeout__phrase___code_"/><link
6968 linkend="fiber.synchronization.channels._code__phrase_role__identifier__timeout__phrase___code_"><code><phrase
6969 role="identifier">timeout</phrase></code></link>
6970 </bridgehead>
6971 <variablelist>
6972 <title></title>
6973 <varlistentry>
6974 <term>Effects:</term>
6975 <listitem>
6976 <para>
6977 The operation did not become ready before specified timeout elapsed.
6978 </para>
6979 </listitem>
6980 </varlistentry>
6981 </variablelist>
6982 <para>
6983 <bridgehead renderas="sect4" id="class_unbounded_channel_bridgehead">
6984 <phrase id="class_unbounded_channel"/>
6985 <link linkend="class_unbounded_channel">Template
6986 <code>unbounded_channel&lt;&gt;</code></link>
6987 </bridgehead>
6988 </para>
6989 <programlisting><phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">fiber</phrase><phrase role="special">/</phrase><phrase role="identifier">unbounded_channel</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase>
6990
6991 <phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase>
6992 <phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase>
6993
6994 <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> <ulink url="http://en.cppreference.com/w/cpp/concept/Allocator"><code><phrase role="identifier">Allocator</phrase></code></ulink> <phrase role="special">=</phrase> <ulink url="http://en.cppreference.com/w/cpp/memory/allocator"><code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">allocator</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">T</phrase> <phrase role="special">&gt;</phrase></code></ulink> <phrase role="special">&gt;</phrase>
6995 <phrase role="keyword">class</phrase> <phrase role="identifier">unbounded_channel</phrase> <phrase role="special">{</phrase>
6996 <phrase role="keyword">public</phrase><phrase role="special">:</phrase>
6997 <phrase role="keyword">typedef</phrase> <phrase role="identifier">T</phrase> <phrase role="identifier">value_type</phrase><phrase role="special">;</phrase>
6998
6999 <phrase role="keyword">explicit</phrase> <phrase role="identifier">unbounded_channel</phrase><phrase role="special">(</phrase> <ulink url="http://en.cppreference.com/w/cpp/concept/Allocator"><code><phrase role="identifier">Allocator</phrase></code></ulink> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">alloc</phrase> <phrase role="special">=</phrase> <phrase role="identifier">Allocator</phrase><phrase role="special">()</phrase> <phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
7000
7001 <phrase role="identifier">unbounded_channel</phrase><phrase role="special">(</phrase> <phrase role="identifier">unbounded_channel</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="special">=</phrase> <phrase role="keyword">delete</phrase><phrase role="special">;</phrase>
7002 <phrase role="identifier">unbounded_channel</phrase> <phrase role="special">&amp;</phrase> <phrase role="keyword">operator</phrase><phrase role="special">=(</phrase> <phrase role="identifier">unbounded_channel</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="special">=</phrase> <phrase role="keyword">delete</phrase><phrase role="special">;</phrase>
7003
7004 <phrase role="keyword">void</phrase> <phrase role="identifier">close</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
7005
7006 <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>
7007 <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>
7008
7009 <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>
7010 <phrase role="identifier">value_type</phrase> <phrase role="identifier">value_pop</phrase><phrase role="special">();</phrase>
7011 <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>
7012 <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>
7013 <phrase role="identifier">channel_op_status</phrase> <phrase role="identifier">pop_wait_for</phrase><phrase role="special">(</phrase>
7014 <phrase role="identifier">value_type</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">va</phrase><phrase role="special">,</phrase>
7015 <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>
7016 <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>
7017 <phrase role="identifier">channel_op_status</phrase> <phrase role="identifier">pop_wait_until</phrase><phrase role="special">(</phrase>
7018 <phrase role="identifier">value_type</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">va</phrase><phrase role="special">,</phrase>
7019 <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>
7020 <phrase role="special">};</phrase>
7021
7022 <phrase role="special">}}</phrase>
7023 </programlisting>
7024 <bridgehead renderas="sect4" id="fiber.synchronization.channels.h6">
7025 <phrase id="fiber.synchronization.channels.constructor"/><link linkend="fiber.synchronization.channels.constructor">Constructor</link>
7026 </bridgehead>
7027 <programlisting><phrase role="keyword">explicit</phrase> <phrase role="identifier">unbounded_channel</phrase><phrase role="special">(</phrase> <ulink url="http://en.cppreference.com/w/cpp/concept/Allocator"><code><phrase role="identifier">Allocator</phrase></code></ulink> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">alloc</phrase> <phrase role="special">=</phrase> <phrase role="identifier">Allocator</phrase><phrase role="special">()</phrase> <phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
7028 </programlisting>
7029 <variablelist>
7030 <title></title>
7031 <varlistentry>
7032 <term>Effects:</term>
7033 <listitem>
7034 <para>
7035 Constructs an object of class <code><phrase role="identifier">unbounded_channel</phrase></code>.
7036 Internal nodes are allocated using <code><phrase role="identifier">alloc</phrase></code>
7037 - C++11-allocators are supported.
7038 </para>
7039 </listitem>
7040 </varlistentry>
7041 <varlistentry>
7042 <term>Throws:</term>
7043 <listitem>
7044 <para>
7045 Nothing.
7046 </para>
7047 </listitem>
7048 </varlistentry>
7049 <varlistentry>
7050 <term>See also:</term>
7051 <listitem>
7052 <para>
7053 <ulink url="http://en.cppreference.com/w/cpp/concept/Allocator"><code><phrase
7054 role="identifier">Allocator</phrase></code></ulink> concept, <ulink
7055 url="http://en.cppreference.com/w/cpp/memory/allocator"><code><phrase
7056 role="identifier">std</phrase><phrase role="special">::</phrase><phrase
7057 role="identifier">allocator</phrase><phrase role="special">&lt;</phrase>
7058 <phrase role="identifier">T</phrase> <phrase role="special">&gt;</phrase></code></ulink>
7059 </para>
7060 </listitem>
7061 </varlistentry>
7062 </variablelist>
7063 <para>
7064 <bridgehead renderas="sect4" id="unbounded_channel_close_bridgehead">
7065 <phrase id="unbounded_channel_close"/>
7066 <link linkend="unbounded_channel_close">Member
7067 function <code>close</code>()</link>
7068 </bridgehead>
7069 </para>
7070 <programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">close</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
7071 </programlisting>
7072 <variablelist>
7073 <title></title>
7074 <varlistentry>
7075 <term>Effects:</term>
7076 <listitem>
7077 <para>
7078 Deactivates the channel. No values can be put after calling <code><phrase
7079 role="keyword">this</phrase><phrase role="special">-&gt;</phrase><phrase
7080 role="identifier">close</phrase><phrase role="special">()</phrase></code>.
7081 Fibers blocked in <code><phrase role="keyword">this</phrase><phrase
7082 role="special">-&gt;</phrase><phrase role="identifier">pop</phrase><phrase
7083 role="special">()</phrase></code>, <code><phrase role="keyword">this</phrase><phrase
7084 role="special">-&gt;</phrase><phrase role="identifier">pop_wait_for</phrase><phrase
7085 role="special">()</phrase></code> or <code><phrase role="keyword">this</phrase><phrase
7086 role="special">-&gt;</phrase><phrase role="identifier">pop_wait_until</phrase><phrase
7087 role="special">()</phrase></code> will return <code><phrase role="identifier">closed</phrase></code>.
7088 Fibers blocked in <code><phrase role="keyword">this</phrase><phrase
7089 role="special">-&gt;</phrase><phrase role="identifier">value_pop</phrase><phrase
7090 role="special">()</phrase></code> will receive an exception.
7091 </para>
7092 </listitem>
7093 </varlistentry>
7094 <varlistentry>
7095 <term>Throws:</term>
7096 <listitem>
7097 <para>
7098 Nothing.
7099 </para>
7100 </listitem>
7101 </varlistentry>
7102 <varlistentry>
7103 <term>Note:</term>
7104 <listitem>
7105 <para>
7106 <code><phrase role="identifier">close</phrase><phrase role="special">()</phrase></code>
7107 is like closing a pipe. It informs waiting consumers that no more values
7108 will arrive.
7109 </para>
7110 </listitem>
7111 </varlistentry>
7112 </variablelist>
7113 <para>
7114 <bridgehead renderas="sect4" id="unbounded_channel_push_bridgehead">
7115 <phrase id="unbounded_channel_push"/>
7116 <link linkend="unbounded_channel_push">Member
7117 function <code>push</code>()</link>
7118 </bridgehead>
7119 </para>
7120 <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>
7121 <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>
7122 </programlisting>
7123 <variablelist>
7124 <title></title>
7125 <varlistentry>
7126 <term>Effects:</term>
7127 <listitem>
7128 <para>
7129 If channel is closed, returns <code><phrase role="identifier">closed</phrase></code>.
7130 Otherwise enqueues the value in the channel, wakes up a fiber blocked
7131 on <code><phrase role="keyword">this</phrase><phrase role="special">-&gt;</phrase><phrase
7132 role="identifier">pop</phrase><phrase role="special">()</phrase></code>,
7133 <code><phrase role="keyword">this</phrase><phrase role="special">-&gt;</phrase><phrase
7134 role="identifier">value_pop</phrase><phrase role="special">()</phrase></code>,
7135 <code><phrase role="keyword">this</phrase><phrase role="special">-&gt;</phrase><phrase
7136 role="identifier">pop_wait_for</phrase><phrase role="special">()</phrase></code>
7137 or <code><phrase role="keyword">this</phrase><phrase role="special">-&gt;</phrase><phrase
7138 role="identifier">pop_wait_until</phrase><phrase role="special">()</phrase></code>
7139 and returns <code><phrase role="identifier">success</phrase></code>.
7140 </para>
7141 </listitem>
7142 </varlistentry>
7143 <varlistentry>
7144 <term>Throws:</term>
7145 <listitem>
7146 <para>
7147 Exceptions thrown by memory allocation and copying or moving <code><phrase
7148 role="identifier">va</phrase></code>.
7149 </para>
7150 </listitem>
7151 </varlistentry>
7152 </variablelist>
7153 <para>
7154 <bridgehead renderas="sect4" id="unbounded_channel_pop_bridgehead">
7155 <phrase id="unbounded_channel_pop"/>
7156 <link linkend="unbounded_channel_pop">Member
7157 function <code>pop</code>()</link>
7158 </bridgehead>
7159 </para>
7160 <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>
7161 </programlisting>
7162 <variablelist>
7163 <title></title>
7164 <varlistentry>
7165 <term>Effects:</term>
7166 <listitem>
7167 <para>
7168 Dequeues a value from the channel. If the channel is empty, the fiber
7169 gets suspended until at least one new item is <code><phrase role="identifier">push</phrase><phrase
7170 role="special">()</phrase></code>ed (return value <code><phrase role="identifier">success</phrase></code>
7171 and <code><phrase role="identifier">va</phrase></code> contains dequeued
7172 value) or the channel gets <code><phrase role="identifier">close</phrase><phrase
7173 role="special">()</phrase></code>d (return value <code><phrase role="identifier">closed</phrase></code>).
7174 </para>
7175 </listitem>
7176 </varlistentry>
7177 <varlistentry>
7178 <term>Throws:</term>
7179 <listitem>
7180 <para>
7181 Nothing
7182 </para>
7183 </listitem>
7184 </varlistentry>
7185 </variablelist>
7186 <para>
7187 <bridgehead renderas="sect4" id="unbounded_channel_value_pop_bridgehead">
7188 <phrase id="unbounded_channel_value_pop"/>
7189 <link linkend="unbounded_channel_value_pop">Member
7190 function <code>value_pop</code>()</link>
7191 </bridgehead>
7192 </para>
7193 <programlisting><phrase role="identifier">value_type</phrase> <phrase role="identifier">value_pop</phrase><phrase role="special">();</phrase>
7194 </programlisting>
7195 <variablelist>
7196 <title></title>
7197 <varlistentry>
7198 <term>Effects:</term>
7199 <listitem>
7200 <para>
7201 Dequeues a value from the channel. If the channel is empty, the fiber
7202 gets suspended until at least one new item is <code><phrase role="identifier">push</phrase><phrase
7203 role="special">()</phrase></code>ed or the channel gets <code><phrase
7204 role="identifier">close</phrase><phrase role="special">()</phrase></code>d
7205 (which throws an exception).
7206 </para>
7207 </listitem>
7208 </varlistentry>
7209 <varlistentry>
7210 <term>Throws:</term>
7211 <listitem>
7212 <para>
7213 <code><phrase role="identifier">fiber_error</phrase></code> if <code><phrase
7214 role="special">*</phrase><phrase role="keyword">this</phrase></code>
7215 is closed
7216 </para>
7217 </listitem>
7218 </varlistentry>
7219 <varlistentry>
7220 <term>Error conditions:</term>
7221 <listitem>
7222 <para>
7223 <code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase
7224 role="identifier">errc</phrase><phrase role="special">::</phrase><phrase
7225 role="identifier">operation_not_permitted</phrase></code>
7226 </para>
7227 </listitem>
7228 </varlistentry>
7229 </variablelist>
7230 <para>
7231 <bridgehead renderas="sect4" id="unbounded_channel_try_pop_bridgehead">
7232 <phrase id="unbounded_channel_try_pop"/>
7233 <link linkend="unbounded_channel_try_pop">Member
7234 function <code>try_pop</code>()</link>
7235 </bridgehead>
7236 </para>
7237 <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>
7238 </programlisting>
7239 <variablelist>
7240 <title></title>
7241 <varlistentry>
7242 <term>Effects:</term>
7243 <listitem>
7244 <para>
7245 If channel is empty, returns <code><phrase role="identifier">empty</phrase></code>.
7246 If channel is closed, returns <code><phrase role="identifier">closed</phrase></code>.
7247 Otherwise it returns <code><phrase role="identifier">success</phrase></code>
7248 and <code><phrase role="identifier">va</phrase></code> contains the
7249 dequeued value.
7250 </para>
7251 </listitem>
7252 </varlistentry>
7253 <varlistentry>
7254 <term>Throws:</term>
7255 <listitem>
7256 <para>
7257 Exceptions thrown by copy- or move-operations.
7258 </para>
7259 </listitem>
7260 </varlistentry>
7261 </variablelist>
7262 <para>
7263 <bridgehead renderas="sect4" id="unbounded_channel_pop_wait_for_bridgehead">
7264 <phrase id="unbounded_channel_pop_wait_for"/>
7265 <link linkend="unbounded_channel_pop_wait_for">Member
7266 function <code>pop_wait_for</code>()</link>
7267 </bridgehead>
7268 </para>
7269 <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>
7270 <phrase role="identifier">channel_op_status</phrase> <phrase role="identifier">pop_wait_for</phrase><phrase role="special">(</phrase>
7271 <phrase role="identifier">value_type</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">va</phrase><phrase role="special">,</phrase>
7272 <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>
7273 </programlisting>
7274 <variablelist>
7275 <title></title>
7276 <varlistentry>
7277 <term>Effects:</term>
7278 <listitem>
7279 <para>
7280 Accepts <code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase
7281 role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase
7282 role="identifier">duration</phrase></code> and internally computes
7283 a timeout time as (system time + <code><phrase role="identifier">timeout_duration</phrase></code>).
7284 If channel is not empty, immediately dequeues a value from the channel.
7285 Otherwise the fiber gets suspended until at least one new item is
7286 <code><phrase role="identifier">push</phrase><phrase role="special">()</phrase></code>ed
7287 (return value <code><phrase role="identifier">success</phrase></code>
7288 and <code><phrase role="identifier">va</phrase></code> contains dequeued
7289 value), or the channel gets <code><phrase role="identifier">close</phrase><phrase
7290 role="special">()</phrase></code>d (return value <code><phrase role="identifier">closed</phrase></code>),
7291 or the system time reaches the computed timeout time (return value
7292 <code><phrase role="identifier">timeout</phrase></code>).
7293 </para>
7294 </listitem>
7295 </varlistentry>
7296 <varlistentry>
7297 <term>Throws:</term>
7298 <listitem>
7299 <para>
7300 timeout-related exceptions.
7301 </para>
7302 </listitem>
7303 </varlistentry>
7304 </variablelist>
7305 <para>
7306 <bridgehead renderas="sect4" id="unbounded_channel_pop_wait_until_bridgehead">
7307 <phrase id="unbounded_channel_pop_wait_until"/>
7308 <link linkend="unbounded_channel_pop_wait_until">Member
7309 function <code>pop_wait_until</code>()</link>
7310 </bridgehead>
7311 </para>
7312 <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>
7313 <phrase role="identifier">channel_op_status</phrase> <phrase role="identifier">pop_wait_until</phrase><phrase role="special">(</phrase>
7314 <phrase role="identifier">value_type</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">va</phrase><phrase role="special">,</phrase>
7315 <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>
7316 </programlisting>
7317 <variablelist>
7318 <title></title>
7319 <varlistentry>
7320 <term>Effects:</term>
7321 <listitem>
7322 <para>
7323 Accepts a <code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase
7324 role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase
7325 role="identifier">time_point</phrase><phrase role="special">&lt;</phrase>
7326 <phrase role="identifier">Clock</phrase><phrase role="special">,</phrase>
7327 <phrase role="identifier">Duration</phrase> <phrase role="special">&gt;</phrase></code>.
7328 If channel is not empty, immediately dequeues a value from the channel.
7329 Otherwise the fiber gets suspended until at least one new item is
7330 <code><phrase role="identifier">push</phrase><phrase role="special">()</phrase></code>ed
7331 (return value <code><phrase role="identifier">success</phrase></code>
7332 and <code><phrase role="identifier">va</phrase></code> contains dequeued
7333 value), or the channel gets <code><phrase role="identifier">close</phrase><phrase
7334 role="special">()</phrase></code>d (return value <code><phrase role="identifier">closed</phrase></code>),
7335 or the system time reaches the passed <code><phrase role="identifier">time_point</phrase></code>
7336 (return value <code><phrase role="identifier">timeout</phrase></code>).
7337 </para>
7338 </listitem>
7339 </varlistentry>
7340 <varlistentry>
7341 <term>Throws:</term>
7342 <listitem>
7343 <para>
7344 timeout-related exceptions.
7345 </para>
7346 </listitem>
7347 </varlistentry>
7348 </variablelist>
7349 <para>
7350 <bridgehead renderas="sect4" id="class_bounded_channel_bridgehead">
7351 <phrase id="class_bounded_channel"/>
7352 <link linkend="class_bounded_channel">Template
7353 <code>bounded_channel&lt;&gt;</code></link>
7354 </bridgehead>
7355 </para>
7356 <programlisting><phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">fiber</phrase><phrase role="special">/</phrase><phrase role="identifier">bounded_channel</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase>
7357
7358 <phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase>
7359 <phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase>
7360
7361 <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> <ulink url="http://en.cppreference.com/w/cpp/concept/Allocator"><code><phrase role="identifier">Allocator</phrase></code></ulink> <phrase role="special">=</phrase> <ulink url="http://en.cppreference.com/w/cpp/memory/allocator"><code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">allocator</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">T</phrase> <phrase role="special">&gt;</phrase></code></ulink> <phrase role="special">&gt;</phrase>
7362 <phrase role="keyword">class</phrase> <phrase role="identifier">bounded_channel</phrase> <phrase role="special">{</phrase>
7363 <phrase role="keyword">public</phrase><phrase role="special">:</phrase>
7364 <phrase role="keyword">typedef</phrase> <phrase role="identifier">T</phrase> <phrase role="identifier">value_type</phrase><phrase role="special">;</phrase>
7365
7366 <phrase role="identifier">bounded_channel</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">wm</phrase><phrase role="special">,</phrase> <ulink url="http://en.cppreference.com/w/cpp/concept/Allocator"><code><phrase role="identifier">Allocator</phrase></code></ulink> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">alloc</phrase> <phrase role="special">=</phrase> <phrase role="identifier">Allocator</phrase><phrase role="special">()</phrase> <phrase role="special">);</phrase>
7367 <phrase role="identifier">bounded_channel</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">hwm</phrase><phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">lwm</phrase><phrase role="special">,</phrase> <ulink url="http://en.cppreference.com/w/cpp/concept/Allocator"><code><phrase role="identifier">Allocator</phrase></code></ulink> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">alloc</phrase> <phrase role="special">=</phrase> <phrase role="identifier">Allocator</phrase><phrase role="special">()</phrase> <phrase role="special">);</phrase>
7368
7369 <phrase role="identifier">bounded_channel</phrase><phrase role="special">(</phrase> <phrase role="identifier">bounded_channel</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="special">=</phrase> <phrase role="keyword">delete</phrase><phrase role="special">;</phrase>
7370 <phrase role="identifier">bounded_channel</phrase> <phrase role="special">&amp;</phrase> <phrase role="keyword">operator</phrase><phrase role="special">=(</phrase> <phrase role="identifier">bounded_channel</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="special">=</phrase> <phrase role="keyword">delete</phrase><phrase role="special">;</phrase>
7371
7372 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">upper_bound</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
7373 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">lower_bound</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
7374
7375 <phrase role="keyword">void</phrase> <phrase role="identifier">close</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
7376
7377 <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>
7378 <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>
7379 <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>
7380 <phrase role="identifier">channel_op_status</phrase> <phrase role="identifier">push_wait_for</phrase><phrase role="special">(</phrase>
7381 <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>
7382 <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>
7383 <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>
7384 <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>
7385 <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>
7386 <phrase role="identifier">channel_op_status</phrase> <phrase role="identifier">push_wait_until</phrase><phrase role="special">(</phrase>
7387 <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>
7388 <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>
7389 <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>
7390 <phrase role="identifier">channel_op_status</phrase> <phrase role="identifier">push_wait_until</phrase><phrase role="special">(</phrase>
7391 <phrase role="identifier">value_type</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="identifier">va</phrase><phrase role="special">,</phrase>
7392 <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>
7393 <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>
7394 <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>
7395
7396 <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>
7397 <phrase role="identifier">value_type</phrase> <phrase role="identifier">value_pop</phrase><phrase role="special">();</phrase>
7398 <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>
7399 <phrase role="identifier">channel_op_status</phrase> <phrase role="identifier">pop_wait_for</phrase><phrase role="special">(</phrase>
7400 <phrase role="identifier">value_type</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">va</phrase><phrase role="special">,</phrase>
7401 <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>
7402 <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>
7403 <phrase role="identifier">channel_op_status</phrase> <phrase role="identifier">pop_wait_until</phrase><phrase role="special">(</phrase>
7404 <phrase role="identifier">value_type</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">va</phrase><phrase role="special">,</phrase>
7405 <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>
7406 <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>
7407 <phrase role="special">};</phrase>
7408
7409 <phrase role="special">}}</phrase>
7410 </programlisting>
7411 <bridgehead renderas="sect4" id="fiber.synchronization.channels.h7">
7412 <phrase id="fiber.synchronization.channels.constructor0"/><link linkend="fiber.synchronization.channels.constructor0">Constructor</link>
7413 </bridgehead>
7414 <programlisting><phrase role="identifier">bounded_channel</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">wm</phrase><phrase role="special">,</phrase> <ulink url="http://en.cppreference.com/w/cpp/concept/Allocator"><code><phrase role="identifier">Allocator</phrase></code></ulink> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">alloc</phrase> <phrase role="special">=</phrase> <phrase role="identifier">Allocator</phrase><phrase role="special">()</phrase> <phrase role="special">);</phrase>
7415 <phrase role="identifier">bounded_channel</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">hwm</phrase><phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">lwm</phrase><phrase role="special">,</phrase> <ulink url="http://en.cppreference.com/w/cpp/concept/Allocator"><code><phrase role="identifier">Allocator</phrase></code></ulink> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">alloc</phrase> <phrase role="special">=</phrase> <phrase role="identifier">Allocator</phrase><phrase role="special">()</phrase> <phrase role="special">);</phrase>
7416 </programlisting>
7417 <variablelist>
7418 <title></title>
7419 <varlistentry>
7420 <term>Preconditions:</term>
7421 <listitem>
7422 <para>
7423 <code><phrase role="identifier">hwm</phrase> <phrase role="special">&gt;</phrase>
7424 <phrase role="identifier">lwm</phrase></code>
7425 </para>
7426 </listitem>
7427 </varlistentry>
7428 <varlistentry>
7429 <term>Effects:</term>
7430 <listitem>
7431 <para>
7432 Constructs an object of class <code><phrase role="identifier">bounded_channel</phrase></code>.
7433 The constructor with two arguments constructs an object of class <code><phrase
7434 role="identifier">bounded_channel</phrase></code> with a high-watermark
7435 of <code><phrase role="identifier">hwm</phrase></code> and a low-watermark
7436 of <code><phrase role="identifier">lwm</phrase></code> items. The constructor
7437 with one <code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase
7438 role="identifier">size_t</phrase></code> argument is effectively the
7439 same as <code><phrase role="identifier">bounded_channel</phrase><phrase
7440 role="special">(</phrase><phrase role="identifier">wm</phrase><phrase
7441 role="special">,</phrase> <phrase role="special">(</phrase><phrase
7442 role="identifier">wm</phrase><phrase role="special">-</phrase><phrase
7443 role="number">1</phrase><phrase role="special">),</phrase> <phrase
7444 role="identifier">alloc</phrase><phrase role="special">)</phrase></code>.
7445 Internal nodes are allocated using <code><phrase role="identifier">alloc</phrase></code>
7446 - C++11-allocators are supported.
7447 </para>
7448 </listitem>
7449 </varlistentry>
7450 <varlistentry>
7451 <term>Throws:</term>
7452 <listitem>
7453 <para>
7454 <code><phrase role="identifier">fiber_error</phrase></code>
7455 </para>
7456 </listitem>
7457 </varlistentry>
7458 <varlistentry>
7459 <term>Error Conditions:</term>
7460 <listitem>
7461 <para>
7462 <emphasis role="bold">invalid_argument</emphasis>: if <code><phrase
7463 role="identifier">lwm</phrase> <phrase role="special">&gt;=</phrase>
7464 <phrase role="identifier">hwm</phrase></code>.
7465 </para>
7466 </listitem>
7467 </varlistentry>
7468 <varlistentry>
7469 <term>Notes:</term>
7470 <listitem>
7471 <para>
7472 Once the number of values in the channel reaches <code><phrase role="identifier">hwm</phrase></code>,
7473 any call to <code><phrase role="identifier">push</phrase><phrase role="special">()</phrase></code>,
7474 <code><phrase role="identifier">push_wait_for</phrase><phrase role="special">()</phrase></code>
7475 or <code><phrase role="identifier">push_wait_until</phrase><phrase
7476 role="special">()</phrase></code> will block until the number of values
7477 in the channel is at most <code><phrase role="identifier">lwm</phrase></code>.
7478 That is, if <code><phrase role="identifier">lwm</phrase> <phrase role="special">&lt;</phrase>
7479 <phrase role="special">(</phrase><phrase role="identifier">hwm</phrase><phrase
7480 role="special">-</phrase><phrase role="number">1</phrase><phrase role="special">)</phrase></code>,
7481 the channel can be in a state in which <code><phrase role="identifier">push</phrase><phrase
7482 role="special">()</phrase></code>, <code><phrase role="identifier">push_wait_for</phrase><phrase
7483 role="special">()</phrase></code> or <code><phrase role="identifier">push_wait_until</phrase><phrase
7484 role="special">()</phrase></code> calls will block (channel is full)
7485 even though the number of values in the channel is less than <code><phrase
7486 role="identifier">hwm</phrase></code>.
7487 </para>
7488 </listitem>
7489 </varlistentry>
7490 <varlistentry>
7491 <term>See also:</term>
7492 <listitem>
7493 <para>
7494 <ulink url="http://en.cppreference.com/w/cpp/concept/Allocator"><code><phrase
7495 role="identifier">Allocator</phrase></code></ulink> concept, <ulink
7496 url="http://en.cppreference.com/w/cpp/memory/allocator"><code><phrase
7497 role="identifier">std</phrase><phrase role="special">::</phrase><phrase
7498 role="identifier">allocator</phrase><phrase role="special">&lt;</phrase>
7499 <phrase role="identifier">T</phrase> <phrase role="special">&gt;</phrase></code></ulink>
7500 </para>
7501 </listitem>
7502 </varlistentry>
7503 </variablelist>
7504 <para>
7505 <bridgehead renderas="sect4" id="bounded_channel_upper_bound_bridgehead">
7506 <phrase id="bounded_channel_upper_bound"/>
7507 <link linkend="bounded_channel_upper_bound">Member
7508 function <code>upper_bound</code>()</link>
7509 </bridgehead>
7510 </para>
7511 <programlisting><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">upper_bound</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
7512 </programlisting>
7513 <variablelist>
7514 <title></title>
7515 <varlistentry>
7516 <term>Returns:</term>
7517 <listitem>
7518 <para>
7519 the high-watermark with which <code><phrase role="special">*</phrase><phrase
7520 role="keyword">this</phrase></code> was constructed.
7521 </para>
7522 </listitem>
7523 </varlistentry>
7524 <varlistentry>
7525 <term>Throws:</term>
7526 <listitem>
7527 <para>
7528 Nothing.
7529 </para>
7530 </listitem>
7531 </varlistentry>
7532 </variablelist>
7533 <para>
7534 <bridgehead renderas="sect4" id="bounded_channel_lower_bound_bridgehead">
7535 <phrase id="bounded_channel_lower_bound"/>
7536 <link linkend="bounded_channel_lower_bound">Member
7537 function <code>lower_bound</code>()</link>
7538 </bridgehead>
7539 </para>
7540 <programlisting><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">lower_bound</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
7541 </programlisting>
7542 <variablelist>
7543 <title></title>
7544 <varlistentry>
7545 <term>Returns:</term>
7546 <listitem>
7547 <para>
7548 the low-watermark with which <code><phrase role="special">*</phrase><phrase
7549 role="keyword">this</phrase></code> was constructed.
7550 </para>
7551 </listitem>
7552 </varlistentry>
7553 <varlistentry>
7554 <term>Throws:</term>
7555 <listitem>
7556 <para>
7557 Nothing.
7558 </para>
7559 </listitem>
7560 </varlistentry>
7561 </variablelist>
7562 <para>
7563 <bridgehead renderas="sect4" id="bounded_channel_close_bridgehead">
7564 <phrase id="bounded_channel_close"/>
7565 <link linkend="bounded_channel_close">Member
7566 function <code>close</code>()</link>
7567 </bridgehead>
7568 </para>
7569 <programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">close</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
7570 </programlisting>
7571 <variablelist>
7572 <title></title>
7573 <varlistentry>
7574 <term>Effects:</term>
7575 <listitem>
7576 <para>
7577 Deactivates the channel. No values can be put after calling <code><phrase
7578 role="keyword">this</phrase><phrase role="special">-&gt;</phrase><phrase
7579 role="identifier">close</phrase><phrase role="special">()</phrase></code>.
7580 Fibers blocked in <code><phrase role="keyword">this</phrase><phrase
7581 role="special">-&gt;</phrase><phrase role="identifier">pop</phrase><phrase
7582 role="special">()</phrase></code>, <code><phrase role="keyword">this</phrase><phrase
7583 role="special">-&gt;</phrase><phrase role="identifier">pop_wait_for</phrase><phrase
7584 role="special">()</phrase></code> or <code><phrase role="keyword">this</phrase><phrase
7585 role="special">-&gt;</phrase><phrase role="identifier">pop_wait_until</phrase><phrase
7586 role="special">()</phrase></code> will return <code><phrase role="identifier">closed</phrase></code>.
7587 Fibers blocked in <code><phrase role="keyword">this</phrase><phrase
7588 role="special">-&gt;</phrase><phrase role="identifier">value_pop</phrase><phrase
7589 role="special">()</phrase></code> will receive an exception.
7590 </para>
7591 </listitem>
7592 </varlistentry>
7593 <varlistentry>
7594 <term>Throws:</term>
7595 <listitem>
7596 <para>
7597 Nothing.
7598 </para>
7599 </listitem>
7600 </varlistentry>
7601 <varlistentry>
7602 <term>Note:</term>
7603 <listitem>
7604 <para>
7605 <code><phrase role="identifier">close</phrase><phrase role="special">()</phrase></code>
7606 is like closing a pipe. It informs waiting consumers that no more values
7607 will arrive.
7608 </para>
7609 </listitem>
7610 </varlistentry>
7611 </variablelist>
7612 <para>
7613 <bridgehead renderas="sect4" id="bounded_channel_push_bridgehead">
7614 <phrase id="bounded_channel_push"/>
7615 <link linkend="bounded_channel_push">Member
7616 function <code>push</code>()</link>
7617 </bridgehead>
7618 </para>
7619 <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>
7620 <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>
7621 </programlisting>
7622 <variablelist>
7623 <title></title>
7624 <varlistentry>
7625 <term>Effects:</term>
7626 <listitem>
7627 <para>
7628 If channel is closed, returns <code><phrase role="identifier">closed</phrase></code>.
7629 If channel is not full, enqueues the value in the channel, wakes up
7630 a fiber blocked on <code><phrase role="keyword">this</phrase><phrase
7631 role="special">-&gt;</phrase><phrase role="identifier">pop</phrase><phrase
7632 role="special">()</phrase></code>, <code><phrase role="keyword">this</phrase><phrase
7633 role="special">-&gt;</phrase><phrase role="identifier">value_pop</phrase><phrase
7634 role="special">()</phrase></code>, <code><phrase role="keyword">this</phrase><phrase
7635 role="special">-&gt;</phrase><phrase role="identifier">pop_wait_for</phrase><phrase
7636 role="special">()</phrase></code> or <code><phrase role="keyword">this</phrase><phrase
7637 role="special">-&gt;</phrase><phrase role="identifier">pop_wait_until</phrase><phrase
7638 role="special">()</phrase></code> and returns <code><phrase role="identifier">success</phrase></code>.
7639 Otherwise the calling fiber is suspended until the number of values
7640 in the channel drops to <code><phrase role="identifier">lwm</phrase></code>
7641 (return value <code><phrase role="identifier">success</phrase></code>)or
7642 the channel is <code><phrase role="identifier">close</phrase><phrase
7643 role="special">()</phrase></code>d (return value <code><phrase role="identifier">closed</phrase></code>).
7644 </para>
7645 </listitem>
7646 </varlistentry>
7647 <varlistentry>
7648 <term>Throws:</term>
7649 <listitem>
7650 <para>
7651 exceptions thrown by memory allocation and copying or moving <code><phrase
7652 role="identifier">va</phrase></code>.
7653 </para>
7654 </listitem>
7655 </varlistentry>
7656 </variablelist>
7657 <para>
7658 <bridgehead renderas="sect4" id="bounded_channel_push_wait_for_bridgehead">
7659 <phrase id="bounded_channel_push_wait_for"/>
7660 <link linkend="bounded_channel_push_wait_for">Member
7661 function <code>push_wait_for</code>()</link>
7662 </bridgehead>
7663 </para>
7664 <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>
7665 <phrase role="identifier">channel_op_status</phrase> <phrase role="identifier">push_wait_for</phrase><phrase role="special">(</phrase>
7666 <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>
7667 <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>
7668
7669 <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>
7670 <phrase role="identifier">channel_op_status</phrase> <phrase role="identifier">push_wait_for</phrase><phrase role="special">(</phrase>
7671 <phrase role="identifier">value_type</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="identifier">va</phrase><phrase role="special">,</phrase>
7672 <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>
7673 </programlisting>
7674 <variablelist>
7675 <title></title>
7676 <varlistentry>
7677 <term>Effects:</term>
7678 <listitem>
7679 <para>
7680 Accepts <code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase
7681 role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase
7682 role="identifier">duration</phrase></code> and internally computes
7683 a time_point as (system time + <code><phrase role="identifier">timeout_duration</phrase></code>).
7684 If channel is closed, returns <code><phrase role="identifier">closed</phrase></code>.
7685 If channel is not full, enqueues the value in the channel, wakes up
7686 a fiber blocked on <code><phrase role="keyword">this</phrase><phrase
7687 role="special">-&gt;</phrase><phrase role="identifier">pop</phrase><phrase
7688 role="special">()</phrase></code>, <code><phrase role="keyword">this</phrase><phrase
7689 role="special">-&gt;</phrase><phrase role="identifier">value_pop</phrase><phrase
7690 role="special">()</phrase></code>, <code><phrase role="keyword">this</phrase><phrase
7691 role="special">-&gt;</phrase><phrase role="identifier">pop_wait_for</phrase><phrase
7692 role="special">()</phrase></code> or <code><phrase role="keyword">this</phrase><phrase
7693 role="special">-&gt;</phrase><phrase role="identifier">pop_wait_until</phrase><phrase
7694 role="special">()</phrase></code> and returns <code><phrase role="identifier">success</phrase></code>.
7695 Otherwise the calling fiber is suspended until the number of values
7696 in the channel drops to <code><phrase role="identifier">lwm</phrase></code>
7697 (return value <code><phrase role="identifier">success</phrase></code>),
7698 the channel is <code><phrase role="identifier">close</phrase><phrase
7699 role="special">()</phrase></code>d (return value <code><phrase role="identifier">closed</phrase></code>),
7700 or the system time reaches the computed time_point (return value <code><phrase
7701 role="identifier">timeout</phrase></code>).
7702 </para>
7703 </listitem>
7704 </varlistentry>
7705 <varlistentry>
7706 <term>Throws:</term>
7707 <listitem>
7708 <para>
7709 exceptions thrown by memory allocation and copying or moving <code><phrase
7710 role="identifier">va</phrase></code> or timeout-related exceptions.
7711 </para>
7712 </listitem>
7713 </varlistentry>
7714 </variablelist>
7715 <para>
7716 <bridgehead renderas="sect4" id="bounded_channel_push_wait_until_bridgehead">
7717 <phrase id="bounded_channel_push_wait_until"/>
7718 <link linkend="bounded_channel_push_wait_until">Member
7719 function <code>push_wait_until</code>()</link>
7720 </bridgehead>
7721 </para>
7722 <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>
7723 <phrase role="identifier">channel_op_status</phrase> <phrase role="identifier">push_wait_until</phrase><phrase role="special">(</phrase>
7724 <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>
7725 <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>
7726
7727 <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>
7728 <phrase role="identifier">channel_op_status</phrase> <phrase role="identifier">push_wait_until</phrase><phrase role="special">(</phrase>
7729 <phrase role="identifier">value_type</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="identifier">va</phrase><phrase role="special">,</phrase>
7730 <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>
7731 </programlisting>
7732 <variablelist>
7733 <title></title>
7734 <varlistentry>
7735 <term>Effects:</term>
7736 <listitem>
7737 <para>
7738 Accepts an absolute <code><phrase role="identifier">timeout_time</phrase></code>
7739 in any supported time_point type. If channel is closed, returns <code><phrase
7740 role="identifier">closed</phrase></code>. If channel is not full, enqueues
7741 the value in the channel, wakes up a fiber blocked on <code><phrase
7742 role="keyword">this</phrase><phrase role="special">-&gt;</phrase><phrase
7743 role="identifier">pop</phrase><phrase role="special">()</phrase></code>,
7744 <code><phrase role="keyword">this</phrase><phrase role="special">-&gt;</phrase><phrase
7745 role="identifier">value_pop</phrase><phrase role="special">()</phrase></code>,
7746 <code><phrase role="keyword">this</phrase><phrase role="special">-&gt;</phrase><phrase
7747 role="identifier">pop_wait_for</phrase><phrase role="special">()</phrase></code>
7748 or <code><phrase role="keyword">this</phrase><phrase role="special">-&gt;</phrase><phrase
7749 role="identifier">pop_wait_until</phrase><phrase role="special">()</phrase></code>
7750 and returns <code><phrase role="identifier">success</phrase></code>.
7751 Otherwise the calling fiber is suspended until the number of values
7752 in the channel drops to <code><phrase role="identifier">lwm</phrase></code>
7753 (return value <code><phrase role="identifier">success</phrase></code>),
7754 the channel is <code><phrase role="identifier">close</phrase><phrase
7755 role="special">()</phrase></code>d (return value <code><phrase role="identifier">closed</phrase></code>),
7756 or the system time reaches the passed time_point (return value <code><phrase
7757 role="identifier">timeout</phrase></code>).
7758 </para>
7759 </listitem>
7760 </varlistentry>
7761 <varlistentry>
7762 <term>Throws:</term>
7763 <listitem>
7764 <para>
7765 exceptions thrown by memory allocation and copying or moving <code><phrase
7766 role="identifier">va</phrase></code> or timeout-related exceptions.
7767 </para>
7768 </listitem>
7769 </varlistentry>
7770 </variablelist>
7771 <para>
7772 <bridgehead renderas="sect4" id="bounded_channel_try_push_bridgehead">
7773 <phrase id="bounded_channel_try_push"/>
7774 <link linkend="bounded_channel_try_push">Member
7775 function <code>try_push</code>()</link>
7776 </bridgehead>
7777 </para>
7778 <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>
7779 <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>
7780 </programlisting>
7781 <variablelist>
7782 <title></title>
7783 <varlistentry>
7784 <term>Effects:</term>
7785 <listitem>
7786 <para>
7787 If channel is full, returns <code><phrase role="identifier">full</phrase></code>.
7788 If channel is closed, returns <code><phrase role="identifier">closed</phrase></code>.
7789 Otherwise enqueues the value in the channel, wakes up a fiber blocked
7790 on <code><phrase role="keyword">this</phrase><phrase role="special">-&gt;</phrase><phrase
7791 role="identifier">pop</phrase><phrase role="special">()</phrase></code>,
7792 <code><phrase role="keyword">this</phrase><phrase role="special">-&gt;</phrase><phrase
7793 role="identifier">value_pop</phrase><phrase role="special">()</phrase></code>,
7794 <code><phrase role="keyword">this</phrase><phrase role="special">-&gt;</phrase><phrase
7795 role="identifier">pop_wait_for</phrase><phrase role="special">()</phrase></code>
7796 or <code><phrase role="keyword">this</phrase><phrase role="special">-&gt;</phrase><phrase
7797 role="identifier">pop_wait_until</phrase><phrase role="special">()</phrase></code>
7798 and returns <code><phrase role="identifier">success</phrase></code>.
7799 </para>
7800 </listitem>
7801 </varlistentry>
7802 <varlistentry>
7803 <term>Throws:</term>
7804 <listitem>
7805 <para>
7806 Exceptions thrown by memory allocation and copying or moving <code><phrase
7807 role="identifier">va</phrase></code>.
7808 </para>
7809 </listitem>
7810 </varlistentry>
7811 </variablelist>
7812 <para>
7813 <bridgehead renderas="sect4" id="bounded_channel_pop_bridgehead">
7814 <phrase id="bounded_channel_pop"/>
7815 <link linkend="bounded_channel_pop">Member
7816 function <code>pop</code>()</link>
7817 </bridgehead>
7818 </para>
7819 <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>
7820 </programlisting>
7821 <variablelist>
7822 <title></title>
7823 <varlistentry>
7824 <term>Effects:</term>
7825 <listitem>
7826 <para>
7827 Dequeues a value from the channel. If the channel is empty, the fiber
7828 gets suspended until at least one new item is <code><phrase role="identifier">push</phrase><phrase
7829 role="special">()</phrase></code>ed (return value <code><phrase role="identifier">success</phrase></code>
7830 and <code><phrase role="identifier">va</phrase></code> contains dequeued
7831 value) or the channel gets <code><phrase role="identifier">close</phrase><phrase
7832 role="special">()</phrase></code>d (return value <code><phrase role="identifier">closed</phrase></code>).
7833 Once the number of items remaining in the channel drops to <code><phrase
7834 role="identifier">lwm</phrase></code>, any fibers blocked on <code><phrase
7835 role="identifier">push</phrase><phrase role="special">()</phrase></code>,
7836 <code><phrase role="identifier">push_wait_for</phrase><phrase role="special">()</phrase></code>
7837 or <code><phrase role="identifier">push_wait_until</phrase><phrase
7838 role="special">()</phrase></code> may resume.
7839 </para>
7840 </listitem>
7841 </varlistentry>
7842 <varlistentry>
7843 <term>Throws:</term>
7844 <listitem>
7845 <para>
7846 Nothing
7847 </para>
7848 </listitem>
7849 </varlistentry>
7850 </variablelist>
7851 <para>
7852 <bridgehead renderas="sect4" id="bounded_channel_value_pop_bridgehead">
7853 <phrase id="bounded_channel_value_pop"/>
7854 <link linkend="bounded_channel_value_pop">Member
7855 function <code>value_pop</code>()</link>
7856 </bridgehead>
7857 </para>
7858 <programlisting><phrase role="identifier">value_type</phrase> <phrase role="identifier">value_pop</phrase><phrase role="special">();</phrase>
7859 </programlisting>
7860 <variablelist>
7861 <title></title>
7862 <varlistentry>
7863 <term>Effects:</term>
7864 <listitem>
7865 <para>
7866 Dequeues a value from the channel. If the channel is empty, the fiber
7867 gets suspended until at least one new item is <code><phrase role="identifier">push</phrase><phrase
7868 role="special">()</phrase></code>ed or the channel gets <code><phrase
7869 role="identifier">close</phrase><phrase role="special">()</phrase></code>d
7870 (which throws an exception). Once the number of items remaining in
7871 the channel drops to <code><phrase role="identifier">lwm</phrase></code>,
7872 any fibers blocked on <code><phrase role="identifier">push</phrase><phrase
7873 role="special">()</phrase></code>, <code><phrase role="identifier">push_wait_for</phrase><phrase
7874 role="special">()</phrase></code> or <code><phrase role="identifier">push_wait_until</phrase><phrase
7875 role="special">()</phrase></code> may resume.
7876 </para>
7877 </listitem>
7878 </varlistentry>
7879 <varlistentry>
7880 <term>Throws:</term>
7881 <listitem>
7882 <para>
7883 <code><phrase role="identifier">fiber_error</phrase></code> if <code><phrase
7884 role="special">*</phrase><phrase role="keyword">this</phrase></code>
7885 is closed
7886 </para>
7887 </listitem>
7888 </varlistentry>
7889 <varlistentry>
7890 <term>Error conditions:</term>
7891 <listitem>
7892 <para>
7893 <code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase
7894 role="identifier">errc</phrase><phrase role="special">::</phrase><phrase
7895 role="identifier">operation_not_permitted</phrase></code>
7896 </para>
7897 </listitem>
7898 </varlistentry>
7899 </variablelist>
7900 <para>
7901 <bridgehead renderas="sect4" id="bounded_channel_try_pop_bridgehead">
7902 <phrase id="bounded_channel_try_pop"/>
7903 <link linkend="bounded_channel_try_pop">Member
7904 function <code>try_pop</code>()</link>
7905 </bridgehead>
7906 </para>
7907 <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>
7908 </programlisting>
7909 <variablelist>
7910 <title></title>
7911 <varlistentry>
7912 <term>Effects:</term>
7913 <listitem>
7914 <para>
7915 If channel is empty, returns <code><phrase role="identifier">empty</phrase></code>.
7916 If channel is closed, returns <code><phrase role="identifier">closed</phrase></code>.
7917 Otherwise it returns <code><phrase role="identifier">success</phrase></code>
7918 and <code><phrase role="identifier">va</phrase></code> contains the
7919 dequeued value. Once the number of items remaining in the channel drops
7920 to <code><phrase role="identifier">lwm</phrase></code>, any fibers
7921 blocked on <code><phrase role="identifier">push</phrase><phrase role="special">()</phrase></code>,
7922 <code><phrase role="identifier">push_wait_for</phrase><phrase role="special">()</phrase></code>
7923 or <code><phrase role="identifier">push_wait_until</phrase><phrase
7924 role="special">()</phrase></code> may resume.
7925 </para>
7926 </listitem>
7927 </varlistentry>
7928 <varlistentry>
7929 <term>Throws:</term>
7930 <listitem>
7931 <para>
7932 Exceptions thrown by copy- or move-operations.
7933 </para>
7934 </listitem>
7935 </varlistentry>
7936 </variablelist>
7937 <para>
7938 <bridgehead renderas="sect4" id="bounded_channel_pop_wait_for_bridgehead">
7939 <phrase id="bounded_channel_pop_wait_for"/>
7940 <link linkend="bounded_channel_pop_wait_for">Member
7941 function <code>pop_wait_for</code>()</link>
7942 </bridgehead>
7943 </para>
7944 <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>
7945 <phrase role="identifier">channel_op_status</phrase> <phrase role="identifier">pop_wait_for</phrase><phrase role="special">(</phrase>
7946 <phrase role="identifier">value_type</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">va</phrase><phrase role="special">,</phrase>
7947 <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>
7948 </programlisting>
7949 <variablelist>
7950 <title></title>
7951 <varlistentry>
7952 <term>Effects:</term>
7953 <listitem>
7954 <para>
7955 Accepts <code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase
7956 role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase
7957 role="identifier">duration</phrase></code> and internally computes
7958 a timeout time as (system time + <code><phrase role="identifier">timeout_duration</phrase></code>).
7959 If channel is not empty, immediately dequeues a value from the channel.
7960 Otherwise the fiber gets suspended until at least one new item is
7961 <code><phrase role="identifier">push</phrase><phrase role="special">()</phrase></code>ed
7962 (return value <code><phrase role="identifier">success</phrase></code>
7963 and <code><phrase role="identifier">va</phrase></code> contains dequeued
7964 value), or the channel gets <code><phrase role="identifier">close</phrase><phrase
7965 role="special">()</phrase></code>d (return value <code><phrase role="identifier">closed</phrase></code>),
7966 or the system time reaches the computed timeout time (return value
7967 <code><phrase role="identifier">timeout</phrase></code>). Once the
7968 number of items remaining in the channel drops to <code><phrase role="identifier">lwm</phrase></code>,
7969 any fibers blocked on <code><phrase role="identifier">push</phrase><phrase
7970 role="special">()</phrase></code>, <code><phrase role="identifier">push_wait_for</phrase><phrase
7971 role="special">()</phrase></code> or <code><phrase role="identifier">push_wait_until</phrase><phrase
7972 role="special">()</phrase></code> may resume.
7973 </para>
7974 </listitem>
7975 </varlistentry>
7976 <varlistentry>
7977 <term>Throws:</term>
7978 <listitem>
7979 <para>
7980 timeout-related exceptions.
7981 </para>
7982 </listitem>
7983 </varlistentry>
7984 </variablelist>
7985 <para>
7986 <bridgehead renderas="sect4" id="bounded_channel_pop_wait_until_bridgehead">
7987 <phrase id="bounded_channel_pop_wait_until"/>
7988 <link linkend="bounded_channel_pop_wait_until">Member
7989 function <code>pop_wait_until</code>()</link>
7990 </bridgehead>
7991 </para>
7992 <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>
7993 <phrase role="identifier">channel_op_status</phrase> <phrase role="identifier">pop_wait_until</phrase><phrase role="special">(</phrase>
7994 <phrase role="identifier">value_type</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">va</phrase><phrase role="special">,</phrase>
7995 <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>
7996 </programlisting>
7997 <variablelist>
7998 <title></title>
7999 <varlistentry>
8000 <term>Effects:</term>
8001 <listitem>
8002 <para>
8003 Accepts a <code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase
8004 role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase
8005 role="identifier">time_point</phrase><phrase role="special">&lt;</phrase>
8006 <phrase role="identifier">Clock</phrase><phrase role="special">,</phrase>
8007 <phrase role="identifier">Duration</phrase> <phrase role="special">&gt;</phrase></code>.
8008 If channel is not empty, immediately dequeues a value from the channel.
8009 Otherwise the fiber gets suspended until at least one new item is
8010 <code><phrase role="identifier">push</phrase><phrase role="special">()</phrase></code>ed
8011 (return value <code><phrase role="identifier">success</phrase></code>
8012 and <code><phrase role="identifier">va</phrase></code> contains dequeued
8013 value), or the channel gets <code><phrase role="identifier">close</phrase><phrase
8014 role="special">()</phrase></code>d (return value <code><phrase role="identifier">closed</phrase></code>),
8015 or the system time reaches the passed <code><phrase role="identifier">time_point</phrase></code>
8016 (return value <code><phrase role="identifier">timeout</phrase></code>).
8017 Once the number of items remaining in the channel drops to <code><phrase
8018 role="identifier">lwm</phrase></code>, any fibers blocked on <code><phrase
8019 role="identifier">push</phrase><phrase role="special">()</phrase></code>,
8020 <code><phrase role="identifier">push_wait_for</phrase><phrase role="special">()</phrase></code>
8021 or <code><phrase role="identifier">push_wait_until</phrase><phrase
8022 role="special">()</phrase></code> may resume.
8023 </para>
8024 </listitem>
8025 </varlistentry>
8026 <varlistentry>
8027 <term>Throws:</term>
8028 <listitem>
8029 <para>
8030 timeout-related exceptions.
8031 </para>
8032 </listitem>
8033 </varlistentry>
8034 </variablelist>
8035 </section>
8036 <section id="fiber.synchronization.futures">
8037 <title><link linkend="fiber.synchronization.futures">Futures</link></title>
8038 <bridgehead renderas="sect4" id="fiber.synchronization.futures.h0">
8039 <phrase id="fiber.synchronization.futures.overview"/><link linkend="fiber.synchronization.futures.overview">Overview</link>
8040 </bridgehead>
8041 <para>
8042 The futures library provides a means of handling asynchronous future values,
8043 whether those values are generated by another fiber, or on a single fiber
8044 in response to external stimuli, or on-demand.
8045 </para>
8046 <para>
8047 This is done through the provision of four class templates: <link linkend="class_future"><code>future&lt;&gt;</code></link> and
8048 <link linkend="class_shared_future"><code>shared_future&lt;&gt;</code></link> which are used to retrieve the asynchronous
8049 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
8050 are used to generate the asynchronous results.
8051 </para>
8052 <para>
8053 An instance of <link linkend="class_future"><code>future&lt;&gt;</code></link> holds the one and only reference
8054 to a result. Ownership can be transferred between instances using the move
8055 constructor or move-assignment operator, but at most one instance holds a
8056 reference to a given asynchronous result. When the result is ready, it is
8057 returned from <link linkend="future_get"><code>future::get()</code></link> by rvalue-reference to allow the result
8058 to be moved or copied as appropriate for the type.
8059 </para>
8060 <para>
8061 On the other hand, many instances of <link linkend="class_shared_future"><code>shared_future&lt;&gt;</code></link> may
8062 reference the same result. Instances can be freely copied and assigned, and
8063 <link linkend="shared_future_get"><code>shared_future::get()</code></link>
8064 returns a <code><phrase role="keyword">const</phrase></code>
8065 reference so that multiple calls to <link linkend="shared_future_get"><code>shared_future::get()</code></link>
8066 are
8067 safe. You can move an instance of <link linkend="class_future"><code>future&lt;&gt;</code></link> into an instance
8068 of <link linkend="class_shared_future"><code>shared_future&lt;&gt;</code></link>, thus transferring ownership
8069 of the associated asynchronous result, but not vice-versa.
8070 </para>
8071 <para>
8072 <link linkend="fibers_async"><code>fibers::async()</code></link> is a simple way of running asynchronous tasks.
8073 A call to <code><phrase role="identifier">async</phrase><phrase role="special">()</phrase></code>
8074 spawns a fiber and returns a <link linkend="class_future"><code>future&lt;&gt;</code></link> that will deliver
8075 the result of the fiber function.
8076 </para>
8077 <bridgehead renderas="sect4" id="fiber.synchronization.futures.h1">
8078 <phrase id="fiber.synchronization.futures.creating_asynchronous_values"/><link
8079 linkend="fiber.synchronization.futures.creating_asynchronous_values">Creating
8080 asynchronous values</link>
8081 </bridgehead>
8082 <para>
8083 You can set the value in a future with either a <link linkend="class_promise"><code>promise&lt;&gt;</code></link> or
8084 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
8085 a callable object with <code><phrase role="keyword">void</phrase></code>
8086 return that wraps a function or callable object returning the specified type.
8087 When the <link linkend="class_packaged_task"><code>packaged_task&lt;&gt;</code></link> is invoked, it invokes the
8088 contained function in turn, and populates a future with the contained function's
8089 return value. This is an answer to the perennial question: <quote>How do
8090 I return a value from a fiber?</quote> Package the function you wish to run
8091 as a <link linkend="class_packaged_task"><code>packaged_task&lt;&gt;</code></link> and pass the packaged task to
8092 the fiber constructor. The future retrieved from the packaged task can then
8093 be used to obtain the return value. If the function throws an exception,
8094 that is stored in the future in place of the return value.
8095 </para>
8096 <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>
8097 <phrase role="keyword">return</phrase> <phrase role="number">42</phrase><phrase role="special">;</phrase>
8098 <phrase role="special">}</phrase>
8099
8100 <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>
8101 <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>
8102 <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>
8103
8104 <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>
8105
8106 <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>
8107 <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>
8108 <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>
8109 <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>
8110 </programlisting>
8111 <para>
8112 A <link linkend="class_promise"><code>promise&lt;&gt;</code></link> is a bit more low level: it just provides explicit
8113 functions to store a value or an exception in the associated future. A promise
8114 can therefore be used where the value might come from more than one possible
8115 source.
8116 </para>
8117 <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>
8118 <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>
8119 <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>
8120
8121 <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>
8122
8123 <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>
8124 <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>
8125 <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>
8126 <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>
8127 </programlisting>
8128 <section id="fiber.synchronization.futures.future">
8129 <title><link linkend="fiber.synchronization.futures.future">Future</link></title>
8130 <para>
8131 A future provides a mechanism to access the result of an asynchronous operation.
8132 </para>
8133 <anchor id="shared_state"/>
8134 <bridgehead renderas="sect5" id="fiber.synchronization.futures.future.h0">
8135 <phrase id="fiber.synchronization.futures.future.shared_state"/><link linkend="fiber.synchronization.futures.future.shared_state">shared
8136 state</link>
8137 </bridgehead>
8138 <para>
8139 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
8140 an unspecified object called their <emphasis>shared state</emphasis>. The
8141 shared state is what will actually hold the async result (or the exception).
8142 </para>
8143 <para>
8144 The shared state is instantiated along with the <link linkend="class_promise"><code>promise&lt;&gt;</code></link>.
8145 </para>
8146 <para>
8147 Aside from its originating <code><phrase role="identifier">promise</phrase><phrase
8148 role="special">&lt;&gt;</phrase></code>, a <link linkend="class_future"><code>future&lt;&gt;</code></link> holds
8149 a unique reference to a particular shared state. However, multiple <link linkend="class_shared_future"><code>shared_future&lt;&gt;</code></link> instances
8150 can reference the same underlying shared state.
8151 </para>
8152 <para>
8153 As <link linkend="class_packaged_task"><code>packaged_task&lt;&gt;</code></link> and <link linkend="fibers_async"><code>fibers::async()</code></link> are
8154 implemented using <link linkend="class_promise"><code>promise&lt;&gt;</code></link>, discussions of shared state
8155 apply to them as well.
8156 </para>
8157 <anchor id="class_future_status"/>
8158 <bridgehead renderas="sect5" id="fiber.synchronization.futures.future.h1">
8159 <phrase id="fiber.synchronization.futures.future.enumeration__code__phrase_role__identifier__future_status__phrase___code_"/><link
8160 linkend="fiber.synchronization.futures.future.enumeration__code__phrase_role__identifier__future_status__phrase___code_">Enumeration
8161 <code><phrase role="identifier">future_status</phrase></code></link>
8162 </bridgehead>
8163 <para>
8164 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>)
8165 return the state of the future.
8166 </para>
8167 <programlisting><phrase role="keyword">enum</phrase> <phrase role="keyword">class</phrase> <phrase role="identifier">future_status</phrase> <phrase role="special">{</phrase>
8168 <phrase role="identifier">ready</phrase><phrase role="special">,</phrase>
8169 <phrase role="identifier">timeout</phrase><phrase role="special">,</phrase>
8170 <phrase role="identifier">deferred</phrase> <phrase role="comment">// not supported yet</phrase>
8171 <phrase role="special">};</phrase>
8172 </programlisting>
8173 <bridgehead renderas="sect5" id="fiber.synchronization.futures.future.h2">
8174 <phrase id="fiber.synchronization.futures.future._code__phrase_role__identifier__ready__phrase___code_"/><link
8175 linkend="fiber.synchronization.futures.future._code__phrase_role__identifier__ready__phrase___code_"><code><phrase
8176 role="identifier">ready</phrase></code></link>
8177 </bridgehead>
8178 <variablelist>
8179 <title></title>
8180 <varlistentry>
8181 <term>Effects:</term>
8182 <listitem>
8183 <para>
8184 The <link linkend="shared_state">shared state</link> is ready.
8185 </para>
8186 </listitem>
8187 </varlistentry>
8188 </variablelist>
8189 <bridgehead renderas="sect5" id="fiber.synchronization.futures.future.h3">
8190 <phrase id="fiber.synchronization.futures.future._code__phrase_role__identifier__timeout__phrase___code_"/><link
8191 linkend="fiber.synchronization.futures.future._code__phrase_role__identifier__timeout__phrase___code_"><code><phrase
8192 role="identifier">timeout</phrase></code></link>
8193 </bridgehead>
8194 <variablelist>
8195 <title></title>
8196 <varlistentry>
8197 <term>Effects:</term>
8198 <listitem>
8199 <para>
8200 The <link linkend="shared_state">shared state</link> did not become
8201 ready before timeout has passed.
8202 </para>
8203 </listitem>
8204 </varlistentry>
8205 </variablelist>
8206 <note>
8207 <para>
8208 Deferred futures are not supported.
8209 </para>
8210 </note>
8211 <para>
8212 <bridgehead renderas="sect4" id="class_future_bridgehead">
8213 <phrase id="class_future"/>
8214 <link linkend="class_future">Template <code>future&lt;&gt;</code></link>
8215 </bridgehead>
8216 </para>
8217 <para>
8218 A <link linkend="class_future"><code>future&lt;&gt;</code></link> contains a <link linkend="shared_state">shared
8219 state</link> which is not shared with any other future.
8220 </para>
8221 <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>
8222
8223 <phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase>
8224 <phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase>
8225
8226 <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>
8227 <phrase role="keyword">class</phrase> <phrase role="identifier">future</phrase> <phrase role="special">{</phrase>
8228 <phrase role="keyword">public</phrase><phrase role="special">:</phrase>
8229 <phrase role="identifier">future</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
8230
8231 <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>
8232
8233 <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>
8234
8235 <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>
8236
8237 <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>
8238
8239 <phrase role="special">~</phrase><phrase role="identifier">future</phrase><phrase role="special">();</phrase>
8240
8241 <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>
8242
8243 <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>
8244
8245 <phrase role="identifier">R</phrase> <phrase role="identifier">get</phrase><phrase role="special">();</phrase> <phrase role="comment">// member only of generic future template</phrase>
8246 <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>
8247 <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>
8248
8249 <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>
8250
8251 <phrase role="keyword">void</phrase> <phrase role="identifier">wait</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
8252
8253 <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>
8254 <phrase role="identifier">future_status</phrase> <phrase role="identifier">wait_for</phrase><phrase role="special">(</phrase>
8255 <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>
8256
8257 <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>
8258 <phrase role="identifier">future_status</phrase> <phrase role="identifier">wait_until</phrase><phrase role="special">(</phrase>
8259 <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>
8260 <phrase role="special">};</phrase>
8261
8262 <phrase role="special">}}</phrase>
8263 </programlisting>
8264 <bridgehead renderas="sect5" id="fiber.synchronization.futures.future.h4">
8265 <phrase id="fiber.synchronization.futures.future.default_constructor"/><link
8266 linkend="fiber.synchronization.futures.future.default_constructor">Default
8267 constructor</link>
8268 </bridgehead>
8269 <programlisting><phrase role="identifier">future</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
8270 </programlisting>
8271 <variablelist>
8272 <title></title>
8273 <varlistentry>
8274 <term>Effects:</term>
8275 <listitem>
8276 <para>
8277 Creates a future with no <link linkend="shared_state">shared state</link>.
8278 After construction <code><phrase role="keyword">false</phrase> <phrase
8279 role="special">==</phrase> <phrase role="identifier">valid</phrase><phrase
8280 role="special">()</phrase></code>.
8281 </para>
8282 </listitem>
8283 </varlistentry>
8284 <varlistentry>
8285 <term>Throws:</term>
8286 <listitem>
8287 <para>
8288 Nothing.
8289 </para>
8290 </listitem>
8291 </varlistentry>
8292 </variablelist>
8293 <bridgehead renderas="sect5" id="fiber.synchronization.futures.future.h5">
8294 <phrase id="fiber.synchronization.futures.future.move_constructor"/><link
8295 linkend="fiber.synchronization.futures.future.move_constructor">Move constructor</link>
8296 </bridgehead>
8297 <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>
8298 </programlisting>
8299 <variablelist>
8300 <title></title>
8301 <varlistentry>
8302 <term>Effects:</term>
8303 <listitem>
8304 <para>
8305 Constructs a future with the <link linkend="shared_state">shared
8306 state</link> of other. After construction <code><phrase role="keyword">false</phrase>
8307 <phrase role="special">==</phrase> <phrase role="identifier">other</phrase><phrase
8308 role="special">.</phrase><phrase role="identifier">valid</phrase><phrase
8309 role="special">()</phrase></code>.
8310 </para>
8311 </listitem>
8312 </varlistentry>
8313 <varlistentry>
8314 <term>Throws:</term>
8315 <listitem>
8316 <para>
8317 Nothing.
8318 </para>
8319 </listitem>
8320 </varlistentry>
8321 </variablelist>
8322 <bridgehead renderas="sect5" id="fiber.synchronization.futures.future.h6">
8323 <phrase id="fiber.synchronization.futures.future.destructor"/><link linkend="fiber.synchronization.futures.future.destructor">Destructor</link>
8324 </bridgehead>
8325 <programlisting><phrase role="special">~</phrase><phrase role="identifier">future</phrase><phrase role="special">();</phrase>
8326 </programlisting>
8327 <variablelist>
8328 <title></title>
8329 <varlistentry>
8330 <term>Effects:</term>
8331 <listitem>
8332 <para>
8333 Destroys the future; ownership is abandoned.
8334 </para>
8335 </listitem>
8336 </varlistentry>
8337 <varlistentry>
8338 <term>Note:</term>
8339 <listitem>
8340 <para>
8341 <code>~future()</code> does <emphasis>not</emphasis> block the calling fiber.
8342 </para>
8343 </listitem>
8344 </varlistentry>
8345 </variablelist>
8346 <para>
8347 Consider a sequence such as:
8348 </para>
8349 <orderedlist>
8350 <listitem>
8351 <simpara>
8352 instantiate <link linkend="class_promise"><code>promise&lt;&gt;</code></link>
8353 </simpara>
8354 </listitem>
8355 <listitem>
8356 <simpara>
8357 obtain its <code><phrase role="identifier">future</phrase><phrase role="special">&lt;&gt;</phrase></code>
8358 via <link linkend="promise_get_future"><code>promise::get_future()</code></link>
8359 </simpara>
8360 </listitem>
8361 <listitem>
8362 <simpara>
8363 launch <link linkend="class_fiber"><code>fiber</code></link>, capturing <code><phrase role="identifier">promise</phrase><phrase
8364 role="special">&lt;&gt;</phrase></code>
8365 </simpara>
8366 </listitem>
8367 <listitem>
8368 <simpara>
8369 destroy <code><phrase role="identifier">future</phrase><phrase role="special">&lt;&gt;</phrase></code>
8370 </simpara>
8371 </listitem>
8372 <listitem>
8373 <simpara>
8374 call <link linkend="promise_set_value"><code>promise::set_value()</code></link>
8375 </simpara>
8376 </listitem>
8377 </orderedlist>
8378 <para>
8379 The final <code><phrase role="identifier">set_value</phrase><phrase role="special">()</phrase></code>
8380 call succeeds, but the value is silently discarded: no additional <code><phrase
8381 role="identifier">future</phrase><phrase role="special">&lt;&gt;</phrase></code>
8382 can be obtained from that <code><phrase role="identifier">promise</phrase><phrase
8383 role="special">&lt;&gt;</phrase></code>.
8384 </para>
8385 <para>
8386 <bridgehead renderas="sect4" id="future_operator_assign_bridgehead">
8387 <phrase id="future_operator_assign"/>
8388 <link linkend="future_operator_assign">Member
8389 function <code>operator=</code>()</link>
8390 </bridgehead>
8391 </para>
8392 <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>
8393 </programlisting>
8394 <variablelist>
8395 <title></title>
8396 <varlistentry>
8397 <term>Effects:</term>
8398 <listitem>
8399 <para>
8400 Moves the <link linkend="shared_state">shared state</link> of other
8401 to <code><phrase role="keyword">this</phrase></code>. After the assignment,
8402 <code><phrase role="keyword">false</phrase> <phrase role="special">==</phrase>
8403 <phrase role="identifier">other</phrase><phrase role="special">.</phrase><phrase
8404 role="identifier">valid</phrase><phrase role="special">()</phrase></code>.
8405 </para>
8406 </listitem>
8407 </varlistentry>
8408 <varlistentry>
8409 <term>Throws:</term>
8410 <listitem>
8411 <para>
8412 Nothing.
8413 </para>
8414 </listitem>
8415 </varlistentry>
8416 </variablelist>
8417 <para>
8418 <bridgehead renderas="sect4" id="future_valid_bridgehead">
8419 <phrase id="future_valid"/>
8420 <link linkend="future_valid">Member function <code>valid</code>()</link>
8421 </bridgehead>
8422 </para>
8423 <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>
8424 </programlisting>
8425 <variablelist>
8426 <title></title>
8427 <varlistentry>
8428 <term>Effects:</term>
8429 <listitem>
8430 <para>
8431 Returns <code><phrase role="keyword">true</phrase></code> if future
8432 contains a <link linkend="shared_state">shared state</link>.
8433 </para>
8434 </listitem>
8435 </varlistentry>
8436 <varlistentry>
8437 <term>Throws:</term>
8438 <listitem>
8439 <para>
8440 Nothing.
8441 </para>
8442 </listitem>
8443 </varlistentry>
8444 </variablelist>
8445 <para>
8446 <bridgehead renderas="sect4" id="future_share_bridgehead">
8447 <phrase id="future_share"/>
8448 <link linkend="future_share">Member function <code>share</code>()</link>
8449 </bridgehead>
8450 </para>
8451 <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>
8452 </programlisting>
8453 <variablelist>
8454 <title></title>
8455 <varlistentry>
8456 <term>Effects:</term>
8457 <listitem>
8458 <para>
8459 Move the state to a <link linkend="class_shared_future"><code>shared_future&lt;&gt;</code></link>.
8460 </para>
8461 </listitem>
8462 </varlistentry>
8463 <varlistentry>
8464 <term>Returns:</term>
8465 <listitem>
8466 <para>
8467 a <link linkend="class_shared_future"><code>shared_future&lt;&gt;</code></link> containing the <link linkend="shared_state">shared
8468 state</link> formerly belonging to <code><phrase role="special">*</phrase><phrase
8469 role="keyword">this</phrase></code>.
8470 </para>
8471 </listitem>
8472 </varlistentry>
8473 <varlistentry>
8474 <term>Postcondition:</term>
8475 <listitem>
8476 <para>
8477 <code><phrase role="keyword">false</phrase> <phrase role="special">==</phrase>
8478 <phrase role="identifier">valid</phrase><phrase role="special">()</phrase></code>
8479 </para>
8480 </listitem>
8481 </varlistentry>
8482 <varlistentry>
8483 <term>Throws:</term>
8484 <listitem>
8485 <para>
8486 <code><phrase role="identifier">future_error</phrase></code> with
8487 error condition <code><phrase role="identifier">future_errc</phrase><phrase
8488 role="special">::</phrase><phrase role="identifier">no_state</phrase></code>.
8489 </para>
8490 </listitem>
8491 </varlistentry>
8492 </variablelist>
8493 <para>
8494 <bridgehead renderas="sect4" id="future_get_bridgehead">
8495 <phrase id="future_get"/>
8496 <link linkend="future_get">Member function <code>get</code>()</link>
8497 </bridgehead>
8498 </para>
8499 <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>
8500 <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>
8501 <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>
8502 </programlisting>
8503 <variablelist>
8504 <title></title>
8505 <varlistentry>
8506 <term>Precondition:</term>
8507 <listitem>
8508 <para>
8509 <code><phrase role="keyword">true</phrase> <phrase role="special">==</phrase>
8510 <phrase role="identifier">valid</phrase><phrase role="special">()</phrase></code>
8511 </para>
8512 </listitem>
8513 </varlistentry>
8514 <varlistentry>
8515 <term>Returns:</term>
8516 <listitem>
8517 <para>
8518 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
8519 called. If <link linkend="promise_set_value"><code>promise::set_value()</code></link> is called, returns
8520 the value. If <link linkend="promise_set_exception"><code>promise::set_exception()</code></link> is called,
8521 throws the indicated exception.
8522 </para>
8523 </listitem>
8524 </varlistentry>
8525 <varlistentry>
8526 <term>Postcondition:</term>
8527 <listitem>
8528 <para>
8529 <code><phrase role="keyword">false</phrase> <phrase role="special">==</phrase>
8530 <phrase role="identifier">valid</phrase><phrase role="special">()</phrase></code>
8531 </para>
8532 </listitem>
8533 </varlistentry>
8534 <varlistentry>
8535 <term>Throws:</term>
8536 <listitem>
8537 <para>
8538 <code><phrase role="identifier">future_error</phrase></code> with
8539 error condition <code><phrase role="identifier">future_errc</phrase><phrase
8540 role="special">::</phrase><phrase role="identifier">no_state</phrase></code>,
8541 <code><phrase role="identifier">future_errc</phrase><phrase role="special">::</phrase><phrase
8542 role="identifier">broken_promise</phrase></code>. Any exception passed
8543 to <code><phrase role="identifier">promise</phrase><phrase role="special">::</phrase><phrase
8544 role="identifier">set_exception</phrase><phrase role="special">()</phrase></code>.
8545 </para>
8546 </listitem>
8547 </varlistentry>
8548 </variablelist>
8549 <para>
8550 <bridgehead renderas="sect4" id="future_get_exception_ptr_bridgehead">
8551 <phrase id="future_get_exception_ptr"/>
8552 <link linkend="future_get_exception_ptr">Member
8553 function <code>get_exception_ptr</code>()</link>
8554 </bridgehead>
8555 </para>
8556 <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>
8557 </programlisting>
8558 <variablelist>
8559 <title></title>
8560 <varlistentry>
8561 <term>Precondition:</term>
8562 <listitem>
8563 <para>
8564 <code><phrase role="keyword">true</phrase> <phrase role="special">==</phrase>
8565 <phrase role="identifier">valid</phrase><phrase role="special">()</phrase></code>
8566 </para>
8567 </listitem>
8568 </varlistentry>
8569 <varlistentry>
8570 <term>Returns:</term>
8571 <listitem>
8572 <para>
8573 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
8574 called. If <code><phrase role="identifier">set_value</phrase><phrase
8575 role="special">()</phrase></code> is called, returns a default-constructed
8576 <code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase
8577 role="identifier">exception_ptr</phrase></code>. If <code><phrase
8578 role="identifier">set_exception</phrase><phrase role="special">()</phrase></code>
8579 is called, returns the passed <code><phrase role="identifier">std</phrase><phrase
8580 role="special">::</phrase><phrase role="identifier">exception_ptr</phrase></code>.
8581 </para>
8582 </listitem>
8583 </varlistentry>
8584 <varlistentry>
8585 <term>Throws:</term>
8586 <listitem>
8587 <para>
8588 <code><phrase role="identifier">future_error</phrase></code> with
8589 error condition <code><phrase role="identifier">future_errc</phrase><phrase
8590 role="special">::</phrase><phrase role="identifier">no_state</phrase></code>.
8591 </para>
8592 </listitem>
8593 </varlistentry>
8594 <varlistentry>
8595 <term>Note:</term>
8596 <listitem>
8597 <para>
8598 <code><phrase role="identifier">get_exception_ptr</phrase><phrase
8599 role="special">()</phrase></code> does <emphasis>not</emphasis> invalidate
8600 the <code>future</code>. After calling <code><phrase role="identifier">get_exception_ptr</phrase><phrase
8601 role="special">()</phrase></code>, you may still call <link linkend="future_get"><code>future::get()</code></link>.
8602 </para>
8603 </listitem>
8604 </varlistentry>
8605 </variablelist>
8606 <para>
8607 <bridgehead renderas="sect4" id="future_wait_bridgehead">
8608 <phrase id="future_wait"/>
8609 <link linkend="future_wait">Member function <code>wait</code>()</link>
8610 </bridgehead>
8611 </para>
8612 <programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">wait</phrase><phrase role="special">();</phrase>
8613 </programlisting>
8614 <variablelist>
8615 <title></title>
8616 <varlistentry>
8617 <term>Effects:</term>
8618 <listitem>
8619 <para>
8620 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
8621 called.
8622 </para>
8623 </listitem>
8624 </varlistentry>
8625 <varlistentry>
8626 <term>Throws:</term>
8627 <listitem>
8628 <para>
8629 <code><phrase role="identifier">future_error</phrase></code> with
8630 error condition <code><phrase role="identifier">future_errc</phrase><phrase
8631 role="special">::</phrase><phrase role="identifier">no_state</phrase></code>.
8632 </para>
8633 </listitem>
8634 </varlistentry>
8635 </variablelist>
8636 <para>
8637 <bridgehead renderas="sect4" id="future_wait_for_bridgehead">
8638 <phrase id="future_wait_for"/>
8639 <link linkend="future_wait_for">Templated member
8640 function <code>wait_for</code>()</link>
8641 </bridgehead>
8642 </para>
8643 <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>
8644 <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>
8645 </programlisting>
8646 <variablelist>
8647 <title></title>
8648 <varlistentry>
8649 <term>Effects:</term>
8650 <listitem>
8651 <para>
8652 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
8653 called, or <code><phrase role="identifier">timeout_duration</phrase></code>
8654 has passed.
8655 </para>
8656 </listitem>
8657 </varlistentry>
8658 <varlistentry>
8659 <term>Result:</term>
8660 <listitem>
8661 <para>
8662 A <code><phrase role="identifier">future_status</phrase></code> is
8663 returned indicating the reason for returning.
8664 </para>
8665 </listitem>
8666 </varlistentry>
8667 <varlistentry>
8668 <term>Throws:</term>
8669 <listitem>
8670 <para>
8671 <code><phrase role="identifier">future_error</phrase></code> with
8672 error condition <code><phrase role="identifier">future_errc</phrase><phrase
8673 role="special">::</phrase><phrase role="identifier">no_state</phrase></code>
8674 or timeout-related exceptions.
8675 </para>
8676 </listitem>
8677 </varlistentry>
8678 </variablelist>
8679 <para>
8680 <bridgehead renderas="sect4" id="future_wait_until_bridgehead">
8681 <phrase id="future_wait_until"/>
8682 <link linkend="future_wait_until">Templated
8683 member function <code>wait_until</code>()</link>
8684 </bridgehead>
8685 </para>
8686 <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>
8687 <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>
8688 </programlisting>
8689 <variablelist>
8690 <title></title>
8691 <varlistentry>
8692 <term>Effects:</term>
8693 <listitem>
8694 <para>
8695 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
8696 called, or <code><phrase role="identifier">timeout_time</phrase></code>
8697 has passed.
8698 </para>
8699 </listitem>
8700 </varlistentry>
8701 <varlistentry>
8702 <term>Result:</term>
8703 <listitem>
8704 <para>
8705 A <code><phrase role="identifier">future_status</phrase></code> is
8706 returned indicating the reason for returning.
8707 </para>
8708 </listitem>
8709 </varlistentry>
8710 <varlistentry>
8711 <term>Throws:</term>
8712 <listitem>
8713 <para>
8714 <code><phrase role="identifier">future_error</phrase></code> with
8715 error condition <code><phrase role="identifier">future_errc</phrase><phrase
8716 role="special">::</phrase><phrase role="identifier">no_state</phrase></code>
8717 or timeout-related exceptions.
8718 </para>
8719 </listitem>
8720 </varlistentry>
8721 </variablelist>
8722 <para>
8723 <bridgehead renderas="sect4" id="class_shared_future_bridgehead">
8724 <phrase id="class_shared_future"/>
8725 <link linkend="class_shared_future">Template
8726 <code>shared_future&lt;&gt;</code></link>
8727 </bridgehead>
8728 </para>
8729 <para>
8730 A <link linkend="class_shared_future"><code>shared_future&lt;&gt;</code></link> contains a <link linkend="shared_state">shared
8731 state</link> which might be shared with other <link linkend="class_shared_future"><code>shared_future&lt;&gt;</code></link> instances.
8732 </para>
8733 <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>
8734
8735 <phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase>
8736 <phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase>
8737
8738 <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>
8739 <phrase role="keyword">class</phrase> <phrase role="identifier">shared_future</phrase> <phrase role="special">{</phrase>
8740 <phrase role="keyword">public</phrase><phrase role="special">:</phrase>
8741 <phrase role="identifier">shared_future</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
8742
8743 <phrase role="special">~</phrase><phrase role="identifier">shared_future</phrase><phrase role="special">();</phrase>
8744
8745 <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>
8746
8747 <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>
8748
8749 <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>
8750
8751 <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>
8752
8753 <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>
8754
8755 <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>
8756
8757 <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>
8758
8759 <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>
8760 <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>
8761 <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>
8762
8763 <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>
8764
8765 <phrase role="keyword">void</phrase> <phrase role="identifier">wait</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
8766
8767 <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>
8768 <phrase role="identifier">future_status</phrase> <phrase role="identifier">wait_for</phrase><phrase role="special">(</phrase>
8769 <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>
8770
8771 <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>
8772 <phrase role="identifier">future_status</phrase> <phrase role="identifier">wait_until</phrase><phrase role="special">(</phrase>
8773 <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>
8774 <phrase role="special">};</phrase>
8775
8776 <phrase role="special">}}</phrase>
8777 </programlisting>
8778 <bridgehead renderas="sect5" id="fiber.synchronization.futures.future.h7">
8779 <phrase id="fiber.synchronization.futures.future.default_constructor0"/><link
8780 linkend="fiber.synchronization.futures.future.default_constructor0">Default
8781 constructor</link>
8782 </bridgehead>
8783 <programlisting><phrase role="identifier">shared_future</phrase><phrase role="special">();</phrase>
8784 </programlisting>
8785 <variablelist>
8786 <title></title>
8787 <varlistentry>
8788 <term>Effects:</term>
8789 <listitem>
8790 <para>
8791 Creates a shared_future with no <link linkend="shared_state">shared
8792 state</link>. After construction <code><phrase role="keyword">false</phrase>
8793 <phrase role="special">==</phrase> <phrase role="identifier">valid</phrase><phrase
8794 role="special">()</phrase></code>.
8795 </para>
8796 </listitem>
8797 </varlistentry>
8798 <varlistentry>
8799 <term>Throws:</term>
8800 <listitem>
8801 <para>
8802 Nothing.
8803 </para>
8804 </listitem>
8805 </varlistentry>
8806 </variablelist>
8807 <bridgehead renderas="sect5" id="fiber.synchronization.futures.future.h8">
8808 <phrase id="fiber.synchronization.futures.future.move_constructor0"/><link
8809 linkend="fiber.synchronization.futures.future.move_constructor0">Move constructor</link>
8810 </bridgehead>
8811 <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>
8812 <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>
8813 </programlisting>
8814 <variablelist>
8815 <title></title>
8816 <varlistentry>
8817 <term>Effects:</term>
8818 <listitem>
8819 <para>
8820 Constructs a shared_future with the <link linkend="shared_state">shared
8821 state</link> of other. After construction <code><phrase role="keyword">false</phrase>
8822 <phrase role="special">==</phrase> <phrase role="identifier">other</phrase><phrase
8823 role="special">.</phrase><phrase role="identifier">valid</phrase><phrase
8824 role="special">()</phrase></code>.
8825 </para>
8826 </listitem>
8827 </varlistentry>
8828 <varlistentry>
8829 <term>Throws:</term>
8830 <listitem>
8831 <para>
8832 Nothing.
8833 </para>
8834 </listitem>
8835 </varlistentry>
8836 </variablelist>
8837 <bridgehead renderas="sect5" id="fiber.synchronization.futures.future.h9">
8838 <phrase id="fiber.synchronization.futures.future.copy_constructor"/><link
8839 linkend="fiber.synchronization.futures.future.copy_constructor">Copy constructor</link>
8840 </bridgehead>
8841 <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>
8842 </programlisting>
8843 <variablelist>
8844 <title></title>
8845 <varlistentry>
8846 <term>Effects:</term>
8847 <listitem>
8848 <para>
8849 Constructs a shared_future with the <link linkend="shared_state">shared
8850 state</link> of other. After construction <code><phrase role="identifier">other</phrase><phrase
8851 role="special">.</phrase><phrase role="identifier">valid</phrase><phrase
8852 role="special">()</phrase></code> is unchanged.
8853 </para>
8854 </listitem>
8855 </varlistentry>
8856 <varlistentry>
8857 <term>Throws:</term>
8858 <listitem>
8859 <para>
8860 Nothing.
8861 </para>
8862 </listitem>
8863 </varlistentry>
8864 </variablelist>
8865 <bridgehead renderas="sect5" id="fiber.synchronization.futures.future.h10">
8866 <phrase id="fiber.synchronization.futures.future.destructor0"/><link linkend="fiber.synchronization.futures.future.destructor0">Destructor</link>
8867 </bridgehead>
8868 <programlisting><phrase role="special">~</phrase><phrase role="identifier">shared_future</phrase><phrase role="special">();</phrase>
8869 </programlisting>
8870 <variablelist>
8871 <title></title>
8872 <varlistentry>
8873 <term>Effects:</term>
8874 <listitem>
8875 <para>
8876 Destroys the shared_future; ownership is abandoned if not shared.
8877 </para>
8878 </listitem>
8879 </varlistentry>
8880 <varlistentry>
8881 <term>Note:</term>
8882 <listitem>
8883 <para>
8884 <code>~shared_future()</code> does <emphasis>not</emphasis> block the calling fiber.
8885 </para>
8886 </listitem>
8887 </varlistentry>
8888 </variablelist>
8889 <para>
8890 <bridgehead renderas="sect4" id="shared_future_operator_assign_bridgehead">
8891 <phrase id="shared_future_operator_assign"/>
8892 <link linkend="shared_future_operator_assign">Member
8893 function <code>operator=</code>()</link>
8894 </bridgehead>
8895 </para>
8896 <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>
8897 <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>
8898 <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>
8899 </programlisting>
8900 <variablelist>
8901 <title></title>
8902 <varlistentry>
8903 <term>Effects:</term>
8904 <listitem>
8905 <para>
8906 Moves or copies the <link linkend="shared_state">shared state</link>
8907 of other to <code><phrase role="keyword">this</phrase></code>. After
8908 the assignment, the state of <code><phrase role="identifier">other</phrase><phrase
8909 role="special">.</phrase><phrase role="identifier">valid</phrase><phrase
8910 role="special">()</phrase></code> depends on which overload was invoked:
8911 unchanged for the overload accepting <code><phrase role="identifier">shared_future</phrase>
8912 <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase></code>,
8913 otherwise <code><phrase role="keyword">false</phrase></code>.
8914 </para>
8915 </listitem>
8916 </varlistentry>
8917 <varlistentry>
8918 <term>Throws:</term>
8919 <listitem>
8920 <para>
8921 Nothing.
8922 </para>
8923 </listitem>
8924 </varlistentry>
8925 </variablelist>
8926 <para>
8927 <bridgehead renderas="sect4" id="shared_future_valid_bridgehead">
8928 <phrase id="shared_future_valid"/>
8929 <link linkend="shared_future_valid">Member
8930 function <code>valid</code>()</link>
8931 </bridgehead>
8932 </para>
8933 <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>
8934 </programlisting>
8935 <variablelist>
8936 <title></title>
8937 <varlistentry>
8938 <term>Effects:</term>
8939 <listitem>
8940 <para>
8941 Returns <code><phrase role="keyword">true</phrase></code> if shared_future
8942 contains a <link linkend="shared_state">shared state</link>.
8943 </para>
8944 </listitem>
8945 </varlistentry>
8946 <varlistentry>
8947 <term>Throws:</term>
8948 <listitem>
8949 <para>
8950 Nothing.
8951 </para>
8952 </listitem>
8953 </varlistentry>
8954 </variablelist>
8955 <para>
8956 <bridgehead renderas="sect4" id="shared_future_get_bridgehead">
8957 <phrase id="shared_future_get"/>
8958 <link linkend="shared_future_get">Member function
8959 <code>get</code>()</link>
8960 </bridgehead>
8961 </para>
8962 <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>
8963 <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>
8964 <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>
8965 </programlisting>
8966 <variablelist>
8967 <title></title>
8968 <varlistentry>
8969 <term>Precondition:</term>
8970 <listitem>
8971 <para>
8972 <code><phrase role="keyword">true</phrase> <phrase role="special">==</phrase>
8973 <phrase role="identifier">valid</phrase><phrase role="special">()</phrase></code>
8974 </para>
8975 </listitem>
8976 </varlistentry>
8977 <varlistentry>
8978 <term>Returns:</term>
8979 <listitem>
8980 <para>
8981 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
8982 called. If <link linkend="promise_set_value"><code>promise::set_value()</code></link> is called, returns
8983 the value. If <link linkend="promise_set_exception"><code>promise::set_exception()</code></link> is called,
8984 throws the indicated exception.
8985 </para>
8986 </listitem>
8987 </varlistentry>
8988 <varlistentry>
8989 <term>Postcondition:</term>
8990 <listitem>
8991 <para>
8992 <code><phrase role="keyword">false</phrase> <phrase role="special">==</phrase>
8993 <phrase role="identifier">valid</phrase><phrase role="special">()</phrase></code>
8994 </para>
8995 </listitem>
8996 </varlistentry>
8997 <varlistentry>
8998 <term>Throws:</term>
8999 <listitem>
9000 <para>
9001 <code><phrase role="identifier">future_error</phrase></code> with
9002 error condition <code><phrase role="identifier">future_errc</phrase><phrase
9003 role="special">::</phrase><phrase role="identifier">no_state</phrase></code>,
9004 <code><phrase role="identifier">future_errc</phrase><phrase role="special">::</phrase><phrase
9005 role="identifier">broken_promise</phrase></code>. Any exception passed
9006 to <code><phrase role="identifier">promise</phrase><phrase role="special">::</phrase><phrase
9007 role="identifier">set_exception</phrase><phrase role="special">()</phrase></code>.
9008 </para>
9009 </listitem>
9010 </varlistentry>
9011 </variablelist>
9012 <para>
9013 <bridgehead renderas="sect4" id="shared_future_get_exception_ptr_bridgehead">
9014 <phrase id="shared_future_get_exception_ptr"/>
9015 <link linkend="shared_future_get_exception_ptr">Member
9016 function <code>get_exception_ptr</code>()</link>
9017 </bridgehead>
9018 </para>
9019 <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>
9020 </programlisting>
9021 <variablelist>
9022 <title></title>
9023 <varlistentry>
9024 <term>Precondition:</term>
9025 <listitem>
9026 <para>
9027 <code><phrase role="keyword">true</phrase> <phrase role="special">==</phrase>
9028 <phrase role="identifier">valid</phrase><phrase role="special">()</phrase></code>
9029 </para>
9030 </listitem>
9031 </varlistentry>
9032 <varlistentry>
9033 <term>Returns:</term>
9034 <listitem>
9035 <para>
9036 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
9037 called. If <code><phrase role="identifier">set_value</phrase><phrase
9038 role="special">()</phrase></code> is called, returns a default-constructed
9039 <code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase
9040 role="identifier">exception_ptr</phrase></code>. If <code><phrase
9041 role="identifier">set_exception</phrase><phrase role="special">()</phrase></code>
9042 is called, returns the passed <code><phrase role="identifier">std</phrase><phrase
9043 role="special">::</phrase><phrase role="identifier">exception_ptr</phrase></code>.
9044 </para>
9045 </listitem>
9046 </varlistentry>
9047 <varlistentry>
9048 <term>Throws:</term>
9049 <listitem>
9050 <para>
9051 <code><phrase role="identifier">future_error</phrase></code> with
9052 error condition <code><phrase role="identifier">future_errc</phrase><phrase
9053 role="special">::</phrase><phrase role="identifier">no_state</phrase></code>.
9054 </para>
9055 </listitem>
9056 </varlistentry>
9057 <varlistentry>
9058 <term>Note:</term>
9059 <listitem>
9060 <para>
9061 <code><phrase role="identifier">get_exception_ptr</phrase><phrase
9062 role="special">()</phrase></code> does <emphasis>not</emphasis> invalidate
9063 the <code>shared_future</code>. After calling <code><phrase role="identifier">get_exception_ptr</phrase><phrase
9064 role="special">()</phrase></code>, you may still call <link linkend="shared_future_get"><code>shared_future::get()</code></link>.
9065 </para>
9066 </listitem>
9067 </varlistentry>
9068 </variablelist>
9069 <para>
9070 <bridgehead renderas="sect4" id="shared_future_wait_bridgehead">
9071 <phrase id="shared_future_wait"/>
9072 <link linkend="shared_future_wait">Member
9073 function <code>wait</code>()</link>
9074 </bridgehead>
9075 </para>
9076 <programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">wait</phrase><phrase role="special">();</phrase>
9077 </programlisting>
9078 <variablelist>
9079 <title></title>
9080 <varlistentry>
9081 <term>Effects:</term>
9082 <listitem>
9083 <para>
9084 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
9085 called.
9086 </para>
9087 </listitem>
9088 </varlistentry>
9089 <varlistentry>
9090 <term>Throws:</term>
9091 <listitem>
9092 <para>
9093 <code><phrase role="identifier">future_error</phrase></code> with
9094 error condition <code><phrase role="identifier">future_errc</phrase><phrase
9095 role="special">::</phrase><phrase role="identifier">no_state</phrase></code>.
9096 </para>
9097 </listitem>
9098 </varlistentry>
9099 </variablelist>
9100 <para>
9101 <bridgehead renderas="sect4" id="shared_future_wait_for_bridgehead">
9102 <phrase id="shared_future_wait_for"/>
9103 <link linkend="shared_future_wait_for">Templated
9104 member function <code>wait_for</code>()</link>
9105 </bridgehead>
9106 </para>
9107 <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>
9108 <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>
9109 </programlisting>
9110 <variablelist>
9111 <title></title>
9112 <varlistentry>
9113 <term>Effects:</term>
9114 <listitem>
9115 <para>
9116 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
9117 called, or <code><phrase role="identifier">timeout_duration</phrase></code>
9118 has passed.
9119 </para>
9120 </listitem>
9121 </varlistentry>
9122 <varlistentry>
9123 <term>Result:</term>
9124 <listitem>
9125 <para>
9126 A <code><phrase role="identifier">future_status</phrase></code> is
9127 returned indicating the reason for returning.
9128 </para>
9129 </listitem>
9130 </varlistentry>
9131 <varlistentry>
9132 <term>Throws:</term>
9133 <listitem>
9134 <para>
9135 <code><phrase role="identifier">future_error</phrase></code> with
9136 error condition <code><phrase role="identifier">future_errc</phrase><phrase
9137 role="special">::</phrase><phrase role="identifier">no_state</phrase></code>
9138 or timeout-related exceptions.
9139 </para>
9140 </listitem>
9141 </varlistentry>
9142 </variablelist>
9143 <para>
9144 <bridgehead renderas="sect4" id="shared_future_wait_until_bridgehead">
9145 <phrase id="shared_future_wait_until"/>
9146 <link linkend="shared_future_wait_until">Templated
9147 member function <code>wait_until</code>()</link>
9148 </bridgehead>
9149 </para>
9150 <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>
9151 <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>
9152 </programlisting>
9153 <variablelist>
9154 <title></title>
9155 <varlistentry>
9156 <term>Effects:</term>
9157 <listitem>
9158 <para>
9159 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
9160 called, or <code><phrase role="identifier">timeout_time</phrase></code>
9161 has passed.
9162 </para>
9163 </listitem>
9164 </varlistentry>
9165 <varlistentry>
9166 <term>Result:</term>
9167 <listitem>
9168 <para>
9169 A <code><phrase role="identifier">future_status</phrase></code> is
9170 returned indicating the reason for returning.
9171 </para>
9172 </listitem>
9173 </varlistentry>
9174 <varlistentry>
9175 <term>Throws:</term>
9176 <listitem>
9177 <para>
9178 <code><phrase role="identifier">future_error</phrase></code> with
9179 error condition <code><phrase role="identifier">future_errc</phrase><phrase
9180 role="special">::</phrase><phrase role="identifier">no_state</phrase></code>
9181 or timeout-related exceptions.
9182 </para>
9183 </listitem>
9184 </varlistentry>
9185 </variablelist>
9186 <para>
9187 <bridgehead renderas="sect4" id="fibers_async_bridgehead">
9188 <phrase id="fibers_async"/>
9189 <link linkend="fibers_async">Non-member function <code>fibers::async()</code></link>
9190 </bridgehead>
9191 </para>
9192 <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>
9193
9194 <phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase>
9195 <phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase>
9196
9197 <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>
9198 <phrase role="identifier">future</phrase><phrase role="special">&lt;</phrase>
9199 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">result_of_t</phrase><phrase role="special">&lt;</phrase>
9200 <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>
9201 <phrase role="special">&gt;</phrase>
9202 <phrase role="special">&gt;</phrase>
9203 <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>
9204
9205 <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>
9206 <phrase role="identifier">future</phrase><phrase role="special">&lt;</phrase>
9207 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">result_of_t</phrase><phrase role="special">&lt;</phrase>
9208 <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>
9209 <phrase role="special">&gt;</phrase>
9210 <phrase role="special">&gt;</phrase>
9211 <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>
9212
9213 <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>
9214 <phrase role="identifier">future</phrase><phrase role="special">&lt;</phrase>
9215 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">result_of_t</phrase><phrase role="special">&lt;</phrase>
9216 <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>
9217 <phrase role="special">&gt;</phrase>
9218 <phrase role="special">&gt;</phrase>
9219 <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>
9220 <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>
9221
9222 <phrase role="special">}}</phrase>
9223 </programlisting>
9224 <variablelist>
9225 <title></title>
9226 <varlistentry>
9227 <term>Effects:</term>
9228 <listitem>
9229 <para>
9230 Executes <code><phrase role="identifier">fn</phrase></code> in a
9231 <link linkend="class_fiber"><code>fiber</code></link> and returns an associated <link linkend="class_future"><code>future&lt;&gt;</code></link>.
9232 </para>
9233 </listitem>
9234 </varlistentry>
9235 <varlistentry>
9236 <term>Result:</term>
9237 <listitem>
9238 <para>
9239 <programlisting><phrase role="identifier">future</phrase><phrase role="special">&lt;</phrase>
9240 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">result_of_t</phrase><phrase role="special">&lt;</phrase>
9241 <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>
9242 <phrase role="special">&gt;</phrase>
9243 <phrase role="special">&gt;</phrase></programlisting>
9244 representing the <link linkend="shared_state">shared state</link>
9245 associated with the asynchronous execution of <code><phrase role="identifier">fn</phrase></code>.
9246 </para>
9247 </listitem>
9248 </varlistentry>
9249 <varlistentry>
9250 <term>Throws:</term>
9251 <listitem>
9252 <para>
9253 <code><phrase role="identifier">fiber_error</phrase></code> or <code><phrase
9254 role="identifier">future_error</phrase></code> if an error occurs.
9255 </para>
9256 </listitem>
9257 </varlistentry>
9258 <varlistentry>
9259 <term>Notes:</term>
9260 <listitem>
9261 <para>
9262 The overloads accepting <ulink url="http://en.cppreference.com/w/cpp/memory/allocator_arg_t"><code><phrase
9263 role="identifier">std</phrase><phrase role="special">::</phrase><phrase
9264 role="identifier">allocator_arg_t</phrase></code></ulink> use the
9265 passed <link linkend="stack_allocator_concept"><code><phrase role="identifier">StackAllocator</phrase></code></link>
9266 when constructing the launched <code><phrase role="identifier">fiber</phrase></code>.
9267 The overloads accepting <link linkend="class_launch"><code>launch</code></link> use the passed <code><phrase
9268 role="identifier">launch</phrase></code> when constructing the launched
9269 <code><phrase role="identifier">fiber</phrase></code>. The default
9270 <code><phrase role="identifier">launch</phrase></code> is <code><phrase
9271 role="identifier">post</phrase></code>, as for the <code><phrase
9272 role="identifier">fiber</phrase></code> constructor.
9273 </para>
9274 </listitem>
9275 </varlistentry>
9276 </variablelist>
9277 <note>
9278 <para>
9279 Deferred futures are not supported.
9280 </para>
9281 </note>
9282 </section>
9283 <section id="fiber.synchronization.futures.promise">
9284 <title><anchor id="class_promise"/><link linkend="fiber.synchronization.futures.promise">Template
9285 <code><phrase role="identifier">promise</phrase><phrase role="special">&lt;&gt;</phrase></code></link></title>
9286 <para>
9287 A <link linkend="class_promise"><code>promise&lt;&gt;</code></link> provides a mechanism to store a value (or
9288 exception) that can later be retrieved from the corresponding <link linkend="class_future"><code>future&lt;&gt;</code></link> object.
9289 <code><phrase role="identifier">promise</phrase><phrase role="special">&lt;&gt;</phrase></code>
9290 and <code><phrase role="identifier">future</phrase><phrase role="special">&lt;&gt;</phrase></code>
9291 communicate via their underlying <link linkend="shared_state">shared state</link>.
9292 </para>
9293 <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>
9294
9295 <phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase>
9296 <phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase>
9297
9298 <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>
9299 <phrase role="keyword">class</phrase> <phrase role="identifier">promise</phrase> <phrase role="special">{</phrase>
9300 <phrase role="keyword">public</phrase><phrase role="special">:</phrase>
9301 <phrase role="identifier">promise</phrase><phrase role="special">();</phrase>
9302
9303 <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>
9304 <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>
9305
9306 <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>
9307
9308 <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>
9309
9310 <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>
9311
9312 <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>
9313
9314 <phrase role="special">~</phrase><phrase role="identifier">promise</phrase><phrase role="special">();</phrase>
9315
9316 <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>
9317
9318 <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>
9319
9320 <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>
9321 <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>
9322 <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>
9323 <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>
9324
9325 <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>
9326 <phrase role="special">};</phrase>
9327
9328 <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>
9329 <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>
9330
9331 <phrase role="special">}</phrase>
9332 </programlisting>
9333 <bridgehead renderas="sect5" id="fiber.synchronization.futures.promise.h0">
9334 <phrase id="fiber.synchronization.futures.promise.default_constructor"/><link
9335 linkend="fiber.synchronization.futures.promise.default_constructor">Default
9336 constructor</link>
9337 </bridgehead>
9338 <programlisting><phrase role="identifier">promise</phrase><phrase role="special">();</phrase>
9339 </programlisting>
9340 <variablelist>
9341 <title></title>
9342 <varlistentry>
9343 <term>Effects:</term>
9344 <listitem>
9345 <para>
9346 Creates a promise with an empty <link linkend="shared_state">shared
9347 state</link>.
9348 </para>
9349 </listitem>
9350 </varlistentry>
9351 <varlistentry>
9352 <term>Throws:</term>
9353 <listitem>
9354 <para>
9355 Exceptions caused by memory allocation.
9356 </para>
9357 </listitem>
9358 </varlistentry>
9359 </variablelist>
9360 <bridgehead renderas="sect5" id="fiber.synchronization.futures.promise.h1">
9361 <phrase id="fiber.synchronization.futures.promise.constructor"/><link linkend="fiber.synchronization.futures.promise.constructor">Constructor</link>
9362 </bridgehead>
9363 <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>
9364 <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>
9365 </programlisting>
9366 <variablelist>
9367 <title></title>
9368 <varlistentry>
9369 <term>Effects:</term>
9370 <listitem>
9371 <para>
9372 Creates a promise with an empty <link linkend="shared_state">shared
9373 state</link> by using <code><phrase role="identifier">alloc</phrase></code>.
9374 </para>
9375 </listitem>
9376 </varlistentry>
9377 <varlistentry>
9378 <term>Throws:</term>
9379 <listitem>
9380 <para>
9381 Exceptions caused by memory allocation.
9382 </para>
9383 </listitem>
9384 </varlistentry>
9385 <varlistentry>
9386 <term>See also:</term>
9387 <listitem>
9388 <para>
9389 <ulink url="http://en.cppreference.com/w/cpp/memory/allocator_arg_t"><code><phrase
9390 role="identifier">std</phrase><phrase role="special">::</phrase><phrase
9391 role="identifier">allocator_arg_t</phrase></code></ulink>
9392 </para>
9393 </listitem>
9394 </varlistentry>
9395 </variablelist>
9396 <bridgehead renderas="sect5" id="fiber.synchronization.futures.promise.h2">
9397 <phrase id="fiber.synchronization.futures.promise.move_constructor"/><link
9398 linkend="fiber.synchronization.futures.promise.move_constructor">Move constructor</link>
9399 </bridgehead>
9400 <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>
9401 </programlisting>
9402 <variablelist>
9403 <title></title>
9404 <varlistentry>
9405 <term>Effects:</term>
9406 <listitem>
9407 <para>
9408 Creates a promise by moving the <link linkend="shared_state">shared
9409 state</link> from <code><phrase role="identifier">other</phrase></code>.
9410 </para>
9411 </listitem>
9412 </varlistentry>
9413 <varlistentry>
9414 <term>Postcondition:</term>
9415 <listitem>
9416 <para>
9417 <code><phrase role="identifier">other</phrase></code> contains no
9418 valid shared state.
9419 </para>
9420 </listitem>
9421 </varlistentry>
9422 <varlistentry>
9423 <term>Throws:</term>
9424 <listitem>
9425 <para>
9426 Nothing.
9427 </para>
9428 </listitem>
9429 </varlistentry>
9430 </variablelist>
9431 <bridgehead renderas="sect5" id="fiber.synchronization.futures.promise.h3">
9432 <phrase id="fiber.synchronization.futures.promise.destructor"/><link linkend="fiber.synchronization.futures.promise.destructor">Destructor</link>
9433 </bridgehead>
9434 <programlisting><phrase role="special">~</phrase><phrase role="identifier">promise</phrase><phrase role="special">();</phrase>
9435 </programlisting>
9436 <variablelist>
9437 <title></title>
9438 <varlistentry>
9439 <term>Effects:</term>
9440 <listitem>
9441 <para>
9442 Destroys <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>
9443 and abandons the <link linkend="shared_state">shared state</link>
9444 if shared state is ready; otherwise stores <code><phrase role="identifier">future_error</phrase></code>
9445 with error condition <code><phrase role="identifier">future_errc</phrase><phrase
9446 role="special">::</phrase><phrase role="identifier">broken_promise</phrase></code>
9447 as if by <link linkend="promise_set_exception"><code>promise::set_exception()</code></link>: the shared
9448 state is set ready.
9449 </para>
9450 </listitem>
9451 </varlistentry>
9452 </variablelist>
9453 <para>
9454 <bridgehead renderas="sect4" id="promise_operator_assign_bridgehead">
9455 <phrase id="promise_operator_assign"/>
9456 <link linkend="promise_operator_assign">Member
9457 function <code>operator=</code>()</link>
9458 </bridgehead>
9459 </para>
9460 <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>
9461 </programlisting>
9462 <variablelist>
9463 <title></title>
9464 <varlistentry>
9465 <term>Effects:</term>
9466 <listitem>
9467 <para>
9468 Transfers the ownership of <link linkend="shared_state">shared state</link>
9469 to <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>.
9470 </para>
9471 </listitem>
9472 </varlistentry>
9473 <varlistentry>
9474 <term>Postcondition:</term>
9475 <listitem>
9476 <para>
9477 <code><phrase role="identifier">other</phrase></code> contains no
9478 valid shared state.
9479 </para>
9480 </listitem>
9481 </varlistentry>
9482 <varlistentry>
9483 <term>Throws:</term>
9484 <listitem>
9485 <para>
9486 Nothing.
9487 </para>
9488 </listitem>
9489 </varlistentry>
9490 </variablelist>
9491 <para>
9492 <bridgehead renderas="sect4" id="promise_swap_bridgehead">
9493 <phrase id="promise_swap"/>
9494 <link linkend="promise_swap">Member function <code>swap</code>()</link>
9495 </bridgehead>
9496 </para>
9497 <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>
9498 </programlisting>
9499 <variablelist>
9500 <title></title>
9501 <varlistentry>
9502 <term>Effects:</term>
9503 <listitem>
9504 <para>
9505 Swaps the <link linkend="shared_state">shared state</link> between
9506 other and <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>.
9507 </para>
9508 </listitem>
9509 </varlistentry>
9510 <varlistentry>
9511 <term>Throws:</term>
9512 <listitem>
9513 <para>
9514 Nothing.
9515 </para>
9516 </listitem>
9517 </varlistentry>
9518 </variablelist>
9519 <para>
9520 <bridgehead renderas="sect4" id="promise_get_future_bridgehead">
9521 <phrase id="promise_get_future"/>
9522 <link linkend="promise_get_future">Member
9523 function <code>get_future</code>()</link>
9524 </bridgehead>
9525 </para>
9526 <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>
9527 </programlisting>
9528 <variablelist>
9529 <title></title>
9530 <varlistentry>
9531 <term>Returns:</term>
9532 <listitem>
9533 <para>
9534 A <link linkend="class_future"><code>future&lt;&gt;</code></link> with the same <link linkend="shared_state">shared
9535 state</link>.
9536 </para>
9537 </listitem>
9538 </varlistentry>
9539 <varlistentry>
9540 <term>Throws:</term>
9541 <listitem>
9542 <para>
9543 <code><phrase role="identifier">future_error</phrase></code> with
9544 <code><phrase role="identifier">future_errc</phrase><phrase role="special">::</phrase><phrase
9545 role="identifier">future_already_retrieved</phrase></code> or <code><phrase
9546 role="identifier">future_errc</phrase><phrase role="special">::</phrase><phrase
9547 role="identifier">no_state</phrase></code>.
9548 </para>
9549 </listitem>
9550 </varlistentry>
9551 </variablelist>
9552 <para>
9553 <bridgehead renderas="sect4" id="promise_set_value_bridgehead">
9554 <phrase id="promise_set_value"/>
9555 <link linkend="promise_set_value">Member function
9556 <code>set_value</code>()</link>
9557 </bridgehead>
9558 </para>
9559 <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>
9560 <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>
9561 <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>
9562 <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>
9563 </programlisting>
9564 <variablelist>
9565 <title></title>
9566 <varlistentry>
9567 <term>Effects:</term>
9568 <listitem>
9569 <para>
9570 Store the result in the <link linkend="shared_state">shared state</link>
9571 and marks the state as ready.
9572 </para>
9573 </listitem>
9574 </varlistentry>
9575 <varlistentry>
9576 <term>Throws:</term>
9577 <listitem>
9578 <para>
9579 <code><phrase role="identifier">future_error</phrase></code> with
9580 <code><phrase role="identifier">future_errc</phrase><phrase role="special">::</phrase><phrase
9581 role="identifier">future_already_satisfied</phrase></code> or <code><phrase
9582 role="identifier">future_errc</phrase><phrase role="special">::</phrase><phrase
9583 role="identifier">no_state</phrase></code>.
9584 </para>
9585 </listitem>
9586 </varlistentry>
9587 </variablelist>
9588 <para>
9589 <bridgehead renderas="sect4" id="promise_set_exception_bridgehead">
9590 <phrase id="promise_set_exception"/>
9591 <link linkend="promise_set_exception">Member
9592 function <code>set_exception</code>()</link>
9593 </bridgehead>
9594 </para>
9595 <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>
9596 </programlisting>
9597 <variablelist>
9598 <title></title>
9599 <varlistentry>
9600 <term>Effects:</term>
9601 <listitem>
9602 <para>
9603 Store an exception pointer in the <link linkend="shared_state">shared
9604 state</link> and marks the state as ready.
9605 </para>
9606 </listitem>
9607 </varlistentry>
9608 <varlistentry>
9609 <term>Throws:</term>
9610 <listitem>
9611 <para>
9612 <code><phrase role="identifier">future_error</phrase></code> with
9613 <code><phrase role="identifier">future_errc</phrase><phrase role="special">::</phrase><phrase
9614 role="identifier">future_already_satisfied</phrase></code> or <code><phrase
9615 role="identifier">future_errc</phrase><phrase role="special">::</phrase><phrase
9616 role="identifier">no_state</phrase></code>.
9617 </para>
9618 </listitem>
9619 </varlistentry>
9620 </variablelist>
9621 <para>
9622 <bridgehead renderas="sect4" id="swap_for_promise_bridgehead">
9623 <phrase id="swap_for_promise"/>
9624 <link linkend="swap_for_promise">Non-member function
9625 <code>swap()</code></link>
9626 </bridgehead>
9627 </para>
9628 <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>
9629 <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>
9630 </programlisting>
9631 <variablelist>
9632 <title></title>
9633 <varlistentry>
9634 <term>Effects:</term>
9635 <listitem>
9636 <para>
9637 Same as <code><phrase role="identifier">l</phrase><phrase role="special">.</phrase><phrase
9638 role="identifier">swap</phrase><phrase role="special">(</phrase>
9639 <phrase role="identifier">r</phrase><phrase role="special">)</phrase></code>.
9640 </para>
9641 </listitem>
9642 </varlistentry>
9643 </variablelist>
9644 </section>
9645 <section id="fiber.synchronization.futures.packaged_task">
9646 <title><anchor id="class_packaged_task"/><link linkend="fiber.synchronization.futures.packaged_task">Template
9647 <code><phrase role="identifier">packaged_task</phrase><phrase role="special">&lt;&gt;</phrase></code></link></title>
9648 <para>
9649 A <link linkend="class_packaged_task"><code>packaged_task&lt;&gt;</code></link> wraps a callable target that
9650 returns a value so that the return value can be computed asynchronously.
9651 </para>
9652 <para>
9653 Conventional usage of <code><phrase role="identifier">packaged_task</phrase><phrase
9654 role="special">&lt;&gt;</phrase></code> is like this:
9655 </para>
9656 <orderedlist>
9657 <listitem>
9658 <simpara>
9659 Instantiate <code><phrase role="identifier">packaged_task</phrase><phrase
9660 role="special">&lt;&gt;</phrase></code> with template arguments matching
9661 the signature of the callable. Pass the callable to the <link linkend="packaged_task_packaged_task">constructor</link>.
9662 </simpara>
9663 </listitem>
9664 <listitem>
9665 <simpara>
9666 Call <link linkend="packaged_task_get_future"><code>packaged_task::get_future()</code></link> and capture
9667 the returned <link linkend="class_future"><code>future&lt;&gt;</code></link> instance.
9668 </simpara>
9669 </listitem>
9670 <listitem>
9671 <simpara>
9672 Launch a <link linkend="class_fiber"><code>fiber</code></link> to run the new <code><phrase role="identifier">packaged_task</phrase><phrase
9673 role="special">&lt;&gt;</phrase></code>, passing any arguments required
9674 by the original callable.
9675 </simpara>
9676 </listitem>
9677 <listitem>
9678 <simpara>
9679 Call <link linkend="fiber_detach"><code>fiber::detach()</code></link> on the newly-launched <code><phrase
9680 role="identifier">fiber</phrase></code>.
9681 </simpara>
9682 </listitem>
9683 <listitem>
9684 <simpara>
9685 At some later point, retrieve the result from the <code><phrase role="identifier">future</phrase><phrase
9686 role="special">&lt;&gt;</phrase></code>.
9687 </simpara>
9688 </listitem>
9689 </orderedlist>
9690 <para>
9691 This is, in fact, pretty much what <link linkend="fibers_async"><code>fibers::async()</code></link>
9692 encapsulates.
9693 </para>
9694 <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>
9695
9696 <phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase>
9697 <phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase>
9698
9699 <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>
9700 <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>
9701 <phrase role="keyword">public</phrase><phrase role="special">:</phrase>
9702 <phrase role="identifier">packaged_task</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
9703
9704 <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>
9705 <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>
9706
9707 <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>
9708 <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>
9709
9710 <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>
9711
9712 <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>
9713
9714 <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>
9715
9716 <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>
9717
9718 <phrase role="special">~</phrase><phrase role="identifier">packaged_task</phrase><phrase role="special">();</phrase>
9719
9720 <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>
9721
9722 <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>
9723
9724 <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>
9725
9726 <phrase role="keyword">void</phrase> <phrase role="keyword">operator</phrase><phrase role="special">()(</phrase> <phrase role="identifier">Args</phrase> <phrase role="special">...);</phrase>
9727
9728 <phrase role="keyword">void</phrase> <phrase role="identifier">reset</phrase><phrase role="special">();</phrase>
9729 <phrase role="special">};</phrase>
9730
9731 <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>
9732 <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>
9733
9734 <phrase role="special">}}</phrase>
9735 </programlisting>
9736 <bridgehead renderas="sect5" id="fiber.synchronization.futures.packaged_task.h0">
9737 <phrase id="fiber.synchronization.futures.packaged_task.default_constructor__code__phrase_role__identifier__packaged_task__phrase__phrase_role__special______phrase___code_"/><link
9738 linkend="fiber.synchronization.futures.packaged_task.default_constructor__code__phrase_role__identifier__packaged_task__phrase__phrase_role__special______phrase___code_">Default
9739 constructor <code><phrase role="identifier">packaged_task</phrase><phrase
9740 role="special">()</phrase></code></link>
9741 </bridgehead>
9742 <programlisting><phrase role="identifier">packaged_task</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase>
9743 </programlisting>
9744 <variablelist>
9745 <title></title>
9746 <varlistentry>
9747 <term>Effects:</term>
9748 <listitem>
9749 <para>
9750 Constructs an object of class <code><phrase role="identifier">packaged_task</phrase></code>
9751 with no <link linkend="shared_state">shared state</link>.
9752 </para>
9753 </listitem>
9754 </varlistentry>
9755 <varlistentry>
9756 <term>Throws:</term>
9757 <listitem>
9758 <para>
9759 Nothing.
9760 </para>
9761 </listitem>
9762 </varlistentry>
9763 </variablelist>
9764 <anchor id="packaged_task_packaged_task"/>
9765 <bridgehead renderas="sect5" id="fiber.synchronization.futures.packaged_task.h1">
9766 <phrase id="fiber.synchronization.futures.packaged_task.templated_constructor__code__phrase_role__identifier__packaged_task__phrase__phrase_role__special______phrase___code_"/><link
9767 linkend="fiber.synchronization.futures.packaged_task.templated_constructor__code__phrase_role__identifier__packaged_task__phrase__phrase_role__special______phrase___code_">Templated
9768 constructor <code><phrase role="identifier">packaged_task</phrase><phrase
9769 role="special">()</phrase></code></link>
9770 </bridgehead>
9771 <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>
9772 <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>
9773
9774 <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>
9775 <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>
9776 </programlisting>
9777 <variablelist>
9778 <title></title>
9779 <varlistentry>
9780 <term>Effects:</term>
9781 <listitem>
9782 <para>
9783 Constructs an object of class <code><phrase role="identifier">packaged_task</phrase></code>
9784 with a <link linkend="shared_state">shared state</link> and copies
9785 or moves the callable target <code><phrase role="identifier">fn</phrase></code>
9786 to internal storage.
9787 </para>
9788 </listitem>
9789 </varlistentry>
9790 <varlistentry>
9791 <term>Throws:</term>
9792 <listitem>
9793 <para>
9794 Exceptions caused by memory allocation.
9795 </para>
9796 </listitem>
9797 </varlistentry>
9798 <varlistentry>
9799 <term>Note:</term>
9800 <listitem>
9801 <para>
9802 The signature of <code><phrase role="identifier">Fn</phrase></code>
9803 should have a return type convertible to <code><phrase role="identifier">R</phrase></code>.
9804 </para>
9805 </listitem>
9806 </varlistentry>
9807 <varlistentry>
9808 <term>See also:</term>
9809 <listitem>
9810 <para>
9811 <ulink url="http://en.cppreference.com/w/cpp/memory/allocator_arg_t"><code><phrase
9812 role="identifier">std</phrase><phrase role="special">::</phrase><phrase
9813 role="identifier">allocator_arg_t</phrase></code></ulink>
9814 </para>
9815 </listitem>
9816 </varlistentry>
9817 </variablelist>
9818 <bridgehead renderas="sect5" id="fiber.synchronization.futures.packaged_task.h2">
9819 <phrase id="fiber.synchronization.futures.packaged_task.move_constructor"/><link
9820 linkend="fiber.synchronization.futures.packaged_task.move_constructor">Move
9821 constructor</link>
9822 </bridgehead>
9823 <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>
9824 </programlisting>
9825 <variablelist>
9826 <title></title>
9827 <varlistentry>
9828 <term>Effects:</term>
9829 <listitem>
9830 <para>
9831 Creates a packaged_task by moving the <link linkend="shared_state">shared
9832 state</link> from <code><phrase role="identifier">other</phrase></code>.
9833 </para>
9834 </listitem>
9835 </varlistentry>
9836 <varlistentry>
9837 <term>Postcondition:</term>
9838 <listitem>
9839 <para>
9840 <code><phrase role="identifier">other</phrase></code> contains no
9841 valid shared state.
9842 </para>
9843 </listitem>
9844 </varlistentry>
9845 <varlistentry>
9846 <term>Throws:</term>
9847 <listitem>
9848 <para>
9849 Nothing.
9850 </para>
9851 </listitem>
9852 </varlistentry>
9853 </variablelist>
9854 <bridgehead renderas="sect5" id="fiber.synchronization.futures.packaged_task.h3">
9855 <phrase id="fiber.synchronization.futures.packaged_task.destructor"/><link
9856 linkend="fiber.synchronization.futures.packaged_task.destructor">Destructor</link>
9857 </bridgehead>
9858 <programlisting><phrase role="special">~</phrase><phrase role="identifier">packaged_task</phrase><phrase role="special">();</phrase>
9859 </programlisting>
9860 <variablelist>
9861 <title></title>
9862 <varlistentry>
9863 <term>Effects:</term>
9864 <listitem>
9865 <para>
9866 Destroys <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>
9867 and abandons the <link linkend="shared_state">shared state</link>
9868 if shared state is ready; otherwise stores <code><phrase role="identifier">future_error</phrase></code>
9869 with error condition <code><phrase role="identifier">future_errc</phrase><phrase
9870 role="special">::</phrase><phrase role="identifier">broken_promise</phrase></code>
9871 as if by <link linkend="promise_set_exception"><code>promise::set_exception()</code></link>: the shared
9872 state is set ready.
9873 </para>
9874 </listitem>
9875 </varlistentry>
9876 </variablelist>
9877 <para>
9878 <bridgehead renderas="sect4" id="packaged_task_operator_assign_bridgehead">
9879 <phrase id="packaged_task_operator_assign"/>
9880 <link linkend="packaged_task_operator_assign">Member
9881 function <code>operator=</code>()</link>
9882 </bridgehead>
9883 </para>
9884 <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>
9885 </programlisting>
9886 <variablelist>
9887 <title></title>
9888 <varlistentry>
9889 <term>Effects:</term>
9890 <listitem>
9891 <para>
9892 Transfers the ownership of <link linkend="shared_state">shared state</link>
9893 to <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>.
9894 </para>
9895 </listitem>
9896 </varlistentry>
9897 <varlistentry>
9898 <term>Postcondition:</term>
9899 <listitem>
9900 <para>
9901 <code><phrase role="identifier">other</phrase></code> contains no
9902 valid shared state.
9903 </para>
9904 </listitem>
9905 </varlistentry>
9906 <varlistentry>
9907 <term>Throws:</term>
9908 <listitem>
9909 <para>
9910 Nothing.
9911 </para>
9912 </listitem>
9913 </varlistentry>
9914 </variablelist>
9915 <para>
9916 <bridgehead renderas="sect4" id="packaged_task_swap_bridgehead">
9917 <phrase id="packaged_task_swap"/>
9918 <link linkend="packaged_task_swap">Member
9919 function <code>swap</code>()</link>
9920 </bridgehead>
9921 </para>
9922 <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>
9923 </programlisting>
9924 <variablelist>
9925 <title></title>
9926 <varlistentry>
9927 <term>Effects:</term>
9928 <listitem>
9929 <para>
9930 Swaps the <link linkend="shared_state">shared state</link> between
9931 other and <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>.
9932 </para>
9933 </listitem>
9934 </varlistentry>
9935 <varlistentry>
9936 <term>Throws:</term>
9937 <listitem>
9938 <para>
9939 Nothing.
9940 </para>
9941 </listitem>
9942 </varlistentry>
9943 </variablelist>
9944 <para>
9945 <bridgehead renderas="sect4" id="packaged_task_valid_bridgehead">
9946 <phrase id="packaged_task_valid"/>
9947 <link linkend="packaged_task_valid">Member
9948 function <code>valid</code>()</link>
9949 </bridgehead>
9950 </para>
9951 <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>
9952 </programlisting>
9953 <variablelist>
9954 <title></title>
9955 <varlistentry>
9956 <term>Effects:</term>
9957 <listitem>
9958 <para>
9959 Returns <code><phrase role="keyword">true</phrase></code> if <code><phrase
9960 role="special">*</phrase><phrase role="keyword">this</phrase></code>
9961 contains a <link linkend="shared_state">shared state</link>.
9962 </para>
9963 </listitem>
9964 </varlistentry>
9965 <varlistentry>
9966 <term>Throws:</term>
9967 <listitem>
9968 <para>
9969 Nothing.
9970 </para>
9971 </listitem>
9972 </varlistentry>
9973 </variablelist>
9974 <para>
9975 <bridgehead renderas="sect4" id="packaged_task_get_future_bridgehead">
9976 <phrase id="packaged_task_get_future"/>
9977 <link linkend="packaged_task_get_future">Member
9978 function <code>get_future</code>()</link>
9979 </bridgehead>
9980 </para>
9981 <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>
9982 </programlisting>
9983 <variablelist>
9984 <title></title>
9985 <varlistentry>
9986 <term>Returns:</term>
9987 <listitem>
9988 <para>
9989 A <link linkend="class_future"><code>future&lt;&gt;</code></link> with the same <link linkend="shared_state">shared
9990 state</link>.
9991 </para>
9992 </listitem>
9993 </varlistentry>
9994 <varlistentry>
9995 <term>Throws:</term>
9996 <listitem>
9997 <para>
9998 <code><phrase role="identifier">future_error</phrase></code> with
9999 <code><phrase role="identifier">future_errc</phrase><phrase role="special">::</phrase><phrase
10000 role="identifier">future_already_retrieved</phrase></code> or <code><phrase
10001 role="identifier">future_errc</phrase><phrase role="special">::</phrase><phrase
10002 role="identifier">no_state</phrase></code>.
10003 </para>
10004 </listitem>
10005 </varlistentry>
10006 </variablelist>
10007 <para>
10008 <bridgehead renderas="sect4" id="packaged_task_operator_apply_bridgehead">
10009 <phrase id="packaged_task_operator_apply"/>
10010 <link linkend="packaged_task_operator_apply">Member
10011 function <code>operator()</code>()</link>
10012 </bridgehead>
10013 </para>
10014 <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>
10015 </programlisting>
10016 <variablelist>
10017 <title></title>
10018 <varlistentry>
10019 <term>Effects:</term>
10020 <listitem>
10021 <para>
10022 Invokes the stored callable target. Any exception thrown by the callable
10023 target <code><phrase role="identifier">fn</phrase></code> is stored
10024 in the <link linkend="shared_state">shared state</link> as if by
10025 <link linkend="promise_set_exception"><code>promise::set_exception()</code></link>. Otherwise, the value
10026 returned by <code><phrase role="identifier">fn</phrase></code> is
10027 stored in the shared state as if by <link linkend="promise_set_value"><code>promise::set_value()</code></link>.
10028 </para>
10029 </listitem>
10030 </varlistentry>
10031 <varlistentry>
10032 <term>Throws:</term>
10033 <listitem>
10034 <para>
10035 <code><phrase role="identifier">future_error</phrase></code> with
10036 <code><phrase role="identifier">future_errc</phrase><phrase role="special">::</phrase><phrase
10037 role="identifier">no_state</phrase></code>.
10038 </para>
10039 </listitem>
10040 </varlistentry>
10041 </variablelist>
10042 <para>
10043 <bridgehead renderas="sect4" id="packaged_task_reset_bridgehead">
10044 <phrase id="packaged_task_reset"/>
10045 <link linkend="packaged_task_reset">Member
10046 function <code>reset</code>()</link>
10047 </bridgehead>
10048 </para>
10049 <programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">reset</phrase><phrase role="special">();</phrase>
10050 </programlisting>
10051 <variablelist>
10052 <title></title>
10053 <varlistentry>
10054 <term>Effects:</term>
10055 <listitem>
10056 <para>
10057 Resets the <link linkend="shared_state">shared state</link> and abandons
10058 the result of previous executions. A new shared state is constructed.
10059 </para>
10060 </listitem>
10061 </varlistentry>
10062 <varlistentry>
10063 <term>Throws:</term>
10064 <listitem>
10065 <para>
10066 <code><phrase role="identifier">future_error</phrase></code> with
10067 <code><phrase role="identifier">future_errc</phrase><phrase role="special">::</phrase><phrase
10068 role="identifier">no_state</phrase></code>.
10069 </para>
10070 </listitem>
10071 </varlistentry>
10072 </variablelist>
10073 <para>
10074 <bridgehead renderas="sect4" id="swap_for_packaged_task_bridgehead">
10075 <phrase id="swap_for_packaged_task"/>
10076 <link linkend="swap_for_packaged_task">Non-member
10077 function <code>swap()</code></link>
10078 </bridgehead>
10079 </para>
10080 <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>
10081 <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>
10082 </programlisting>
10083 <variablelist>
10084 <title></title>
10085 <varlistentry>
10086 <term>Effects:</term>
10087 <listitem>
10088 <para>
10089 Same as <code><phrase role="identifier">l</phrase><phrase role="special">.</phrase><phrase
10090 role="identifier">swap</phrase><phrase role="special">(</phrase>
10091 <phrase role="identifier">r</phrase><phrase role="special">)</phrase></code>.
10092 </para>
10093 </listitem>
10094 </varlistentry>
10095 </variablelist>
10096 </section>
10097 </section>
10098 </section>
10099 <section id="fiber.fls">
10100 <title><link linkend="fiber.fls">Fiber local storage</link></title>
10101 <bridgehead renderas="sect3" id="fiber.fls.h0">
10102 <phrase id="fiber.fls.synopsis"/><link linkend="fiber.fls.synopsis">Synopsis</link>
10103 </bridgehead>
10104 <para>
10105 Fiber local storage allows a separate instance of a given data item for each
10106 fiber.
10107 </para>
10108 <bridgehead renderas="sect3" id="fiber.fls.h1">
10109 <phrase id="fiber.fls.cleanup_at_fiber_exit"/><link linkend="fiber.fls.cleanup_at_fiber_exit">Cleanup
10110 at fiber exit</link>
10111 </bridgehead>
10112 <para>
10113 When a fiber exits, the objects associated with each <link linkend="class_fiber_specific_ptr"><code>fiber_specific_ptr</code></link> instance
10114 are destroyed. By default, the object pointed to by a pointer <code><phrase
10115 role="identifier">p</phrase></code> is destroyed by invoking <code><phrase
10116 role="keyword">delete</phrase> <phrase role="identifier">p</phrase></code>,
10117 but this can be overridden for a specific instance of <link linkend="class_fiber_specific_ptr"><code>fiber_specific_ptr</code></link> by
10118 providing a cleanup routine <code><phrase role="identifier">func</phrase></code>
10119 to the constructor. In this case, the object is destroyed by invoking <code><phrase
10120 role="identifier">func</phrase><phrase role="special">(</phrase><phrase role="identifier">p</phrase><phrase
10121 role="special">)</phrase></code>. The cleanup functions are called in an unspecified
10122 order.
10123 </para>
10124 <para>
10125 <bridgehead renderas="sect4" id="class_fiber_specific_ptr_bridgehead">
10126 <phrase id="class_fiber_specific_ptr"/>
10127 <link linkend="class_fiber_specific_ptr">Class
10128 <code>fiber_specific_ptr</code></link>
10129 </bridgehead>
10130 </para>
10131 <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>
10132
10133 <phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase>
10134 <phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase>
10135
10136 <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>
10137 <phrase role="keyword">class</phrase> <phrase role="identifier">fiber_specific_ptr</phrase> <phrase role="special">{</phrase>
10138 <phrase role="keyword">public</phrase><phrase role="special">:</phrase>
10139 <phrase role="keyword">typedef</phrase> <phrase role="identifier">T</phrase> <phrase role="identifier">element_type</phrase><phrase role="special">;</phrase>
10140
10141 <phrase role="identifier">fiber_specific_ptr</phrase><phrase role="special">();</phrase>
10142
10143 <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>
10144
10145 <phrase role="special">~</phrase><phrase role="identifier">fiber_specific_ptr</phrase><phrase role="special">();</phrase>
10146
10147 <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>
10148 <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>
10149
10150 <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>
10151
10152 <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>
10153
10154 <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>
10155
10156 <phrase role="identifier">T</phrase> <phrase role="special">*</phrase> <phrase role="identifier">release</phrase><phrase role="special">();</phrase>
10157
10158 <phrase role="keyword">void</phrase> <phrase role="identifier">reset</phrase><phrase role="special">(</phrase> <phrase role="identifier">T</phrase> <phrase role="special">*);</phrase>
10159 <phrase role="special">};</phrase>
10160
10161 <phrase role="special">}}</phrase>
10162 </programlisting>
10163 <bridgehead renderas="sect3" id="fiber.fls.h2">
10164 <phrase id="fiber.fls.constructor"/><link linkend="fiber.fls.constructor">Constructor</link>
10165 </bridgehead>
10166 <programlisting><phrase role="identifier">fiber_specific_ptr</phrase><phrase role="special">();</phrase>
10167 <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>
10168 </programlisting>
10169 <variablelist>
10170 <title></title>
10171 <varlistentry>
10172 <term>Requires:</term>
10173 <listitem>
10174 <para>
10175 <code><phrase role="keyword">delete</phrase> <phrase role="keyword">this</phrase><phrase
10176 role="special">-&gt;</phrase><phrase role="identifier">get</phrase><phrase
10177 role="special">()</phrase></code> is well-formed; <code><phrase role="identifier">fn</phrase><phrase
10178 role="special">(</phrase><phrase role="keyword">this</phrase><phrase
10179 role="special">-&gt;</phrase><phrase role="identifier">get</phrase><phrase
10180 role="special">())</phrase></code> does not throw
10181 </para>
10182 </listitem>
10183 </varlistentry>
10184 <varlistentry>
10185 <term>Effects:</term>
10186 <listitem>
10187 <para>
10188 Construct a <link linkend="class_fiber_specific_ptr"><code>fiber_specific_ptr</code></link> object for storing
10189 a pointer to an object of type <code><phrase role="identifier">T</phrase></code>
10190 specific to each fiber. When <code><phrase role="identifier">reset</phrase><phrase
10191 role="special">()</phrase></code> is called, or the fiber exits, <link linkend="class_fiber_specific_ptr"><code>fiber_specific_ptr</code></link> calls
10192 <code><phrase role="identifier">fn</phrase><phrase role="special">(</phrase><phrase
10193 role="keyword">this</phrase><phrase role="special">-&gt;</phrase><phrase
10194 role="identifier">get</phrase><phrase role="special">())</phrase></code>.
10195 If the no-arguments constructor is used, the default <code><phrase role="keyword">delete</phrase></code>-based
10196 cleanup function will be used to destroy the fiber-local objects.
10197 </para>
10198 </listitem>
10199 </varlistentry>
10200 <varlistentry>
10201 <term>Throws:</term>
10202 <listitem>
10203 <para>
10204 <code><phrase role="identifier">fiber_error</phrase></code> if an error
10205 occurs.
10206 </para>
10207 </listitem>
10208 </varlistentry>
10209 </variablelist>
10210 <bridgehead renderas="sect3" id="fiber.fls.h3">
10211 <phrase id="fiber.fls.destructor"/><link linkend="fiber.fls.destructor">Destructor</link>
10212 </bridgehead>
10213 <programlisting><phrase role="special">~</phrase><phrase role="identifier">fiber_specific_ptr</phrase><phrase role="special">();</phrase>
10214 </programlisting>
10215 <variablelist>
10216 <title></title>
10217 <varlistentry>
10218 <term>Requires:</term>
10219 <listitem>
10220 <para>
10221 All the fiber specific instances associated to this <link linkend="class_fiber_specific_ptr"><code>fiber_specific_ptr</code></link>
10222 (except
10223 maybe the one associated to this fiber) must be nullptr.
10224 </para>
10225 </listitem>
10226 </varlistentry>
10227 <varlistentry>
10228 <term>Effects:</term>
10229 <listitem>
10230 <para>
10231 Calls <code><phrase role="keyword">this</phrase><phrase role="special">-&gt;</phrase><phrase
10232 role="identifier">reset</phrase><phrase role="special">()</phrase></code>
10233 to clean up the associated value for the current fiber, and destroys
10234 <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>.
10235 </para>
10236 </listitem>
10237 </varlistentry>
10238 <varlistentry>
10239 <term>Remarks:</term>
10240 <listitem>
10241 <para>
10242 The requirement is an implementation restriction. If the destructor promised
10243 to delete instances for all fibers, the implementation would be forced
10244 to maintain a list of all the fibers having an associated specific ptr,
10245 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
10246 outlive the fibers that use it.
10247 </para>
10248 </listitem>
10249 </varlistentry>
10250 </variablelist>
10251 <note>
10252 <para>
10253 Care needs to be taken to ensure that any fibers still running after an instance
10254 of <link linkend="class_fiber_specific_ptr"><code>fiber_specific_ptr</code></link> has been destroyed do not call
10255 any member functions on that instance.
10256 </para>
10257 </note>
10258 <para>
10259 <bridgehead renderas="sect4" id="fiber_specific_ptr_get_bridgehead">
10260 <phrase id="fiber_specific_ptr_get"/>
10261 <link linkend="fiber_specific_ptr_get">Member
10262 function <code>get</code>()</link>
10263 </bridgehead>
10264 </para>
10265 <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>
10266 </programlisting>
10267 <variablelist>
10268 <title></title>
10269 <varlistentry>
10270 <term>Returns:</term>
10271 <listitem>
10272 <para>
10273 The pointer associated with the current fiber.
10274 </para>
10275 </listitem>
10276 </varlistentry>
10277 <varlistentry>
10278 <term>Throws:</term>
10279 <listitem>
10280 <para>
10281 Nothing.
10282 </para>
10283 </listitem>
10284 </varlistentry>
10285 </variablelist>
10286 <note>
10287 <para>
10288 The initial value associated with an instance of <link linkend="class_fiber_specific_ptr"><code>fiber_specific_ptr</code></link> is
10289 <code><phrase role="keyword">nullptr</phrase></code> for each fiber.
10290 </para>
10291 </note>
10292 <para>
10293 <bridgehead renderas="sect4" id="fiber_specific_ptr_operator_arrow_bridgehead">
10294 <phrase id="fiber_specific_ptr_operator_arrow"/>
10295 <link linkend="fiber_specific_ptr_operator_arrow">Member
10296 function <code>operator-&gt;</code>()</link>
10297 </bridgehead>
10298 </para>
10299 <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>
10300 </programlisting>
10301 <variablelist>
10302 <title></title>
10303 <varlistentry>
10304 <term>Requires:</term>
10305 <listitem>
10306 <para>
10307 <code><phrase role="keyword">this</phrase><phrase role="special">-&gt;</phrase><phrase
10308 role="identifier">get</phrase><phrase role="special">()</phrase></code>
10309 is not <code><phrase role="keyword">nullptr</phrase></code>.
10310 </para>
10311 </listitem>
10312 </varlistentry>
10313 <varlistentry>
10314 <term>Returns:</term>
10315 <listitem>
10316 <para>
10317 <code><phrase role="keyword">this</phrase><phrase role="special">-&gt;</phrase><phrase
10318 role="identifier">get</phrase><phrase role="special">()</phrase></code>
10319 </para>
10320 </listitem>
10321 </varlistentry>
10322 <varlistentry>
10323 <term>Throws:</term>
10324 <listitem>
10325 <para>
10326 Nothing.
10327 </para>
10328 </listitem>
10329 </varlistentry>
10330 </variablelist>
10331 <para>
10332 <bridgehead renderas="sect4" id="fiber_specific_ptr_operator_star_bridgehead">
10333 <phrase id="fiber_specific_ptr_operator_star"/>
10334 <link linkend="fiber_specific_ptr_operator_star">Member
10335 function <code>operator*</code>()</link>
10336 </bridgehead>
10337 </para>
10338 <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>
10339 </programlisting>
10340 <variablelist>
10341 <title></title>
10342 <varlistentry>
10343 <term>Requires:</term>
10344 <listitem>
10345 <para>
10346 <code><phrase role="keyword">this</phrase><phrase role="special">-&gt;</phrase><phrase
10347 role="identifier">get</phrase><phrase role="special">()</phrase></code>
10348 is not <code><phrase role="keyword">nullptr</phrase></code>.
10349 </para>
10350 </listitem>
10351 </varlistentry>
10352 <varlistentry>
10353 <term>Returns:</term>
10354 <listitem>
10355 <para>
10356 <code><phrase role="special">*(</phrase><phrase role="keyword">this</phrase><phrase
10357 role="special">-&gt;</phrase><phrase role="identifier">get</phrase><phrase
10358 role="special">())</phrase></code>
10359 </para>
10360 </listitem>
10361 </varlistentry>
10362 <varlistentry>
10363 <term>Throws:</term>
10364 <listitem>
10365 <para>
10366 Nothing.
10367 </para>
10368 </listitem>
10369 </varlistentry>
10370 </variablelist>
10371 <para>
10372 <bridgehead renderas="sect4" id="fiber_specific_ptr_release_bridgehead">
10373 <phrase id="fiber_specific_ptr_release"/>
10374 <link linkend="fiber_specific_ptr_release">Member
10375 function <code>release</code>()</link>
10376 </bridgehead>
10377 </para>
10378 <programlisting><phrase role="identifier">T</phrase> <phrase role="special">*</phrase> <phrase role="identifier">release</phrase><phrase role="special">();</phrase>
10379 </programlisting>
10380 <variablelist>
10381 <title></title>
10382 <varlistentry>
10383 <term>Effects:</term>
10384 <listitem>
10385 <para>
10386 Return <code><phrase role="keyword">this</phrase><phrase role="special">-&gt;</phrase><phrase
10387 role="identifier">get</phrase><phrase role="special">()</phrase></code>
10388 and store <code><phrase role="keyword">nullptr</phrase></code> as the
10389 pointer associated with the current fiber without invoking the cleanup
10390 function.
10391 </para>
10392 </listitem>
10393 </varlistentry>
10394 <varlistentry>
10395 <term>Postcondition:</term>
10396 <listitem>
10397 <para>
10398 <code><phrase role="keyword">this</phrase><phrase role="special">-&gt;</phrase><phrase
10399 role="identifier">get</phrase><phrase role="special">()==</phrase><phrase
10400 role="keyword">nullptr</phrase></code>
10401 </para>
10402 </listitem>
10403 </varlistentry>
10404 <varlistentry>
10405 <term>Throws:</term>
10406 <listitem>
10407 <para>
10408 Nothing.
10409 </para>
10410 </listitem>
10411 </varlistentry>
10412 </variablelist>
10413 <para>
10414 <bridgehead renderas="sect4" id="fiber_specific_ptr_reset_bridgehead">
10415 <phrase id="fiber_specific_ptr_reset"/>
10416 <link linkend="fiber_specific_ptr_reset">Member
10417 function <code>reset</code>()</link>
10418 </bridgehead>
10419 </para>
10420 <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>
10421 </programlisting>
10422 <variablelist>
10423 <title></title>
10424 <varlistentry>
10425 <term>Effects:</term>
10426 <listitem>
10427 <para>
10428 If <code><phrase role="keyword">this</phrase><phrase role="special">-&gt;</phrase><phrase
10429 role="identifier">get</phrase><phrase role="special">()!=</phrase><phrase
10430 role="identifier">new_value</phrase></code> and <code><phrase role="keyword">this</phrase><phrase
10431 role="special">-&gt;</phrase><phrase role="identifier">get</phrase><phrase
10432 role="special">()</phrase></code> is not <code><phrase role="keyword">nullptr</phrase></code>,
10433 invoke <code><phrase role="keyword">delete</phrase> <phrase role="keyword">this</phrase><phrase
10434 role="special">-&gt;</phrase><phrase role="identifier">get</phrase><phrase
10435 role="special">()</phrase></code> or <code><phrase role="identifier">fn</phrase><phrase
10436 role="special">(</phrase><phrase role="keyword">this</phrase><phrase
10437 role="special">-&gt;</phrase><phrase role="identifier">get</phrase><phrase
10438 role="special">())</phrase></code> as appropriate. Store <code><phrase
10439 role="identifier">new_value</phrase></code> as the pointer associated
10440 with the current fiber.
10441 </para>
10442 </listitem>
10443 </varlistentry>
10444 <varlistentry>
10445 <term>Postcondition:</term>
10446 <listitem>
10447 <para>
10448 <code><phrase role="keyword">this</phrase><phrase role="special">-&gt;</phrase><phrase
10449 role="identifier">get</phrase><phrase role="special">()==</phrase><phrase
10450 role="identifier">new_value</phrase></code>
10451 </para>
10452 </listitem>
10453 </varlistentry>
10454 <varlistentry>
10455 <term>Throws:</term>
10456 <listitem>
10457 <para>
10458 Exception raised during cleanup of previous value.
10459 </para>
10460 </listitem>
10461 </varlistentry>
10462 </variablelist>
10463 </section>
10464 <section id="fiber.migration">
10465 <title><anchor id="migration"/><link linkend="fiber.migration">Migrating fibers
10466 between threads</link></title>
10467 <bridgehead renderas="sect3" id="fiber.migration.h0">
10468 <phrase id="fiber.migration.overview"/><link linkend="fiber.migration.overview">Overview</link>
10469 </bridgehead>
10470 <para>
10471 Each fiber owns a stack and manages its execution state, including all registers
10472 and CPU flags, the instruction pointer and the stack pointer. That means, in
10473 general, a fiber is not bound to a specific thread.<footnote id="fiber.migration.f0">
10474 <para>
10475 The <quote>main</quote> fiber on each thread, that is, the fiber on which
10476 the thread is launched, cannot migrate to any other thread. Also <emphasis
10477 role="bold">Boost.Fiber</emphasis> implicitly creates a dispatcher fiber
10478 for each thread &mdash; this cannot migrate either.
10479 </para>
10480 </footnote><superscript>,</superscript><footnote id="fiber.migration.f1">
10481 <para>
10482 Of course it would be problematic to migrate a fiber that relies on <link
10483 linkend="thread_local_storage">thread-local storage</link>.
10484 </para>
10485 </footnote>
10486 </para>
10487 <para>
10488 Migrating a fiber from a logical CPU with heavy workload to another logical
10489 CPU with a lighter workload might speed up the overall execution. Note that
10490 in the case of NUMA-architectures, it is not always advisable to migrate data
10491 between threads. Suppose fiber <emphasis>f</emphasis> is running on logical
10492 CPU <emphasis>cpu0</emphasis> which belongs to NUMA node <emphasis>node0</emphasis>.
10493 The data of <emphasis>f</emphasis> are allocated on the physical memory located
10494 at <emphasis>node0</emphasis>. Migrating the fiber from <emphasis>cpu0</emphasis>
10495 to another logical CPU <emphasis>cpuX</emphasis> which is part of a different
10496 NUMA node <emphasis>nodeX</emphasis> might reduce the performance of the application
10497 due to increased latency of memory access.
10498 </para>
10499 <para>
10500 Only fibers that are contained in <link linkend="class_algorithm"><code>algorithm</code></link>&#8217;s ready queue can
10501 migrate between threads. You cannot migrate a running fiber, nor one that is
10502 <link linkend="blocking"><emphasis>blocked</emphasis></link>. You cannot migrate
10503 a fiber if its <link linkend="context_is_context"><code>context::is_context()</code></link> method returns <code><phrase
10504 role="keyword">true</phrase></code> for <code><phrase role="identifier">pinned_context</phrase></code>.
10505 </para>
10506 <para>
10507 In <emphasis role="bold">Boost.Fiber</emphasis> a fiber is migrated by invoking
10508 <link linkend="context_detach"><code>context::detach()</code></link> on the thread from which the fiber migrates
10509 and <link linkend="context_attach"><code>context::attach()</code></link> on the thread to which the fiber migrates.
10510 </para>
10511 <para>
10512 Thus, fiber migration is accomplished by sharing state between instances of
10513 a user-coded <link linkend="class_algorithm"><code>algorithm</code></link> implementation running on different threads.
10514 The fiber&#8217;s original thread calls <link linkend="algorithm_awakened"><code>algorithm::awakened()</code></link>, passing
10515 the fiber&#8217;s <link linkend="class_context"><code>context</code></link><literal>*</literal>. The <code><phrase role="identifier">awakened</phrase><phrase
10516 role="special">()</phrase></code> implementation calls <link linkend="context_detach"><code>context::detach()</code></link>.
10517 </para>
10518 <para>
10519 At some later point, when the same or a different thread calls <link linkend="algorithm_pick_next"><code>algorithm::pick_next()</code></link>,
10520 the <code><phrase role="identifier">pick_next</phrase><phrase role="special">()</phrase></code>
10521 implementation selects a ready fiber and calls <link linkend="context_attach"><code>context::attach()</code></link> on
10522 it before returning it.
10523 </para>
10524 <para>
10525 As stated above, a <code><phrase role="identifier">context</phrase></code>
10526 for which <code><phrase role="identifier">is_context</phrase><phrase role="special">(</phrase><phrase
10527 role="identifier">pinned_context</phrase><phrase role="special">)</phrase>
10528 <phrase role="special">==</phrase> <phrase role="keyword">true</phrase></code>
10529 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>.
10530 It may only be returned from <code><phrase role="identifier">pick_next</phrase><phrase
10531 role="special">()</phrase></code> called by the <emphasis>same</emphasis> thread
10532 that passed that context to <code><phrase role="identifier">awakened</phrase><phrase
10533 role="special">()</phrase></code>.
10534 </para>
10535 <bridgehead renderas="sect3" id="fiber.migration.h1">
10536 <phrase id="fiber.migration.example_of_work_sharing"/><link linkend="fiber.migration.example_of_work_sharing">Example
10537 of work sharing</link>
10538 </bridgehead>
10539 <para>
10540 In the example <ulink url="../../examples/work_sharing.cpp">work_sharing.cpp</ulink>
10541 multiple worker fibers are created on the main thread. Each fiber gets a character
10542 as parameter at construction. This character is printed out ten times. Between
10543 each iteration the fiber calls <link linkend="this_fiber_yield"><code>this_fiber::yield()</code></link>. That puts
10544 the fiber in the ready queue of the fiber-scheduler <emphasis>shared_ready_queue</emphasis>,
10545 running in the current thread. The next fiber ready to be executed is dequeued
10546 from the shared ready queue and resumed by <emphasis>shared_ready_queue</emphasis>
10547 running on <emphasis>any participating thread</emphasis>.
10548 </para>
10549 <para>
10550 All instances of <emphasis>shared_ready_queue</emphasis> share one global concurrent
10551 queue, used as ready queue. This mechanism shares all worker fibers between
10552 all instances of <emphasis>shared_ready_queue</emphasis>, thus between all
10553 participating threads.
10554 </para>
10555 <bridgehead renderas="sect3" id="fiber.migration.h2">
10556 <phrase id="fiber.migration.setup_of_threads_and_fibers"/><link linkend="fiber.migration.setup_of_threads_and_fibers">Setup
10557 of threads and fibers</link>
10558 </bridgehead>
10559 <para>
10560 In <code><phrase role="identifier">main</phrase><phrase role="special">()</phrase></code>
10561 the fiber-scheduler is installed and the worker fibers and the threads are
10562 launched.
10563 </para>
10564 <para>
10565 <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" />
10566
10567 <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" />
10568 <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>
10569 <phrase role="special">++</phrase><phrase role="identifier">fiber_count</phrase><phrase role="special">;</phrase> <co id="fiber.migration.c4" linkends="fiber.migration.c5" />
10570 <phrase role="special">}</phrase>
10571 <phrase role="identifier">barrier</phrase> <phrase role="identifier">b</phrase><phrase role="special">(</phrase> <phrase role="number">4</phrase><phrase role="special">);</phrase>
10572 <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" />
10573 <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>
10574 <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>
10575 <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>
10576 <phrase role="special">};</phrase>
10577 <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" />
10578 <phrase role="special">{</phrase>
10579 <phrase role="identifier">lock_t</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>
10580 <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" />
10581 <phrase role="special">}</phrase> <co id="fiber.migration.c14" linkends="fiber.migration.c15" />
10582 <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>
10583 <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" />
10584 <phrase role="identifier">t</phrase><phrase role="special">.</phrase><phrase role="identifier">join</phrase><phrase role="special">();</phrase>
10585 <phrase role="special">}</phrase>
10586 </programlisting>
10587 </para>
10588 <calloutlist>
10589 <callout arearefs="fiber.migration.c0" id="fiber.migration.c1">
10590 <para>
10591 Install the scheduling algorithm <code><phrase role="identifier">boost</phrase><phrase
10592 role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase
10593 role="special">::</phrase><phrase role="identifier">algo</phrase><phrase
10594 role="special">::</phrase><phrase role="identifier">shared_work</phrase></code>
10595 in the main thread too, so each new fiber gets launched into the shared
10596 pool.
10597 </para>
10598 </callout>
10599 <callout arearefs="fiber.migration.c2" id="fiber.migration.c3">
10600 <para>
10601 Launch a number of worker fibers; each worker fiber picks up a character
10602 that is passed as parameter to fiber-function <code><phrase role="identifier">whatevah</phrase></code>.
10603 Each worker fiber gets detached.
10604 </para>
10605 </callout>
10606 <callout arearefs="fiber.migration.c4" id="fiber.migration.c5">
10607 <para>
10608 Increment fiber counter for each new fiber.
10609 </para>
10610 </callout>
10611 <callout arearefs="fiber.migration.c6" id="fiber.migration.c7">
10612 <para>
10613 Launch a couple of threads that join the work sharing.
10614 </para>
10615 </callout>
10616 <callout arearefs="fiber.migration.c8" id="fiber.migration.c9">
10617 <para>
10618 sync with other threads: allow them to start processing
10619 </para>
10620 </callout>
10621 <callout arearefs="fiber.migration.c10" id="fiber.migration.c11">
10622 <para>
10623 <code><phrase role="identifier">lock_t</phrase></code> is typedef'ed as
10624 <ulink url="http://en.cppreference.com/w/cpp/thread/unique_lock"><code><phrase
10625 role="identifier">std</phrase><phrase role="special">::</phrase><phrase
10626 role="identifier">unique_lock</phrase></code></ulink>&lt; <ulink url="http://en.cppreference.com/w/cpp/thread/mutex"><code><phrase
10627 role="identifier">std</phrase><phrase role="special">::</phrase><phrase
10628 role="identifier">mutex</phrase></code></ulink> &gt;
10629 </para>
10630 </callout>
10631 <callout arearefs="fiber.migration.c12" id="fiber.migration.c13">
10632 <para>
10633 Suspend main fiber and resume worker fibers in the meanwhile. Main fiber
10634 gets resumed (e.g returns from <code><phrase role="identifier">condition_variable_any</phrase><phrase
10635 role="special">::</phrase><phrase role="identifier">wait</phrase><phrase
10636 role="special">()</phrase></code>) if all worker fibers are complete.
10637 </para>
10638 </callout>
10639 <callout arearefs="fiber.migration.c14" id="fiber.migration.c15">
10640 <para>
10641 Releasing lock of mtx_count is required before joining the threads, otherwise
10642 the other threads would be blocked inside condition_variable::wait() and
10643 would never return (deadlock).
10644 </para>
10645 </callout>
10646 <callout arearefs="fiber.migration.c16" id="fiber.migration.c17">
10647 <para>
10648 wait for threads to terminate
10649 </para>
10650 </callout>
10651 </calloutlist>
10652 <para>
10653 The start of the threads is synchronized with a barrier. The main fiber of
10654 each thread (including main thread) is suspended until all worker fibers are
10655 complete. When the main fiber returns from <link linkend="condition_variable_wait"><code>condition_variable::wait()</code></link>,
10656 the thread terminates: the main thread joins all other threads.
10657 </para>
10658 <para>
10659 <programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">thread</phrase><phrase role="special">(</phrase> <phrase role="identifier">barrier</phrase> <phrase role="special">*</phrase> <phrase role="identifier">b</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
10660 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">ostringstream</phrase> <phrase role="identifier">buffer</phrase><phrase role="special">;</phrase>
10661 <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>
10662 <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>
10663 <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" />
10664 <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" />
10665 <phrase role="identifier">lock_t</phrase> <phrase role="identifier">lk</phrase><phrase role="special">(</phrase> <phrase role="identifier">mtx_count</phrase><phrase role="special">);</phrase>
10666 <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" />
10667 <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>
10668 <phrase role="special">}</phrase>
10669 </programlisting>
10670 </para>
10671 <calloutlist>
10672 <callout arearefs="fiber.migration.c18" id="fiber.migration.c19">
10673 <para>
10674 Install the scheduling algorithm <code><phrase role="identifier">boost</phrase><phrase
10675 role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase
10676 role="special">::</phrase><phrase role="identifier">algo</phrase><phrase
10677 role="special">::</phrase><phrase role="identifier">shared_work</phrase></code>
10678 in order to join the work sharing.
10679 </para>
10680 </callout>
10681 <callout arearefs="fiber.migration.c20" id="fiber.migration.c21">
10682 <para>
10683 sync with other threads: allow them to start processing
10684 </para>
10685 </callout>
10686 <callout arearefs="fiber.migration.c22" id="fiber.migration.c23">
10687 <para>
10688 Suspend main fiber and resume worker fibers in the meanwhile. Main fiber
10689 gets resumed (e.g returns from <code><phrase role="identifier">condition_variable_any</phrase><phrase
10690 role="special">::</phrase><phrase role="identifier">wait</phrase><phrase
10691 role="special">()</phrase></code>) if all worker fibers are complete.
10692 </para>
10693 </callout>
10694 </calloutlist>
10695 <para>
10696 Each worker fiber executes function <code><phrase role="identifier">whatevah</phrase><phrase
10697 role="special">()</phrase></code> with character <code><phrase role="identifier">me</phrase></code>
10698 as parameter. The fiber yields in a loop and prints out a message if it was
10699 migrated to another thread.
10700 </para>
10701 <para>
10702 <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>
10703 <phrase role="keyword">try</phrase> <phrase role="special">{</phrase>
10704 <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" />
10705 <phrase role="special">{</phrase>
10706 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">ostringstream</phrase> <phrase role="identifier">buffer</phrase><phrase role="special">;</phrase>
10707 <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>
10708 <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>
10709 <phrase role="special">}</phrase>
10710 <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" />
10711 <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" />
10712 <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" />
10713 <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" />
10714 <phrase role="identifier">my_thread</phrase> <phrase role="special">=</phrase> <phrase role="identifier">new_thread</phrase><phrase role="special">;</phrase>
10715 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">ostringstream</phrase> <phrase role="identifier">buffer</phrase><phrase role="special">;</phrase>
10716 <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>
10717 <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>
10718 <phrase role="special">}</phrase>
10719 <phrase role="special">}</phrase>
10720 <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>
10721 <phrase role="special">}</phrase>
10722 <phrase role="identifier">lock_t</phrase> <phrase role="identifier">lk</phrase><phrase role="special">(</phrase> <phrase role="identifier">mtx_count</phrase><phrase role="special">);</phrase>
10723 <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" />
10724 <phrase role="identifier">lk</phrase><phrase role="special">.</phrase><phrase role="identifier">unlock</phrase><phrase role="special">();</phrase>
10725 <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" />
10726 <phrase role="special">}</phrase>
10727 <phrase role="special">}</phrase>
10728 </programlisting>
10729 </para>
10730 <calloutlist>
10731 <callout arearefs="fiber.migration.c24" id="fiber.migration.c25">
10732 <para>
10733 get ID of initial thread
10734 </para>
10735 </callout>
10736 <callout arearefs="fiber.migration.c26" id="fiber.migration.c27">
10737 <para>
10738 loop ten times
10739 </para>
10740 </callout>
10741 <callout arearefs="fiber.migration.c28" id="fiber.migration.c29">
10742 <para>
10743 yield to other fibers
10744 </para>
10745 </callout>
10746 <callout arearefs="fiber.migration.c30" id="fiber.migration.c31">
10747 <para>
10748 get ID of current thread
10749 </para>
10750 </callout>
10751 <callout arearefs="fiber.migration.c32" id="fiber.migration.c33">
10752 <para>
10753 test if fiber was migrated to another thread
10754 </para>
10755 </callout>
10756 <callout arearefs="fiber.migration.c34" id="fiber.migration.c35">
10757 <para>
10758 Decrement fiber counter for each completed fiber.
10759 </para>
10760 </callout>
10761 <callout arearefs="fiber.migration.c36" id="fiber.migration.c37">
10762 <para>
10763 Notify all fibers waiting on <code><phrase role="identifier">cnd_count</phrase></code>.
10764 </para>
10765 </callout>
10766 </calloutlist>
10767 <bridgehead renderas="sect3" id="fiber.migration.h3">
10768 <phrase id="fiber.migration.scheduling_fibers"/><link linkend="fiber.migration.scheduling_fibers">Scheduling
10769 fibers</link>
10770 </bridgehead>
10771 <para>
10772 The fiber scheduler <code><phrase role="identifier">shared_ready_queue</phrase></code>
10773 is like <code><phrase role="identifier">round_robin</phrase></code>, except
10774 that it shares a common ready queue among all participating threads. A thread
10775 participates in this pool by executing <link linkend="use_scheduling_algorithm"><code>use_scheduling_algorithm()</code></link>
10776 before
10777 any other <emphasis role="bold">Boost.Fiber</emphasis> operation.
10778 </para>
10779 <para>
10780 The important point about the ready queue is that it&#8217;s a class static, common
10781 to all instances of shared_ready_queue. Fibers that are enqueued via <link linkend="algorithm_awakened"><code>algorithm::awakened()</code></link> (fibers
10782 that are ready to be resumed) are thus available to all threads. It is required
10783 to reserve a separate, scheduler-specific queue for the thread&#8217;s main fiber
10784 and dispatcher fibers: these may <emphasis>not</emphasis> be shared between
10785 threads! When we&#8217;re passed either of these fibers, push it there instead of
10786 in the shared queue: it would be Bad News for thread B to retrieve and attempt
10787 to execute thread A&#8217;s main fiber.
10788 </para>
10789 <para>
10790 [awakened_ws]
10791 </para>
10792 <para>
10793 When <link linkend="algorithm_pick_next"><code>algorithm::pick_next()</code></link> gets called inside one thread,
10794 a fiber is dequeued from <emphasis>rqueue_</emphasis> and will be resumed in
10795 that thread.
10796 </para>
10797 <para>
10798 [pick_next_ws]
10799 </para>
10800 <para>
10801 The source code above is found in <ulink url="../../examples/work_sharing.cpp">work_sharing.cpp</ulink>.
10802 </para>
10803 </section>
10804 <section id="fiber.callbacks">
10805 <title><anchor id="callbacks"/><link linkend="fiber.callbacks">Integrating Fibers
10806 with Asynchronous Callbacks</link></title>
10807 <section id="fiber.callbacks.overview">
10808 <title><link linkend="fiber.callbacks.overview">Overview</link></title>
10809 <para>
10810 One of the primary benefits of <emphasis role="bold">Boost.Fiber</emphasis>
10811 is the ability to use asynchronous operations for efficiency, while at the
10812 same time structuring the calling code <emphasis>as if</emphasis> the operations
10813 were synchronous. Asynchronous operations provide completion notification
10814 in a variety of ways, but most involve a callback function of some kind.
10815 This section discusses tactics for interfacing <emphasis role="bold">Boost.Fiber</emphasis>
10816 with an arbitrary async operation.
10817 </para>
10818 <para>
10819 For purposes of illustration, consider the following hypothetical API:
10820 </para>
10821 <para>
10822 <programlisting><phrase role="keyword">class</phrase> <phrase role="identifier">AsyncAPI</phrase> <phrase role="special">{</phrase>
10823 <phrase role="keyword">public</phrase><phrase role="special">:</phrase>
10824 <phrase role="comment">// constructor acquires some resource that can be read and written</phrase>
10825 <phrase role="identifier">AsyncAPI</phrase><phrase role="special">();</phrase>
10826
10827 <phrase role="comment">// callbacks accept an int error code; 0 == success</phrase>
10828 <phrase role="keyword">typedef</phrase> <phrase role="keyword">int</phrase> <phrase role="identifier">errorcode</phrase><phrase role="special">;</phrase>
10829
10830 <phrase role="comment">// write callback only needs to indicate success or failure</phrase>
10831 <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>
10832 <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>
10833
10834 <phrase role="comment">// read callback needs to accept both errorcode and data</phrase>
10835 <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>
10836 <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>
10837
10838 <phrase role="comment">// ... other operations ...</phrase>
10839 <phrase role="special">};</phrase>
10840 </programlisting>
10841 </para>
10842 <para>
10843 The significant points about each of <code><phrase role="identifier">init_write</phrase><phrase
10844 role="special">()</phrase></code> and <code><phrase role="identifier">init_read</phrase><phrase
10845 role="special">()</phrase></code> are:
10846 </para>
10847 <itemizedlist>
10848 <listitem>
10849 <simpara>
10850 The <code><phrase role="identifier">AsyncAPI</phrase></code> method only
10851 initiates the operation. It returns immediately, while the requested
10852 operation is still pending.
10853 </simpara>
10854 </listitem>
10855 <listitem>
10856 <simpara>
10857 The method accepts a callback. When the operation completes, the callback
10858 is called with relevant parameters (error code, data if applicable).
10859 </simpara>
10860 </listitem>
10861 </itemizedlist>
10862 <para>
10863 We would like to wrap these asynchronous methods in functions that appear
10864 synchronous by blocking the calling fiber until the operation completes.
10865 This lets us use the wrapper function&#8217;s return value to deliver relevant data.
10866 </para>
10867 <tip>
10868 <para>
10869 <link linkend="class_promise"><code>promise&lt;&gt;</code></link> and <link linkend="class_future"><code>future&lt;&gt;</code></link> are your friends
10870 here.
10871 </para>
10872 </tip>
10873 </section>
10874 <section id="fiber.callbacks.return_errorcode">
10875 <title><link linkend="fiber.callbacks.return_errorcode">Return Errorcode</link></title>
10876 <para>
10877 The <code><phrase role="identifier">AsyncAPI</phrase><phrase role="special">::</phrase><phrase
10878 role="identifier">init_write</phrase><phrase role="special">()</phrase></code>
10879 callback passes only an <code><phrase role="identifier">errorcode</phrase></code>.
10880 If we simply want the blocking wrapper to return that <code><phrase role="identifier">errorcode</phrase></code>,
10881 this is an extremely straightforward use of <link linkend="class_promise"><code>promise&lt;&gt;</code></link> and
10882 <link linkend="class_future"><code>future&lt;&gt;</code></link>:
10883 </para>
10884 <para>
10885 <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>
10886 <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>
10887 <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>
10888 <phrase role="comment">// In general, even though we block waiting for future::get() and therefore</phrase>
10889 <phrase role="comment">// won't destroy 'promise' until promise::set_value() has been called, we</phrase>
10890 <phrase role="comment">// are advised that with threads it's possible for ~promise() to be</phrase>
10891 <phrase role="comment">// entered before promise::set_value() has returned. While that shouldn't</phrase>
10892 <phrase role="comment">// happen with fibers::promise, a robust way to deal with the lifespan</phrase>
10893 <phrase role="comment">// issue is to bind 'promise' into our lambda. Since promise is move-only,</phrase>
10894 <phrase role="comment">// use initialization capture.</phrase>
10895 <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>
10896 <phrase role="identifier">api</phrase><phrase role="special">.</phrase><phrase role="identifier">init_write</phrase><phrase role="special">(</phrase>
10897 <phrase role="identifier">data</phrase><phrase role="special">,</phrase>
10898 <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>
10899 <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>
10900 <phrase role="special">});</phrase>
10901
10902 <phrase role="preprocessor">#else</phrase> <phrase role="comment">// defined(BOOST_NO_CXX14_INITIALIZED_LAMBDA_CAPTURES)</phrase>
10903 <phrase role="identifier">api</phrase><phrase role="special">.</phrase><phrase role="identifier">init_write</phrase><phrase role="special">(</phrase>
10904 <phrase role="identifier">data</phrase><phrase role="special">,</phrase>
10905 <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>
10906 <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>
10907 <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>
10908 <phrase role="special">},</phrase>
10909 <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>
10910 <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>
10911 <phrase role="preprocessor">#endif</phrase> <phrase role="comment">// BOOST_NO_CXX14_INITIALIZED_LAMBDA_CAPTURES</phrase>
10912
10913 <phrase role="keyword">return</phrase> <phrase role="identifier">future</phrase><phrase role="special">.</phrase><phrase role="identifier">get</phrase><phrase role="special">();</phrase>
10914 <phrase role="special">}</phrase>
10915 </programlisting>
10916 </para>
10917 <para>
10918 All we have to do is:
10919 </para>
10920 <orderedlist>
10921 <listitem>
10922 <simpara>
10923 Instantiate a <code><phrase role="identifier">promise</phrase><phrase
10924 role="special">&lt;&gt;</phrase></code> of correct type.
10925 </simpara>
10926 </listitem>
10927 <listitem>
10928 <simpara>
10929 Obtain its <code><phrase role="identifier">future</phrase><phrase role="special">&lt;&gt;</phrase></code>.
10930 </simpara>
10931 </listitem>
10932 <listitem>
10933 <simpara>
10934 Arrange for the callback to call <link linkend="promise_set_value"><code>promise::set_value()</code></link>.
10935 </simpara>
10936 </listitem>
10937 <listitem>
10938 <simpara>
10939 Block on <link linkend="future_get"><code>future::get()</code></link>.
10940 </simpara>
10941 </listitem>
10942 </orderedlist>
10943 <note>
10944 <para>
10945 This tactic for resuming a pending fiber works even if the callback is
10946 called on a different thread than the one on which the initiating fiber
10947 is running. In fact, <ulink url="../../examples/adapt_callbacks.cpp">the
10948 example program&#8217;s</ulink> dummy <code><phrase role="identifier">AsyncAPI</phrase></code>
10949 implementation illustrates that: it simulates async I/O by launching a
10950 new thread that sleeps briefly and then calls the relevant callback.
10951 </para>
10952 </note>
10953 </section>
10954 <section id="fiber.callbacks.success_or_exception">
10955 <title><link linkend="fiber.callbacks.success_or_exception">Success or Exception</link></title>
10956 <para>
10957 A wrapper more aligned with modern C++ practice would use an exception, rather
10958 than an <code><phrase role="identifier">errorcode</phrase></code>, to communicate
10959 failure to its caller. This is straightforward to code in terms of <code><phrase
10960 role="identifier">write_ec</phrase><phrase role="special">()</phrase></code>:
10961 </para>
10962 <para>
10963 <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>
10964 <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>
10965 <phrase role="keyword">if</phrase> <phrase role="special">(</phrase> <phrase role="identifier">ec</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
10966 <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>
10967 <phrase role="special">}</phrase>
10968 <phrase role="special">}</phrase>
10969 </programlisting>
10970 </para>
10971 <para>
10972 The point is that since each fiber has its own stack, you need not repeat
10973 messy boilerplate: normal encapsulation works.
10974 </para>
10975 </section>
10976 <section id="fiber.callbacks.return_errorcode_or_data">
10977 <title><link linkend="fiber.callbacks.return_errorcode_or_data">Return Errorcode
10978 or Data</link></title>
10979 <para>
10980 Things get a bit more interesting when the async operation&#8217;s callback passes
10981 multiple data items of interest. One approach would be to use <code><phrase
10982 role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">pair</phrase><phrase
10983 role="special">&lt;&gt;</phrase></code> to capture both:
10984 </para>
10985 <para>
10986 <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>
10987 <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>
10988 <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>
10989 <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>
10990 <phrase role="comment">// We promise that both 'promise' and 'future' will survive until our</phrase>
10991 <phrase role="comment">// lambda has been called.</phrase>
10992 <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>
10993 <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>
10994 <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>
10995 <phrase role="special">});</phrase>
10996 <phrase role="preprocessor">#else</phrase> <phrase role="comment">// defined(BOOST_NO_CXX14_INITIALIZED_LAMBDA_CAPTURES)</phrase>
10997 <phrase role="identifier">api</phrase><phrase role="special">.</phrase><phrase role="identifier">init_read</phrase><phrase role="special">(</phrase>
10998 <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>
10999 <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>
11000 <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>
11001 <phrase role="special">},</phrase>
11002 <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>
11003 <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>
11004 <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>
11005 <phrase role="preprocessor">#endif</phrase> <phrase role="comment">// BOOST_NO_CXX14_INITIALIZED_LAMBDA_CAPTURES</phrase>
11006 <phrase role="keyword">return</phrase> <phrase role="identifier">future</phrase><phrase role="special">.</phrase><phrase role="identifier">get</phrase><phrase role="special">();</phrase>
11007 <phrase role="special">}</phrase>
11008 </programlisting>
11009 </para>
11010 <para>
11011 Once you bundle the interesting data in <code><phrase role="identifier">std</phrase><phrase
11012 role="special">::</phrase><phrase role="identifier">pair</phrase><phrase
11013 role="special">&lt;&gt;</phrase></code>, the code is effectively identical
11014 to <code><phrase role="identifier">write_ec</phrase><phrase role="special">()</phrase></code>.
11015 You can call it like this:
11016 </para>
11017 <para>
11018 <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>
11019 </programlisting>
11020 </para>
11021 </section>
11022 <section id="fiber.callbacks.data_or_exception">
11023 <title><anchor id="Data_or_Exception"/><link linkend="fiber.callbacks.data_or_exception">Data
11024 or Exception</link></title>
11025 <para>
11026 But a more natural API for a function that obtains data is to return only
11027 the data on success, throwing an exception on error.
11028 </para>
11029 <para>
11030 As with <code><phrase role="identifier">write</phrase><phrase role="special">()</phrase></code>
11031 above, it&#8217;s certainly possible to code a <code><phrase role="identifier">read</phrase><phrase
11032 role="special">()</phrase></code> wrapper in terms of <code><phrase role="identifier">read_ec</phrase><phrase
11033 role="special">()</phrase></code>. But since a given application is unlikely
11034 to need both, let&#8217;s code <code><phrase role="identifier">read</phrase><phrase
11035 role="special">()</phrase></code> from scratch, leveraging <link linkend="promise_set_exception"><code>promise::set_exception()</code></link>:
11036 </para>
11037 <para>
11038 <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>
11039 <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>
11040 <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>
11041 <phrase role="comment">// Both 'promise' and 'future' will survive until our lambda has been</phrase>
11042 <phrase role="comment">// called.</phrase>
11043 <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>
11044 <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>
11045 <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>
11046 <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>
11047 <phrase role="special">}</phrase> <phrase role="keyword">else</phrase> <phrase role="special">{</phrase>
11048 <phrase role="identifier">promise</phrase><phrase role="special">.</phrase><phrase role="identifier">set_exception</phrase><phrase role="special">(</phrase>
11049 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">make_exception_ptr</phrase><phrase role="special">(</phrase>
11050 <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>
11051 <phrase role="special">}</phrase>
11052 <phrase role="special">});</phrase>
11053 <phrase role="preprocessor">#else</phrase> <phrase role="comment">// defined(BOOST_NO_CXX14_INITIALIZED_LAMBDA_CAPTURES)</phrase>
11054 <phrase role="identifier">api</phrase><phrase role="special">.</phrase><phrase role="identifier">init_read</phrase><phrase role="special">(</phrase>
11055 <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>
11056 <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>
11057 <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>
11058 <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>
11059 <phrase role="special">}</phrase> <phrase role="keyword">else</phrase> <phrase role="special">{</phrase>
11060 <phrase role="identifier">promise</phrase><phrase role="special">.</phrase><phrase role="identifier">set_exception</phrase><phrase role="special">(</phrase>
11061 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">make_exception_ptr</phrase><phrase role="special">(</phrase>
11062 <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>
11063 <phrase role="special">}</phrase>
11064 <phrase role="special">},</phrase>
11065 <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>
11066 <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>
11067 <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>
11068 <phrase role="preprocessor">#endif</phrase> <phrase role="comment">// BOOST_NO_CXX14_INITIALIZED_LAMBDA_CAPTURES</phrase>
11069 <phrase role="keyword">return</phrase> <phrase role="identifier">future</phrase><phrase role="special">.</phrase><phrase role="identifier">get</phrase><phrase role="special">();</phrase>
11070 <phrase role="special">}</phrase>
11071 </programlisting>
11072 </para>
11073 <para>
11074 <link linkend="future_get"><code>future::get()</code></link> will do the right thing, either returning <code><phrase
11075 role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase></code>
11076 or throwing an exception.
11077 </para>
11078 </section>
11079 <section id="fiber.callbacks.success_error_virtual_methods">
11080 <title><link linkend="fiber.callbacks.success_error_virtual_methods">Success/Error
11081 Virtual Methods</link></title>
11082 <para>
11083 One classic approach to completion notification is to define an abstract
11084 base class with <code><phrase role="identifier">success</phrase><phrase role="special">()</phrase></code>
11085 and <code><phrase role="identifier">error</phrase><phrase role="special">()</phrase></code>
11086 methods. Code wishing to perform async I/O must derive a subclass, override
11087 each of these methods and pass the async operation a pointer to a subclass
11088 instance. The abstract base class might look like this:
11089 </para>
11090 <para>
11091 <programlisting><phrase role="comment">// every async operation receives a subclass instance of this abstract base</phrase>
11092 <phrase role="comment">// class through which to communicate its result</phrase>
11093 <phrase role="keyword">struct</phrase> <phrase role="identifier">Response</phrase> <phrase role="special">{</phrase>
11094 <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>
11095
11096 <phrase role="comment">// called if the operation succeeds</phrase>
11097 <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>
11098
11099 <phrase role="comment">// called if the operation fails</phrase>
11100 <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>
11101 <phrase role="special">};</phrase>
11102 </programlisting>
11103 </para>
11104 <para>
11105 Now the <code><phrase role="identifier">AsyncAPI</phrase></code> operation
11106 might look more like this:
11107 </para>
11108 <para>
11109 <programlisting><phrase role="comment">// derive Response subclass, instantiate, pass Response::ptr</phrase>
11110 <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>
11111 </programlisting>
11112 </para>
11113 <para>
11114 We can address this by writing a one-size-fits-all <code><phrase role="identifier">PromiseResponse</phrase></code>:
11115 </para>
11116 <para>
11117 <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>
11118 <phrase role="keyword">public</phrase><phrase role="special">:</phrase>
11119 <phrase role="comment">// called if the operation succeeds</phrase>
11120 <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>
11121 <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>
11122 <phrase role="special">}</phrase>
11123
11124 <phrase role="comment">// called if the operation fails</phrase>
11125 <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>
11126 <phrase role="identifier">promise_</phrase><phrase role="special">.</phrase><phrase role="identifier">set_exception</phrase><phrase role="special">(</phrase>
11127 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">make_exception_ptr</phrase><phrase role="special">(</phrase>
11128 <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>
11129 <phrase role="special">}</phrase>
11130
11131 <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>
11132 <phrase role="keyword">return</phrase> <phrase role="identifier">promise_</phrase><phrase role="special">.</phrase><phrase role="identifier">get_future</phrase><phrase role="special">();</phrase>
11133 <phrase role="special">}</phrase>
11134
11135 <phrase role="keyword">private</phrase><phrase role="special">:</phrase>
11136 <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>
11137 <phrase role="special">};</phrase>
11138 </programlisting>
11139 </para>
11140 <para>
11141 Now we can simply obtain the <code><phrase role="identifier">future</phrase><phrase
11142 role="special">&lt;&gt;</phrase></code> from that <code><phrase role="identifier">PromiseResponse</phrase></code>
11143 and wait on its <code><phrase role="identifier">get</phrase><phrase role="special">()</phrase></code>:
11144 </para>
11145 <para>
11146 <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>
11147 <phrase role="comment">// Because init_read() requires a shared_ptr, we must allocate our</phrase>
11148 <phrase role="comment">// ResponsePromise on the heap, even though we know its lifespan.</phrase>
11149 <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>
11150 <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>
11151 <phrase role="comment">// Both 'promisep' and 'future' will survive until our lambda has been</phrase>
11152 <phrase role="comment">// called.</phrase>
11153 <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>
11154 <phrase role="keyword">return</phrase> <phrase role="identifier">future</phrase><phrase role="special">.</phrase><phrase role="identifier">get</phrase><phrase role="special">();</phrase>
11155 <phrase role="special">}</phrase>
11156 </programlisting>
11157 </para>
11158 <para>
11159 The source code above is found in <ulink url="../../examples/adapt_callbacks.cpp">adapt_callbacks.cpp</ulink>
11160 and <ulink url="../../examples/adapt_method_calls.cpp">adapt_method_calls.cpp</ulink>.
11161 </para>
11162 </section>
11163 <section id="fiber.callbacks.then_there_s____boost_asio__">
11164 <title><anchor id="callbacks_asio"/><link linkend="fiber.callbacks.then_there_s____boost_asio__">Then
11165 There&#8217;s <ulink url="http://www.boost.org/doc/libs/release/libs/asio/index.html">Boost.Asio</ulink></link></title>
11166 <para>
11167 Since the simplest form of Boost.Asio asynchronous operation completion token
11168 is a callback function, we could apply the same tactics for Asio as for our
11169 hypothetical <code><phrase role="identifier">AsyncAPI</phrase></code> asynchronous
11170 operations.
11171 </para>
11172 <para>
11173 Fortunately we need not. Boost.Asio incorporates a mechanism<footnote id="fiber.callbacks.then_there_s____boost_asio__.f0">
11174 <para>
11175 This mechanism has been proposed as a conventional way to allow the caller
11176 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>.
11177 </para>
11178 </footnote> by which the caller can customize the notification behavior of
11179 any async operation. Therefore we can construct a <emphasis>completion token</emphasis>
11180 which, when passed to a <ulink url="http://www.boost.org/doc/libs/release/libs/asio/index.html">Boost.Asio</ulink>
11181 async operation, requests blocking for the calling fiber.
11182 </para>
11183 <para>
11184 A typical Asio async function might look something like this:<footnote id="fiber.callbacks.then_there_s____boost_asio__.f1">
11185 <para>
11186 per <ulink url="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4045.pdf">N4045</ulink>
11187 </para>
11188 </footnote>
11189 </para>
11190 <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>
11191 <emphasis>deduced_return_type</emphasis>
11192 <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>
11193 <phrase role="special">{</phrase>
11194 <phrase role="comment">// construct handler_type instance from CompletionToken</phrase>
11195 <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>
11196 <phrase role="comment">// construct async_result instance from handler_type</phrase>
11197 <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>
11198
11199 <phrase role="comment">// ... arrange to call handler on completion ...</phrase>
11200 <phrase role="comment">// ... initiate actual I/O operation ...</phrase>
11201
11202 <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>
11203 <phrase role="special">}</phrase>
11204 </programlisting>
11205 <para>
11206 We will engage that mechanism, which is based on specializing Asio&#8217;s <code><phrase
11207 role="identifier">handler_type</phrase><phrase role="special">&lt;&gt;</phrase></code>
11208 template for the <code><phrase role="identifier">CompletionToken</phrase></code>
11209 type and the signature of the specific callback. The remainder of this discussion
11210 will refer back to <code><phrase role="identifier">async_something</phrase><phrase
11211 role="special">()</phrase></code> as the Asio async function under consideration.
11212 </para>
11213 <para>
11214 The implementation described below uses lower-level facilities than <code><phrase
11215 role="identifier">promise</phrase></code> and <code><phrase role="identifier">future</phrase></code>
11216 because the <code><phrase role="identifier">promise</phrase></code> mechanism
11217 interacts badly with <ulink url="http://www.boost.org/doc/libs/release/doc/html/boost_asio/reference/io_service/stop.html"><code><phrase
11218 role="identifier">io_service</phrase><phrase role="special">::</phrase><phrase
11219 role="identifier">stop</phrase><phrase role="special">()</phrase></code></ulink>.
11220 It produces <code><phrase role="identifier">broken_promise</phrase></code>
11221 exceptions.
11222 </para>
11223 <para>
11224 <code><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase
11225 role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase
11226 role="identifier">asio</phrase><phrase role="special">::</phrase><phrase
11227 role="identifier">yield</phrase></code> is a completion token of this kind.
11228 <code><phrase role="identifier">yield</phrase></code> is an instance of
11229 <code><phrase role="identifier">yield_t</phrase></code>:
11230 </para>
11231 <para>
11232 <programlisting><phrase role="keyword">class</phrase> <phrase role="identifier">yield_t</phrase> <phrase role="special">{</phrase>
11233 <phrase role="keyword">public</phrase><phrase role="special">:</phrase>
11234 <phrase role="identifier">yield_t</phrase><phrase role="special">()</phrase> <phrase role="special">=</phrase> <phrase role="keyword">default</phrase><phrase role="special">;</phrase>
11235
11236 <phrase role="comment">/**
11237 * @code
11238 * static yield_t yield;
11239 * boost::system::error_code myec;
11240 * func(yield[myec]);
11241 * @endcode
11242 * @c yield[myec] returns an instance of @c yield_t whose @c ec_ points
11243 * to @c myec. The expression @c yield[myec] &quot;binds&quot; @c myec to that
11244 * (anonymous) @c yield_t instance, instructing @c func() to store any
11245 * @c error_code it might produce into @c myec rather than throwing @c
11246 * boost::system::system_error.
11247 */</phrase>
11248 <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>
11249 <phrase role="identifier">yield_t</phrase> <phrase role="identifier">tmp</phrase><phrase role="special">;</phrase>
11250 <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>
11251 <phrase role="keyword">return</phrase> <phrase role="identifier">tmp</phrase><phrase role="special">;</phrase>
11252 <phrase role="special">}</phrase>
11253
11254 <phrase role="comment">//private:</phrase>
11255 <phrase role="comment">// ptr to bound error_code instance if any</phrase>
11256 <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>
11257 <phrase role="special">};</phrase>
11258 </programlisting>
11259 </para>
11260 <para>
11261 <code><phrase role="identifier">yield_t</phrase></code> is in fact only a
11262 placeholder, a way to trigger Boost.Asio customization. It can bind a <ulink
11263 url="http://www.boost.org/doc/libs/release/libs/system/doc/reference.html#Class-error_code"><code><phrase
11264 role="identifier">boost</phrase><phrase role="special">::</phrase><phrase
11265 role="identifier">system</phrase><phrase role="special">::</phrase><phrase
11266 role="identifier">error_code</phrase></code></ulink> for use by the actual
11267 handler.
11268 </para>
11269 <para>
11270 <code><phrase role="identifier">yield</phrase></code> is declared as:
11271 </para>
11272 <para>
11273 <programlisting><phrase role="comment">// canonical instance</phrase>
11274 <phrase role="keyword">thread_local</phrase> <phrase role="identifier">yield_t</phrase> <phrase role="identifier">yield</phrase><phrase role="special">{};</phrase>
11275 </programlisting>
11276 </para>
11277 <para>
11278 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
11279 role="identifier">boost</phrase><phrase role="special">::</phrase><phrase
11280 role="identifier">asio</phrase><phrase role="special">::</phrase><phrase
11281 role="identifier">handler_type</phrase><phrase role="special">&lt;&gt;</phrase></code></ulink>
11282 for <code><phrase role="identifier">yield_t</phrase></code>:
11283 </para>
11284 <para>
11285 <programlisting><phrase role="comment">// Handler type specialisation for fibers::asio::yield.</phrase>
11286 <phrase role="comment">// When 'yield' is passed as a completion handler which accepts only</phrase>
11287 <phrase role="comment">// error_code, use yield_handler&lt;void&gt;. yield_handler will take care of the</phrase>
11288 <phrase role="comment">// error_code one way or another.</phrase>
11289 <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>
11290 <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>
11291 <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>
11292 </programlisting>
11293 </para>
11294 <para>
11295 (There are actually four different specializations in <ulink url="../../examples/asio/detail/yield.hpp">detail/yield.hpp</ulink>,
11296 one for each of the four Asio async callback signatures we expect.)
11297 </para>
11298 <para>
11299 The above directs Asio to use <code><phrase role="identifier">yield_handler</phrase></code>
11300 as the actual handler for an async operation to which <code><phrase role="identifier">yield</phrase></code>
11301 is passed. There&#8217;s a generic <code><phrase role="identifier">yield_handler</phrase><phrase
11302 role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;</phrase></code>
11303 implementation and a <code><phrase role="identifier">yield_handler</phrase><phrase
11304 role="special">&lt;</phrase><phrase role="keyword">void</phrase><phrase role="special">&gt;</phrase></code>
11305 specialization. Let&#8217;s start with the <code><phrase role="special">&lt;</phrase><phrase
11306 role="keyword">void</phrase><phrase role="special">&gt;</phrase></code> specialization:
11307 </para>
11308 <para>
11309 <programlisting><phrase role="comment">// yield_handler&lt;void&gt; is like yield_handler&lt;T&gt; without value_. In fact it's</phrase>
11310 <phrase role="comment">// just like yield_handler_base.</phrase>
11311 <phrase role="keyword">template</phrase><phrase role="special">&lt;&gt;</phrase>
11312 <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>
11313 <phrase role="keyword">public</phrase><phrase role="special">:</phrase>
11314 <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>
11315 <phrase role="identifier">yield_handler_base</phrase><phrase role="special">{</phrase> <phrase role="identifier">y</phrase> <phrase role="special">}</phrase> <phrase role="special">{</phrase>
11316 <phrase role="special">}</phrase>
11317
11318 <phrase role="comment">// nullary completion callback</phrase>
11319 <phrase role="keyword">void</phrase> <phrase role="keyword">operator</phrase><phrase role="special">()()</phrase> <phrase role="special">{</phrase>
11320 <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>
11321 <phrase role="special">}</phrase>
11322
11323 <phrase role="comment">// inherit operator()(error_code) overload from base class</phrase>
11324 <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>
11325 <phrase role="special">};</phrase>
11326 </programlisting>
11327 </para>
11328 <para>
11329 <code><phrase role="identifier">async_something</phrase><phrase role="special">()</phrase></code>,
11330 having consulted the <code><phrase role="identifier">handler_type</phrase><phrase
11331 role="special">&lt;&gt;</phrase></code> traits specialization, instantiates
11332 a <code><phrase role="identifier">yield_handler</phrase><phrase role="special">&lt;</phrase><phrase
11333 role="keyword">void</phrase><phrase role="special">&gt;</phrase></code> to
11334 be passed as the actual callback for the async operation. <code><phrase role="identifier">yield_handler</phrase></code>&#8217;s
11335 constructor accepts the <code><phrase role="identifier">yield_t</phrase></code>
11336 instance (the <code><phrase role="identifier">yield</phrase></code> object
11337 passed to the async function) and passes it along to <code><phrase role="identifier">yield_handler_base</phrase></code>:
11338 </para>
11339 <para>
11340 <programlisting><phrase role="comment">// This class encapsulates common elements between yield_handler&lt;T&gt; (capturing</phrase>
11341 <phrase role="comment">// a value to return from asio async function) and yield_handler&lt;void&gt; (no</phrase>
11342 <phrase role="comment">// such value). See yield_handler&lt;T&gt; and its &lt;void&gt; specialization below. Both</phrase>
11343 <phrase role="comment">// yield_handler&lt;T&gt; and yield_handler&lt;void&gt; are passed by value through</phrase>
11344 <phrase role="comment">// various layers of asio functions. In other words, they're potentially</phrase>
11345 <phrase role="comment">// copied multiple times. So key data such as the yield_completion instance</phrase>
11346 <phrase role="comment">// must be stored in our async_result&lt;yield_handler&lt;&gt;&gt; specialization, which</phrase>
11347 <phrase role="comment">// should be instantiated only once.</phrase>
11348 <phrase role="keyword">class</phrase> <phrase role="identifier">yield_handler_base</phrase> <phrase role="special">{</phrase>
11349 <phrase role="keyword">public</phrase><phrase role="special">:</phrase>
11350 <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>
11351 <phrase role="comment">// capture the context* associated with the running fiber</phrase>
11352 <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>
11353 <phrase role="comment">// capture the passed yield_t</phrase>
11354 <phrase role="identifier">yt_</phrase><phrase role="special">(</phrase> <phrase role="identifier">y</phrase> <phrase role="special">)</phrase> <phrase role="special">{</phrase>
11355 <phrase role="special">}</phrase>
11356
11357 <phrase role="comment">// completion callback passing only (error_code)</phrase>
11358 <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>
11359 <phrase role="identifier">BOOST_ASSERT_MSG</phrase><phrase role="special">(</phrase> <phrase role="identifier">ycomp_</phrase><phrase role="special">,</phrase>
11360 <phrase role="string">&quot;Must inject yield_completion* &quot;</phrase>
11361 <phrase role="string">&quot;before calling yield_handler_base::operator()()&quot;</phrase><phrase role="special">);</phrase>
11362 <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>
11363 <phrase role="string">&quot;Must inject boost::system::error_code* &quot;</phrase>
11364 <phrase role="string">&quot;before calling yield_handler_base::operator()()&quot;</phrase><phrase role="special">);</phrase>
11365 <phrase role="comment">// If originating fiber is busy testing completed_ flag, wait until it</phrase>
11366 <phrase role="comment">// has observed (! completed_).</phrase>
11367 <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>
11368 <phrase role="comment">// Notify a subsequent yield_completion::wait() call that it need not</phrase>
11369 <phrase role="comment">// suspend.</phrase>
11370 <phrase role="identifier">ycomp_</phrase><phrase role="special">-&gt;</phrase><phrase role="identifier">completed_</phrase> <phrase role="special">=</phrase> <phrase role="keyword">true</phrase><phrase role="special">;</phrase>
11371 <phrase role="comment">// set the error_code bound by yield_t</phrase>
11372 <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>
11373 <phrase role="comment">// If ctx_ is still active, e.g. because the async operation</phrase>
11374 <phrase role="comment">// immediately called its callback (this method!) before the asio</phrase>
11375 <phrase role="comment">// async function called async_result_base::get(), we must not set it</phrase>
11376 <phrase role="comment">// ready.</phrase>
11377 <phrase role="keyword">if</phrase> <phrase role="special">(</phrase> <phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">context</phrase><phrase role="special">::</phrase><phrase role="identifier">active</phrase><phrase role="special">()</phrase> <phrase role="special">!=</phrase> <phrase role="identifier">ctx_</phrase> <phrase role="special">)</phrase> <phrase role="special">{</phrase>
11378 <phrase role="comment">// wake the fiber</phrase>
11379 <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">set_ready</phrase><phrase role="special">(</phrase> <phrase role="identifier">ctx_</phrase><phrase role="special">);</phrase>
11380 <phrase role="special">}</phrase>
11381 <phrase role="special">}</phrase>
11382
11383 <phrase role="comment">//private:</phrase>
11384 <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>
11385 <phrase role="identifier">yield_t</phrase> <phrase role="identifier">yt_</phrase><phrase role="special">;</phrase>
11386 <phrase role="comment">// We depend on this pointer to yield_completion, which will be injected</phrase>
11387 <phrase role="comment">// by async_result.</phrase>
11388 <phrase role="identifier">yield_completion</phrase> <phrase role="special">*</phrase> <phrase role="identifier">ycomp_</phrase><phrase role="special">{</phrase> <phrase role="keyword">nullptr</phrase> <phrase role="special">};</phrase>
11389 <phrase role="special">};</phrase>
11390 </programlisting>
11391 </para>
11392 <para>
11393 <code><phrase role="identifier">yield_handler_base</phrase></code> stores
11394 a copy of the <code><phrase role="identifier">yield_t</phrase></code> instance
11395 &mdash; which, as shown above, contains only an <code><phrase role="identifier">error_code</phrase><phrase
11396 role="special">*</phrase></code>. It also captures the <link linkend="class_context"><code>context</code></link>*
11397 for the currently-running fiber by calling <link linkend="context_active"><code>context::active()</code></link>.
11398 </para>
11399 <para>
11400 You will notice that <code><phrase role="identifier">yield_handler_base</phrase></code>
11401 has one more data member (<code><phrase role="identifier">ycomp_</phrase></code>)
11402 that is initialized to <code><phrase role="keyword">nullptr</phrase></code>
11403 by its constructor &mdash; though its <code><phrase role="keyword">operator</phrase><phrase
11404 role="special">()()</phrase></code> method relies on <code><phrase role="identifier">ycomp_</phrase></code>
11405 being non-null. More on this in a moment.
11406 </para>
11407 <para>
11408 Having constructed the <code><phrase role="identifier">yield_handler</phrase><phrase
11409 role="special">&lt;</phrase><phrase role="keyword">void</phrase><phrase role="special">&gt;</phrase></code>
11410 instance, <code><phrase role="identifier">async_something</phrase><phrase
11411 role="special">()</phrase></code> goes on to construct an <code><phrase role="identifier">async_result</phrase></code>
11412 specialized for the <code><phrase role="identifier">handler_type</phrase><phrase
11413 role="special">&lt;&gt;::</phrase><phrase role="identifier">type</phrase></code>:
11414 in this case, <code><phrase role="identifier">async_result</phrase><phrase
11415 role="special">&lt;</phrase><phrase role="identifier">yield_handler</phrase><phrase
11416 role="special">&lt;</phrase><phrase role="keyword">void</phrase><phrase role="special">&gt;&gt;</phrase></code>.
11417 It passes the <code><phrase role="identifier">yield_handler</phrase><phrase
11418 role="special">&lt;</phrase><phrase role="keyword">void</phrase><phrase role="special">&gt;</phrase></code>
11419 instance to the new <code><phrase role="identifier">async_result</phrase></code>
11420 instance.
11421 </para>
11422 <para>
11423 <programlisting><phrase role="comment">// Without the need to handle a passed value, our yield_handler&lt;void&gt;</phrase>
11424 <phrase role="comment">// specialization is just like async_result_base.</phrase>
11425 <phrase role="keyword">template</phrase><phrase role="special">&lt;&gt;</phrase>
11426 <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>
11427 <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>
11428 <phrase role="keyword">public</phrase><phrase role="special">:</phrase>
11429 <phrase role="keyword">typedef</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">type</phrase><phrase role="special">;</phrase>
11430
11431 <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>
11432 <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>
11433 <phrase role="special">}</phrase>
11434 <phrase role="special">};</phrase>
11435 </programlisting>
11436 </para>
11437 <para>
11438 Naturally that leads us straight to <code><phrase role="identifier">async_result_base</phrase></code>:
11439 </para>
11440 <para>
11441 <programlisting><phrase role="comment">// Factor out commonality between async_result&lt;yield_handler&lt;T&gt;&gt; and</phrase>
11442 <phrase role="comment">// async_result&lt;yield_handler&lt;void&gt;&gt;</phrase>
11443 <phrase role="keyword">class</phrase> <phrase role="identifier">async_result_base</phrase> <phrase role="special">{</phrase>
11444 <phrase role="keyword">public</phrase><phrase role="special">:</phrase>
11445 <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>
11446 <phrase role="comment">// Inject ptr to our yield_completion instance into this</phrase>
11447 <phrase role="comment">// yield_handler&lt;&gt;.</phrase>
11448 <phrase role="identifier">h</phrase><phrase role="special">.</phrase><phrase role="identifier">ycomp_</phrase> <phrase role="special">=</phrase> <phrase role="special">&amp;</phrase> <phrase role="keyword">this</phrase><phrase role="special">-&gt;</phrase><phrase role="identifier">ycomp_</phrase><phrase role="special">;</phrase>
11449 <phrase role="comment">// if yield_t didn't bind an error_code, make yield_handler_base's</phrase>
11450 <phrase role="comment">// error_code* point to an error_code local to this object so</phrase>
11451 <phrase role="comment">// yield_handler_base::operator() can unconditionally store through</phrase>
11452 <phrase role="comment">// its error_code*</phrase>
11453 <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>
11454 <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>
11455 <phrase role="special">}</phrase>
11456 <phrase role="special">}</phrase>
11457
11458 <phrase role="keyword">void</phrase> <phrase role="identifier">get</phrase><phrase role="special">()</phrase> <phrase role="special">{</phrase>
11459 <phrase role="comment">// Unless yield_handler_base::operator() has already been called,</phrase>
11460 <phrase role="comment">// suspend the calling fiber until that call.</phrase>
11461 <phrase role="identifier">ycomp_</phrase><phrase role="special">.</phrase><phrase role="identifier">wait</phrase><phrase role="special">();</phrase>
11462 <phrase role="comment">// The only way our own ec_ member could have a non-default value is</phrase>
11463 <phrase role="comment">// if our yield_handler did not have a bound error_code AND the</phrase>
11464 <phrase role="comment">// completion callback passed a non-default error_code.</phrase>
11465 <phrase role="keyword">if</phrase> <phrase role="special">(</phrase> <phrase role="identifier">ec_</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
11466 <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>
11467 <phrase role="special">}</phrase>
11468 <phrase role="special">}</phrase>
11469
11470 <phrase role="keyword">private</phrase><phrase role="special">:</phrase>
11471 <phrase role="comment">// If yield_t does not bind an error_code instance, store into here.</phrase>
11472 <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>
11473 <phrase role="comment">// async_result_base owns the yield_completion because, unlike</phrase>
11474 <phrase role="comment">// yield_handler&lt;&gt;, async_result&lt;&gt; is only instantiated once.</phrase>
11475 <phrase role="identifier">yield_completion</phrase> <phrase role="identifier">ycomp_</phrase><phrase role="special">{};</phrase>
11476 <phrase role="special">};</phrase>
11477 </programlisting>
11478 </para>
11479 <para>
11480 This is how <code><phrase role="identifier">yield_handler_base</phrase><phrase
11481 role="special">::</phrase><phrase role="identifier">ycomp_</phrase></code>
11482 becomes non-null: <code><phrase role="identifier">async_result_base</phrase></code>&#8217;s
11483 constructor injects a pointer back to its own <code><phrase role="identifier">yield_completion</phrase></code>
11484 member.
11485 </para>
11486 <para>
11487 Recall that the canonical <code><phrase role="identifier">yield_t</phrase></code>
11488 instance <code><phrase role="identifier">yield</phrase></code> initializes
11489 its <code><phrase role="identifier">error_code</phrase><phrase role="special">*</phrase></code>
11490 member <code><phrase role="identifier">ec_</phrase></code> to <code><phrase
11491 role="keyword">nullptr</phrase></code>. If this instance is passed to <code><phrase
11492 role="identifier">async_something</phrase><phrase role="special">()</phrase></code>
11493 (<code><phrase role="identifier">ec_</phrase></code> is still <code><phrase
11494 role="keyword">nullptr</phrase></code>), the copy stored in <code><phrase
11495 role="identifier">yield_handler_base</phrase></code> will likewise have null
11496 <code><phrase role="identifier">ec_</phrase></code>. <code><phrase role="identifier">async_result_base</phrase></code>&#8217;s
11497 constructor sets <code><phrase role="identifier">yield_handler_base</phrase></code>&#8217;s
11498 <code><phrase role="identifier">yield_t</phrase></code>&#8217;s <code><phrase role="identifier">ec_</phrase></code>
11499 member to point to its own <code><phrase role="identifier">error_code</phrase></code>
11500 member.
11501 </para>
11502 <para>
11503 The stage is now set. <code><phrase role="identifier">async_something</phrase><phrase
11504 role="special">()</phrase></code> initiates the actual async operation, arranging
11505 to call its <code><phrase role="identifier">yield_handler</phrase><phrase
11506 role="special">&lt;</phrase><phrase role="keyword">void</phrase><phrase role="special">&gt;</phrase></code>
11507 instance on completion. Let&#8217;s say, for the sake of argument, that the actual
11508 async operation&#8217;s callback has signature <code><phrase role="keyword">void</phrase><phrase
11509 role="special">(</phrase><phrase role="identifier">error_code</phrase><phrase
11510 role="special">)</phrase></code>.
11511 </para>
11512 <para>
11513 But since it&#8217;s an async operation, control returns at once to <code><phrase
11514 role="identifier">async_something</phrase><phrase role="special">()</phrase></code>.
11515 <code><phrase role="identifier">async_something</phrase><phrase role="special">()</phrase></code>
11516 calls <code><phrase role="identifier">async_result</phrase><phrase role="special">&lt;</phrase><phrase
11517 role="identifier">yield_handler</phrase><phrase role="special">&lt;</phrase><phrase
11518 role="keyword">void</phrase><phrase role="special">&gt;&gt;::</phrase><phrase
11519 role="identifier">get</phrase><phrase role="special">()</phrase></code>,
11520 and will return its return value.
11521 </para>
11522 <para>
11523 <code><phrase role="identifier">async_result</phrase><phrase role="special">&lt;</phrase><phrase
11524 role="identifier">yield_handler</phrase><phrase role="special">&lt;</phrase><phrase
11525 role="keyword">void</phrase><phrase role="special">&gt;&gt;::</phrase><phrase
11526 role="identifier">get</phrase><phrase role="special">()</phrase></code> inherits
11527 <code><phrase role="identifier">async_result_base</phrase><phrase role="special">::</phrase><phrase
11528 role="identifier">get</phrase><phrase role="special">()</phrase></code>.
11529 </para>
11530 <para>
11531 <code><phrase role="identifier">async_result_base</phrase><phrase role="special">::</phrase><phrase
11532 role="identifier">get</phrase><phrase role="special">()</phrase></code> immediately
11533 calls <code><phrase role="identifier">yield_completion</phrase><phrase role="special">::</phrase><phrase
11534 role="identifier">wait</phrase><phrase role="special">()</phrase></code>.
11535 </para>
11536 <para>
11537 <programlisting><phrase role="comment">// Bundle a completion bool flag with a spinlock to protect it.</phrase>
11538 <phrase role="keyword">struct</phrase> <phrase role="identifier">yield_completion</phrase> <phrase role="special">{</phrase>
11539 <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>
11540 <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>
11541
11542 <phrase role="identifier">mutex_t</phrase> <phrase role="identifier">mtx_</phrase><phrase role="special">{};</phrase>
11543 <phrase role="keyword">bool</phrase> <phrase role="identifier">completed_</phrase><phrase role="special">{</phrase> <phrase role="keyword">false</phrase> <phrase role="special">};</phrase>
11544
11545 <phrase role="keyword">void</phrase> <phrase role="identifier">wait</phrase><phrase role="special">()</phrase> <phrase role="special">{</phrase>
11546 <phrase role="comment">// yield_handler_base::operator()() will set completed_ true and</phrase>
11547 <phrase role="comment">// attempt to wake a suspended fiber. It would be Bad if that call</phrase>
11548 <phrase role="comment">// happened between our detecting (! completed_) and suspending.</phrase>
11549 <phrase role="identifier">lock_t</phrase> <phrase role="identifier">lk</phrase><phrase role="special">{</phrase> <phrase role="identifier">mtx_</phrase> <phrase role="special">};</phrase>
11550 <phrase role="comment">// If completed_ is already set, we're done here: don't suspend.</phrase>
11551 <phrase role="keyword">if</phrase> <phrase role="special">(</phrase> <phrase role="special">!</phrase> <phrase role="identifier">completed_</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
11552 <phrase role="comment">// suspend(unique_lock&lt;spinlock&gt;) unlocks the lock in the act of</phrase>
11553 <phrase role="comment">// resuming another fiber</phrase>
11554 <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>
11555 <phrase role="special">}</phrase>
11556 <phrase role="special">}</phrase>
11557 <phrase role="special">};</phrase>
11558 </programlisting>
11559 </para>
11560 <para>
11561 Supposing that the pending async operation has not yet completed, <code><phrase
11562 role="identifier">yield_completion</phrase><phrase role="special">::</phrase><phrase
11563 role="identifier">completed_</phrase></code> will still be <code><phrase
11564 role="keyword">false</phrase></code>, and <code><phrase role="identifier">wait</phrase><phrase
11565 role="special">()</phrase></code> will call <link linkend="context_suspend"><code>context::suspend()</code></link> on
11566 the currently-running fiber.
11567 </para>
11568 <para>
11569 Other fibers will now have a chance to run.
11570 </para>
11571 <para>
11572 Some time later, the async operation completes. It calls <code><phrase role="identifier">yield_handler</phrase><phrase
11573 role="special">&lt;</phrase><phrase role="keyword">void</phrase><phrase role="special">&gt;::</phrase><phrase
11574 role="keyword">operator</phrase><phrase role="special">()(</phrase><phrase
11575 role="identifier">error_code</phrase> <phrase role="keyword">const</phrase><phrase
11576 role="special">&amp;)</phrase></code> with an <code><phrase role="identifier">error_code</phrase></code>
11577 indicating either success or failure. We&#8217;ll consider both cases.
11578 </para>
11579 <para>
11580 <code><phrase role="identifier">yield_handler</phrase><phrase role="special">&lt;</phrase><phrase
11581 role="keyword">void</phrase><phrase role="special">&gt;</phrase></code> explicitly
11582 inherits <code><phrase role="keyword">operator</phrase><phrase role="special">()(</phrase><phrase
11583 role="identifier">error_code</phrase> <phrase role="keyword">const</phrase><phrase
11584 role="special">&amp;)</phrase></code> from <code><phrase role="identifier">yield_handler_base</phrase></code>.
11585 </para>
11586 <para>
11587 <code><phrase role="identifier">yield_handler_base</phrase><phrase role="special">::</phrase><phrase
11588 role="keyword">operator</phrase><phrase role="special">()(</phrase><phrase
11589 role="identifier">error_code</phrase> <phrase role="keyword">const</phrase><phrase
11590 role="special">&amp;)</phrase></code> first sets <code><phrase role="identifier">yield_completion</phrase><phrase
11591 role="special">::</phrase><phrase role="identifier">completed_</phrase></code>
11592 <code><phrase role="keyword">true</phrase></code>. This way, if <code><phrase
11593 role="identifier">async_something</phrase><phrase role="special">()</phrase></code>&#8217;s
11594 async operation completes immediately &mdash; if <code><phrase role="identifier">yield_handler_base</phrase><phrase
11595 role="special">::</phrase><phrase role="keyword">operator</phrase><phrase
11596 role="special">()</phrase></code> is called even before <code><phrase role="identifier">async_result_base</phrase><phrase
11597 role="special">::</phrase><phrase role="identifier">get</phrase><phrase role="special">()</phrase></code>
11598 &mdash; the calling fiber will <emphasis>not</emphasis> suspend.
11599 </para>
11600 <para>
11601 The actual <code><phrase role="identifier">error_code</phrase></code> produced
11602 by the async operation is then stored through the stored <code><phrase role="identifier">yield_t</phrase><phrase
11603 role="special">::</phrase><phrase role="identifier">ec_</phrase></code> pointer.
11604 If <code><phrase role="identifier">async_something</phrase><phrase role="special">()</phrase></code>&#8217;s
11605 caller used (e.g.) <code><phrase role="identifier">yield</phrase><phrase
11606 role="special">[</phrase><phrase role="identifier">my_ec</phrase><phrase
11607 role="special">]</phrase></code> to bind a local <code><phrase role="identifier">error_code</phrase></code>
11608 instance, the actual <code><phrase role="identifier">error_code</phrase></code>
11609 value is stored into the caller&#8217;s variable. Otherwise, it is stored into
11610 <code><phrase role="identifier">async_result_base</phrase><phrase role="special">::</phrase><phrase
11611 role="identifier">ec_</phrase></code>.
11612 </para>
11613 <para>
11614 If the stored fiber context <code><phrase role="identifier">yield_handler_base</phrase><phrase
11615 role="special">::</phrase><phrase role="identifier">ctx_</phrase></code>
11616 is not already running, it is marked as ready to run by passing it to <link linkend="context_set_ready"><code>context::set_ready()</code></link>.
11617 Control then returns from <code><phrase role="identifier">yield_handler_base</phrase><phrase
11618 role="special">::</phrase><phrase role="keyword">operator</phrase><phrase
11619 role="special">()</phrase></code>: the callback is done.
11620 </para>
11621 <para>
11622 In due course, that fiber is resumed. Control returns from <link linkend="context_suspend"><code>context::suspend()</code></link> to
11623 <code><phrase role="identifier">yield_completion</phrase><phrase role="special">::</phrase><phrase
11624 role="identifier">wait</phrase><phrase role="special">()</phrase></code>,
11625 which returns to <code><phrase role="identifier">async_result_base</phrase><phrase
11626 role="special">::</phrase><phrase role="identifier">get</phrase><phrase role="special">()</phrase></code>.
11627 </para>
11628 <itemizedlist>
11629 <listitem>
11630 <simpara>
11631 If the original caller passed <code><phrase role="identifier">yield</phrase><phrase
11632 role="special">[</phrase><phrase role="identifier">my_ec</phrase><phrase
11633 role="special">]</phrase></code> to <code><phrase role="identifier">async_something</phrase><phrase
11634 role="special">()</phrase></code> to bind a local <code><phrase role="identifier">error_code</phrase></code>
11635 instance, then <code><phrase role="identifier">yield_handler_base</phrase><phrase
11636 role="special">::</phrase><phrase role="keyword">operator</phrase><phrase
11637 role="special">()</phrase></code> stored its <code><phrase role="identifier">error_code</phrase></code>
11638 to the caller&#8217;s <code><phrase role="identifier">my_ec</phrase></code>
11639 instance, leaving <code><phrase role="identifier">async_result_base</phrase><phrase
11640 role="special">::</phrase><phrase role="identifier">ec_</phrase></code>
11641 initialized to success.
11642 </simpara>
11643 </listitem>
11644 <listitem>
11645 <simpara>
11646 If the original caller passed <code><phrase role="identifier">yield</phrase></code>
11647 to <code><phrase role="identifier">async_something</phrase><phrase role="special">()</phrase></code>
11648 without binding a local <code><phrase role="identifier">error_code</phrase></code>
11649 variable, then <code><phrase role="identifier">yield_handler_base</phrase><phrase
11650 role="special">::</phrase><phrase role="keyword">operator</phrase><phrase
11651 role="special">()</phrase></code> stored its <code><phrase role="identifier">error_code</phrase></code>
11652 into <code><phrase role="identifier">async_result_base</phrase><phrase
11653 role="special">::</phrase><phrase role="identifier">ec_</phrase></code>.
11654 If in fact that <code><phrase role="identifier">error_code</phrase></code>
11655 is success, then all is well.
11656 </simpara>
11657 </listitem>
11658 <listitem>
11659 <simpara>
11660 Otherwise &mdash; the original caller did not bind a local <code><phrase role="identifier">error_code</phrase></code>
11661 and <code><phrase role="identifier">yield_handler_base</phrase><phrase
11662 role="special">::</phrase><phrase role="keyword">operator</phrase><phrase
11663 role="special">()</phrase></code> was called with an <code><phrase role="identifier">error_code</phrase></code>
11664 indicating error &mdash; <code><phrase role="identifier">async_result_base</phrase><phrase
11665 role="special">::</phrase><phrase role="identifier">get</phrase><phrase
11666 role="special">()</phrase></code> throws <code><phrase role="identifier">system_error</phrase></code>
11667 with that <code><phrase role="identifier">error_code</phrase></code>.
11668 </simpara>
11669 </listitem>
11670 </itemizedlist>
11671 <para>
11672 The case in which <code><phrase role="identifier">async_something</phrase><phrase
11673 role="special">()</phrase></code>&#8217;s completion callback has signature <code><phrase
11674 role="keyword">void</phrase><phrase role="special">()</phrase></code> is
11675 similar. <code><phrase role="identifier">yield_handler</phrase><phrase role="special">&lt;</phrase><phrase
11676 role="keyword">void</phrase><phrase role="special">&gt;::</phrase><phrase
11677 role="keyword">operator</phrase><phrase role="special">()()</phrase></code>
11678 invokes the machinery above with a <quote>success</quote> <code><phrase role="identifier">error_code</phrase></code>.
11679 </para>
11680 <para>
11681 A completion callback with signature <code><phrase role="keyword">void</phrase><phrase
11682 role="special">(</phrase><phrase role="identifier">error_code</phrase><phrase
11683 role="special">,</phrase> <phrase role="identifier">T</phrase><phrase role="special">)</phrase></code>
11684 (that is: in addition to <code><phrase role="identifier">error_code</phrase></code>,
11685 callback receives some data item) is handled somewhat differently. For this
11686 kind of signature, <code><phrase role="identifier">handler_type</phrase><phrase
11687 role="special">&lt;&gt;::</phrase><phrase role="identifier">type</phrase></code>
11688 specifies <code><phrase role="identifier">yield_handler</phrase><phrase role="special">&lt;</phrase><phrase
11689 role="identifier">T</phrase><phrase role="special">&gt;</phrase></code> (for
11690 <code><phrase role="identifier">T</phrase></code> other than <code><phrase
11691 role="keyword">void</phrase></code>).
11692 </para>
11693 <para>
11694 A <code><phrase role="identifier">yield_handler</phrase><phrase role="special">&lt;</phrase><phrase
11695 role="identifier">T</phrase><phrase role="special">&gt;</phrase></code> reserves
11696 a <code><phrase role="identifier">value_</phrase></code> pointer to a value
11697 of type <code><phrase role="identifier">T</phrase></code>:
11698 </para>
11699 <para>
11700 <programlisting><phrase role="comment">// asio uses handler_type&lt;completion token type, signature&gt;::type to decide</phrase>
11701 <phrase role="comment">// what to instantiate as the actual handler. Below, we specialize</phrase>
11702 <phrase role="comment">// handler_type&lt; yield_t, ... &gt; to indicate yield_handler&lt;&gt;. So when you pass</phrase>
11703 <phrase role="comment">// an instance of yield_t as an asio completion token, asio selects</phrase>
11704 <phrase role="comment">// yield_handler&lt;&gt; as the actual handler class.</phrase>
11705 <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>
11706 <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>
11707 <phrase role="keyword">public</phrase><phrase role="special">:</phrase>
11708 <phrase role="comment">// asio passes the completion token to the handler constructor</phrase>
11709 <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>
11710 <phrase role="identifier">yield_handler_base</phrase><phrase role="special">{</phrase> <phrase role="identifier">y</phrase> <phrase role="special">}</phrase> <phrase role="special">{</phrase>
11711 <phrase role="special">}</phrase>
11712
11713 <phrase role="comment">// completion callback passing only value (T)</phrase>
11714 <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>
11715 <phrase role="comment">// just like callback passing success error_code</phrase>
11716 <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>
11717 <phrase role="special">}</phrase>
11718
11719 <phrase role="comment">// completion callback passing (error_code, T)</phrase>
11720 <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>
11721 <phrase role="identifier">BOOST_ASSERT_MSG</phrase><phrase role="special">(</phrase> <phrase role="identifier">value_</phrase><phrase role="special">,</phrase>
11722 <phrase role="string">&quot;Must inject value ptr &quot;</phrase>
11723 <phrase role="string">&quot;before caling yield_handler&lt;T&gt;::operator()()&quot;</phrase><phrase role="special">);</phrase>
11724 <phrase role="comment">// move the value to async_result&lt;&gt; instance BEFORE waking up a</phrase>
11725 <phrase role="comment">// suspended fiber</phrase>
11726 <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>
11727 <phrase role="comment">// forward the call to base-class completion handler</phrase>
11728 <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>
11729 <phrase role="special">}</phrase>
11730
11731 <phrase role="comment">//private:</phrase>
11732 <phrase role="comment">// pointer to destination for eventual value</phrase>
11733 <phrase role="comment">// this must be injected by async_result before operator()() is called</phrase>
11734 <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>
11735 <phrase role="special">};</phrase>
11736 </programlisting>
11737 </para>
11738 <para>
11739 This pointer is initialized to <code><phrase role="keyword">nullptr</phrase></code>.
11740 </para>
11741 <para>
11742 When <code><phrase role="identifier">async_something</phrase><phrase role="special">()</phrase></code>
11743 instantiates <code><phrase role="identifier">async_result</phrase><phrase
11744 role="special">&lt;</phrase><phrase role="identifier">yield_handler</phrase><phrase
11745 role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;&gt;</phrase></code>:
11746 </para>
11747 <para>
11748 <programlisting><phrase role="comment">// asio constructs an async_result&lt;&gt; instance from the yield_handler specified</phrase>
11749 <phrase role="comment">// by handler_type&lt;&gt;::type. A particular asio async method constructs the</phrase>
11750 <phrase role="comment">// yield_handler, constructs this async_result specialization from it, then</phrase>
11751 <phrase role="comment">// returns the result of calling its get() method.</phrase>
11752 <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>
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="identifier">T</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="comment">// type returned by get()</phrase>
11757 <phrase role="keyword">typedef</phrase> <phrase role="identifier">T</phrase> <phrase role="identifier">type</phrase><phrase role="special">;</phrase>
11758
11759 <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>
11760 <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>
11761 <phrase role="comment">// Inject ptr to our value_ member into yield_handler&lt;&gt;: result will</phrase>
11762 <phrase role="comment">// be stored here.</phrase>
11763 <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>
11764 <phrase role="special">}</phrase>
11765
11766 <phrase role="comment">// asio async method returns result of calling get()</phrase>
11767 <phrase role="identifier">type</phrase> <phrase role="identifier">get</phrase><phrase role="special">()</phrase> <phrase role="special">{</phrase>
11768 <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>
11769 <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>
11770 <phrase role="special">}</phrase>
11771
11772 <phrase role="keyword">private</phrase><phrase role="special">:</phrase>
11773 <phrase role="identifier">type</phrase> <phrase role="identifier">value_</phrase><phrase role="special">{};</phrase>
11774 <phrase role="special">};</phrase>
11775 </programlisting>
11776 </para>
11777 <para>
11778 this <code><phrase role="identifier">async_result</phrase><phrase role="special">&lt;&gt;</phrase></code>
11779 specialization reserves a member of type <code><phrase role="identifier">T</phrase></code>
11780 to receive the passed data item, and sets <code><phrase role="identifier">yield_handler</phrase><phrase
11781 role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase
11782 role="identifier">value_</phrase></code> to point to its own data member.
11783 </para>
11784 <para>
11785 <code><phrase role="identifier">async_result</phrase><phrase role="special">&lt;</phrase><phrase
11786 role="identifier">yield_handler</phrase><phrase role="special">&lt;</phrase><phrase
11787 role="identifier">T</phrase><phrase role="special">&gt;&gt;</phrase></code>
11788 overrides <code><phrase role="identifier">get</phrase><phrase role="special">()</phrase></code>.
11789 The override calls <code><phrase role="identifier">async_result_base</phrase><phrase
11790 role="special">::</phrase><phrase role="identifier">get</phrase><phrase role="special">()</phrase></code>,
11791 so the calling fiber suspends as described above.
11792 </para>
11793 <para>
11794 <code><phrase role="identifier">yield_handler</phrase><phrase role="special">&lt;</phrase><phrase
11795 role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase
11796 role="keyword">operator</phrase><phrase role="special">()(</phrase><phrase
11797 role="identifier">error_code</phrase><phrase role="special">,</phrase> <phrase
11798 role="identifier">T</phrase><phrase role="special">)</phrase></code> stores
11799 its passed <code><phrase role="identifier">T</phrase></code> value into
11800 <code><phrase role="identifier">async_result</phrase><phrase role="special">&lt;</phrase><phrase
11801 role="identifier">yield_handler</phrase><phrase role="special">&lt;</phrase><phrase
11802 role="identifier">T</phrase><phrase role="special">&gt;&gt;::</phrase><phrase
11803 role="identifier">value_</phrase></code>.
11804 </para>
11805 <para>
11806 Then it passes control to <code><phrase role="identifier">yield_handler_base</phrase><phrase
11807 role="special">::</phrase><phrase role="keyword">operator</phrase><phrase
11808 role="special">()(</phrase><phrase role="identifier">error_code</phrase><phrase
11809 role="special">)</phrase></code> to deal with waking the original fiber as
11810 described above.
11811 </para>
11812 <para>
11813 When <code><phrase role="identifier">async_result</phrase><phrase role="special">&lt;</phrase><phrase
11814 role="identifier">yield_handler</phrase><phrase role="special">&lt;</phrase><phrase
11815 role="identifier">T</phrase><phrase role="special">&gt;&gt;::</phrase><phrase
11816 role="identifier">get</phrase><phrase role="special">()</phrase></code> resumes,
11817 it returns the stored <code><phrase role="identifier">value_</phrase></code>
11818 to <code><phrase role="identifier">async_something</phrase><phrase role="special">()</phrase></code>
11819 and ultimately to <code><phrase role="identifier">async_something</phrase><phrase
11820 role="special">()</phrase></code>&#8217;s caller.
11821 </para>
11822 <para>
11823 The case of a callback signature <code><phrase role="keyword">void</phrase><phrase
11824 role="special">(</phrase><phrase role="identifier">T</phrase><phrase role="special">)</phrase></code>
11825 is handled by having <code><phrase role="identifier">yield_handler</phrase><phrase
11826 role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase role="special">&gt;::</phrase><phrase
11827 role="keyword">operator</phrase><phrase role="special">()(</phrase><phrase
11828 role="identifier">T</phrase><phrase role="special">)</phrase></code> engage
11829 the <code><phrase role="keyword">void</phrase><phrase role="special">(</phrase><phrase
11830 role="identifier">error_code</phrase><phrase role="special">,</phrase> <phrase
11831 role="identifier">T</phrase><phrase role="special">)</phrase></code> machinery,
11832 passing a <quote>success</quote> <code><phrase role="identifier">error_code</phrase></code>.
11833 </para>
11834 <para>
11835 The source code above is found in <ulink url="../../examples/asio/yield.hpp">yield.hpp</ulink>
11836 and <ulink url="../../examples/asio/detail/yield.hpp">detail/yield.hpp</ulink>.
11837 </para>
11838 </section>
11839 </section>
11840 <section id="fiber.nonblocking">
11841 <title><anchor id="nonblocking"/><link linkend="fiber.nonblocking">Integrating
11842 Fibers with Nonblocking I/O</link></title>
11843 <bridgehead renderas="sect3" id="fiber.nonblocking.h0">
11844 <phrase id="fiber.nonblocking.overview"/><link linkend="fiber.nonblocking.overview">Overview</link>
11845 </bridgehead>
11846 <para>
11847 <emphasis>Nonblocking</emphasis> I/O is distinct from <emphasis>asynchronous</emphasis>
11848 I/O. A true async I/O operation promises to initiate the operation and notify
11849 the caller on completion, usually via some sort of callback (as described in
11850 <link linkend="callbacks">Integrating Fibers with Asynchronous Callbacks</link>).
11851 </para>
11852 <para>
11853 In contrast, a nonblocking I/O operation refuses to start at all if it would
11854 be necessary to block, returning an error code such as <ulink url="http://man7.org/linux/man-pages/man3/errno.3.html"><code><phrase
11855 role="identifier">EWOULDBLOCK</phrase></code></ulink>. The operation is performed
11856 only when it can complete immediately. In effect, the caller must repeatedly
11857 retry the operation until it stops returning <code><phrase role="identifier">EWOULDBLOCK</phrase></code>.
11858 </para>
11859 <para>
11860 In a classic event-driven program, it can be something of a headache to use
11861 nonblocking I/O. At the point where the nonblocking I/O is attempted, a return
11862 value of <code><phrase role="identifier">EWOULDBLOCK</phrase></code> requires
11863 the caller to pass control back to the main event loop, arranging to retry
11864 again on the next iteration.
11865 </para>
11866 <para>
11867 Worse, a nonblocking I/O operation might <emphasis>partially</emphasis> succeed.
11868 That means that the relevant business logic must continue receiving control
11869 on every main loop iteration until all required data have been processed: a
11870 doubly-nested loop, implemented as a callback-driven state machine.
11871 </para>
11872 <para>
11873 <emphasis role="bold">Boost.Fiber</emphasis> can simplify this problem immensely.
11874 Once you have integrated with the application's main loop as described in
11875 <link linkend="integration">Sharing a Thread with Another Main Loop</link>,
11876 waiting for the next main-loop iteration is as simple as calling <link linkend="this_fiber_yield"><code>this_fiber::yield()</code></link>.
11877 </para>
11878 <bridgehead renderas="sect3" id="fiber.nonblocking.h1">
11879 <phrase id="fiber.nonblocking.example_nonblocking_api"/><link linkend="fiber.nonblocking.example_nonblocking_api">Example
11880 Nonblocking API</link>
11881 </bridgehead>
11882 <para>
11883 For purposes of illustration, consider this API:
11884 </para>
11885 <para>
11886 <programlisting><phrase role="keyword">class</phrase> <phrase role="identifier">NonblockingAPI</phrase> <phrase role="special">{</phrase>
11887 <phrase role="keyword">public</phrase><phrase role="special">:</phrase>
11888 <phrase role="identifier">NonblockingAPI</phrase><phrase role="special">();</phrase>
11889
11890 <phrase role="comment">// nonblocking operation: may return EWOULDBLOCK</phrase>
11891 <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>
11892
11893 <phrase role="special">...</phrase>
11894 <phrase role="special">};</phrase>
11895 </programlisting>
11896 </para>
11897 <bridgehead renderas="sect3" id="fiber.nonblocking.h2">
11898 <phrase id="fiber.nonblocking.polling_for_completion"/><link linkend="fiber.nonblocking.polling_for_completion">Polling
11899 for Completion</link>
11900 </bridgehead>
11901 <para>
11902 We can build a low-level wrapper around <code><phrase role="identifier">NonblockingAPI</phrase><phrase
11903 role="special">::</phrase><phrase role="identifier">read</phrase><phrase role="special">()</phrase></code>
11904 that shields its caller from ever having to deal with <code><phrase role="identifier">EWOULDBLOCK</phrase></code>:
11905 </para>
11906 <para>
11907 <programlisting><phrase role="comment">// guaranteed not to return EWOULDBLOCK</phrase>
11908 <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>
11909 <phrase role="keyword">int</phrase> <phrase role="identifier">error</phrase><phrase role="special">;</phrase>
11910 <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>
11911 <phrase role="comment">// not ready yet -- try again on the next iteration of the</phrase>
11912 <phrase role="comment">// application's main loop</phrase>
11913 <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>
11914 <phrase role="special">}</phrase>
11915 <phrase role="keyword">return</phrase> <phrase role="identifier">error</phrase><phrase role="special">;</phrase>
11916 <phrase role="special">}</phrase>
11917 </programlisting>
11918 </para>
11919 <bridgehead renderas="sect3" id="fiber.nonblocking.h3">
11920 <phrase id="fiber.nonblocking.filling_all_desired_data"/><link linkend="fiber.nonblocking.filling_all_desired_data">Filling
11921 All Desired Data</link>
11922 </bridgehead>
11923 <para>
11924 Given <code><phrase role="identifier">read_chunk</phrase><phrase role="special">()</phrase></code>,
11925 we can straightforwardly iterate until we have all desired data:
11926 </para>
11927 <para>
11928 <programlisting><phrase role="comment">// keep reading until desired length, EOF or error</phrase>
11929 <phrase role="comment">// may return both partial data and nonzero error</phrase>
11930 <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>
11931 <phrase role="comment">// we're going to accumulate results into 'data'</phrase>
11932 <phrase role="identifier">data</phrase><phrase role="special">.</phrase><phrase role="identifier">clear</phrase><phrase role="special">();</phrase>
11933 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="identifier">chunk</phrase><phrase role="special">;</phrase>
11934 <phrase role="keyword">int</phrase> <phrase role="identifier">error</phrase> <phrase role="special">=</phrase> <phrase role="number">0</phrase><phrase role="special">;</phrase>
11935 <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>
11936 <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>
11937 <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>
11938 <phrase role="special">}</phrase>
11939 <phrase role="keyword">return</phrase> <phrase role="identifier">error</phrase><phrase role="special">;</phrase>
11940 <phrase role="special">}</phrase>
11941 </programlisting>
11942 </para>
11943 <para>
11944 (Of <emphasis>course</emphasis> there are more efficient ways to accumulate
11945 string data. That's not the point of this example.)
11946 </para>
11947 <bridgehead renderas="sect3" id="fiber.nonblocking.h4">
11948 <phrase id="fiber.nonblocking.wrapping_it_up"/><link linkend="fiber.nonblocking.wrapping_it_up">Wrapping
11949 it Up</link>
11950 </bridgehead>
11951 <para>
11952 Finally, we can define a relevant exception:
11953 </para>
11954 <para>
11955 <programlisting><phrase role="comment">// exception class augmented with both partially-read data and errorcode</phrase>
11956 <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>
11957 <phrase role="keyword">public</phrase><phrase role="special">:</phrase>
11958 <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>
11959 <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>
11960 <phrase role="identifier">partial_</phrase><phrase role="special">(</phrase> <phrase role="identifier">partial</phrase><phrase role="special">),</phrase>
11961 <phrase role="identifier">ec_</phrase><phrase role="special">(</phrase> <phrase role="identifier">ec</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
11962 <phrase role="special">}</phrase>
11963
11964 <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>
11965 <phrase role="keyword">return</phrase> <phrase role="identifier">partial_</phrase><phrase role="special">;</phrase>
11966 <phrase role="special">}</phrase>
11967
11968 <phrase role="keyword">int</phrase> <phrase role="identifier">get_errorcode</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase> <phrase role="special">{</phrase>
11969 <phrase role="keyword">return</phrase> <phrase role="identifier">ec_</phrase><phrase role="special">;</phrase>
11970 <phrase role="special">}</phrase>
11971
11972 <phrase role="keyword">private</phrase><phrase role="special">:</phrase>
11973 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="identifier">partial_</phrase><phrase role="special">;</phrase>
11974 <phrase role="keyword">int</phrase> <phrase role="identifier">ec_</phrase><phrase role="special">;</phrase>
11975 <phrase role="special">};</phrase>
11976 </programlisting>
11977 </para>
11978 <para>
11979 and write a simple <code><phrase role="identifier">read</phrase><phrase role="special">()</phrase></code>
11980 function that either returns all desired data or throws <code><phrase role="identifier">IncompleteRead</phrase></code>:
11981 </para>
11982 <para>
11983 <programlisting><phrase role="comment">// read all desired data or throw IncompleteRead</phrase>
11984 <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>
11985 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="identifier">data</phrase><phrase role="special">;</phrase>
11986 <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>
11987
11988 <phrase role="comment">// for present purposes, EOF isn't a failure</phrase>
11989 <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>
11990 <phrase role="keyword">return</phrase> <phrase role="identifier">data</phrase><phrase role="special">;</phrase>
11991 <phrase role="special">}</phrase>
11992
11993 <phrase role="comment">// oh oh, partial read</phrase>
11994 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">ostringstream</phrase> <phrase role="identifier">msg</phrase><phrase role="special">;</phrase>
11995 <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>
11996 <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>
11997 <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>
11998 <phrase role="special">}</phrase>
11999 </programlisting>
12000 </para>
12001 <para>
12002 Once we can transparently wait for the next main-loop iteration using <link linkend="this_fiber_yield"><code>this_fiber::yield()</code></link>,
12003 ordinary encapsulation Just Works.
12004 </para>
12005 <para>
12006 The source code above is found in <ulink url="../../examples/adapt_nonblocking.cpp">adapt_nonblocking.cpp</ulink>.
12007 </para>
12008 </section>
12009 <section id="fiber.when_any">
12010 <title><anchor id="when_any"/><link linkend="fiber.when_any">when_any / when_all
12011 functionality</link></title>
12012 <bridgehead renderas="sect3" id="fiber.when_any.h0">
12013 <phrase id="fiber.when_any.overview"/><link linkend="fiber.when_any.overview">Overview</link>
12014 </bridgehead>
12015 <para>
12016 A bit of wisdom from the early days of computing still holds true today: prefer
12017 to model program state using the instruction pointer rather than with Boolean
12018 flags. In other words, if the program must <quote>do something</quote> and
12019 then do something almost the same, but with minor changes... perhaps parts
12020 of that something should be broken out as smaller separate functions, rather
12021 than introducing flags to alter the internal behavior of a monolithic function.
12022 </para>
12023 <para>
12024 To that we would add: prefer to describe control flow using C++ native constructs
12025 such as function calls, <code><phrase role="keyword">if</phrase></code>, <code><phrase
12026 role="keyword">while</phrase></code>, <code><phrase role="keyword">for</phrase></code>,
12027 <code><phrase role="keyword">do</phrase></code> et al. rather than as chains
12028 of callbacks.
12029 </para>
12030 <para>
12031 One of the great strengths of <emphasis role="bold">Boost.Fiber</emphasis>
12032 is the flexibility it confers on the coder to restructure an application from
12033 chains of callbacks to straightforward C++ statement sequence, even when code
12034 in that fiber is in fact interleaved with code running in other fibers.
12035 </para>
12036 <para>
12037 There has been much recent discussion about the benefits of when_any and when_all
12038 functionality. When dealing with asynchronous and possibly unreliable services,
12039 these are valuable idioms. But of course when_any and when_all are closely
12040 tied to the use of chains of callbacks.
12041 </para>
12042 <para>
12043 This section presents recipes for achieving the same ends, in the context of
12044 a fiber that wants to <quote>do something</quote> when one or more other independent
12045 activities have completed. Accordingly, these are <code><phrase role="identifier">wait_something</phrase><phrase
12046 role="special">()</phrase></code> functions rather than <code><phrase role="identifier">when_something</phrase><phrase
12047 role="special">()</phrase></code> functions. The expectation is that the calling
12048 fiber asks to launch those independent activities, then waits for them, then
12049 sequentially proceeds with whatever processing depends on those results.
12050 </para>
12051 <para>
12052 The function names shown (e.g. <link linkend="wait_first_simple"><code><phrase
12053 role="identifier">wait_first_simple</phrase><phrase role="special">()</phrase></code></link>)
12054 are for illustrative purposes only, because all these functions have been bundled
12055 into a single source file. Presumably, if (say) <link linkend="wait_first_success"><code><phrase
12056 role="identifier">wait_first_success</phrase><phrase role="special">()</phrase></code></link>
12057 best suits your application needs, you could introduce that variant with the
12058 name <code><phrase role="identifier">wait_any</phrase><phrase role="special">()</phrase></code>.
12059 </para>
12060 <note>
12061 <para>
12062 The functions presented in this section accept variadic argument lists of
12063 task functions. Corresponding <code><phrase role="identifier">wait_something</phrase><phrase
12064 role="special">()</phrase></code> functions accepting a container of task
12065 functions are left as an exercise for the interested reader. Those should
12066 actually be simpler. Most of the complexity would arise from overloading
12067 the same name for both purposes.
12068 </para>
12069 </note>
12070 <para>
12071 All the source code for this section is found in <ulink url="../../examples/wait_stuff.cpp">wait_stuff.cpp</ulink>.
12072 </para>
12073 <bridgehead renderas="sect3" id="fiber.when_any.h1">
12074 <phrase id="fiber.when_any.example_task_function"/><link linkend="fiber.when_any.example_task_function">Example
12075 Task Function</link>
12076 </bridgehead>
12077 <para>
12078 <anchor id="wait_sleeper"/>We found it convenient to model an asynchronous
12079 task using this function:
12080 </para>
12081 <para>
12082 <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>
12083 <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>
12084 <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>
12085 <phrase role="identifier">descb</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="identifier">item</phrase><phrase role="special">;</phrase>
12086 <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>
12087 <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>
12088 <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>
12089
12090 <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>
12091 <phrase role="keyword">if</phrase> <phrase role="special">(</phrase> <phrase role="identifier">thrw</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
12092 <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>
12093 <phrase role="special">}</phrase>
12094 <phrase role="keyword">return</phrase> <phrase role="identifier">item</phrase><phrase role="special">;</phrase>
12095 <phrase role="special">}</phrase>
12096 </programlisting>
12097 </para>
12098 <para>
12099 with type-specific <code><phrase role="identifier">sleeper</phrase><phrase
12100 role="special">()</phrase></code> <quote>front ends</quote> for <code><phrase
12101 role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase></code>,
12102 <code><phrase role="keyword">double</phrase></code> and <code><phrase role="keyword">int</phrase></code>.
12103 </para>
12104 <para>
12105 <code><phrase role="identifier">Verbose</phrase></code> simply prints a message
12106 to <code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase
12107 role="identifier">cout</phrase></code> on construction and destruction.
12108 </para>
12109 <para>
12110 Basically:
12111 </para>
12112 <orderedlist>
12113 <listitem>
12114 <simpara>
12115 <code><phrase role="identifier">sleeper</phrase><phrase role="special">()</phrase></code>
12116 prints a start message;
12117 </simpara>
12118 </listitem>
12119 <listitem>
12120 <simpara>
12121 sleeps for the specified number of milliseconds;
12122 </simpara>
12123 </listitem>
12124 <listitem>
12125 <simpara>
12126 if <code><phrase role="identifier">thrw</phrase></code> is passed as <code><phrase
12127 role="keyword">true</phrase></code>, throws a string description of the
12128 passed <code><phrase role="identifier">item</phrase></code>;
12129 </simpara>
12130 </listitem>
12131 <listitem>
12132 <simpara>
12133 else returns the passed <code><phrase role="identifier">item</phrase></code>.
12134 </simpara>
12135 </listitem>
12136 <listitem>
12137 <simpara>
12138 On the way out, <code><phrase role="identifier">sleeper</phrase><phrase
12139 role="special">()</phrase></code> produces a stop message.
12140 </simpara>
12141 </listitem>
12142 </orderedlist>
12143 <para>
12144 This function will feature in the example calls to the various functions presented
12145 below.
12146 </para>
12147 <section id="fiber.when_any.when_any">
12148 <title><link linkend="fiber.when_any.when_any">when_any</link></title>
12149 <section id="fiber.when_any.when_any.when_any__simple_completion">
12150 <title><anchor id="wait_first_simple_section"/><link linkend="fiber.when_any.when_any.when_any__simple_completion">when_any,
12151 simple completion</link></title>
12152 <para>
12153 The simplest case is when you only need to know that the first of a set
12154 of asynchronous tasks has completed &mdash; but you don't need to obtain a return
12155 value, and you're confident that they will not throw exceptions.
12156 </para>
12157 <para>
12158 <anchor id="wait_done"/>For this we introduce a <code><phrase role="identifier">Done</phrase></code>
12159 class to wrap a <code><phrase role="keyword">bool</phrase></code> variable
12160 with a <link linkend="class_condition_variable"><code>condition_variable</code></link> and a <link linkend="class_mutex"><code>mutex</code></link>:
12161 </para>
12162 <para>
12163 <programlisting><phrase role="comment">// Wrap canonical pattern for condition_variable + bool flag</phrase>
12164 <phrase role="keyword">struct</phrase> <phrase role="identifier">Done</phrase> <phrase role="special">{</phrase>
12165 <phrase role="keyword">private</phrase><phrase role="special">:</phrase>
12166 <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>
12167 <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>
12168 <phrase role="keyword">bool</phrase> <phrase role="identifier">ready</phrase> <phrase role="special">=</phrase> <phrase role="keyword">false</phrase><phrase role="special">;</phrase>
12169
12170 <phrase role="keyword">public</phrase><phrase role="special">:</phrase>
12171 <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>
12172
12173 <phrase role="keyword">void</phrase> <phrase role="identifier">wait</phrase><phrase role="special">()</phrase> <phrase role="special">{</phrase>
12174 <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>
12175 <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>
12176 <phrase role="special">}</phrase>
12177
12178 <phrase role="keyword">void</phrase> <phrase role="identifier">notify</phrase><phrase role="special">()</phrase> <phrase role="special">{</phrase>
12179 <phrase role="special">{</phrase>
12180 <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>
12181 <phrase role="identifier">ready</phrase> <phrase role="special">=</phrase> <phrase role="keyword">true</phrase><phrase role="special">;</phrase>
12182 <phrase role="special">}</phrase> <phrase role="comment">// release mutex</phrase>
12183 <phrase role="identifier">cond</phrase><phrase role="special">.</phrase><phrase role="identifier">notify_one</phrase><phrase role="special">();</phrase>
12184 <phrase role="special">}</phrase>
12185 <phrase role="special">};</phrase>
12186 </programlisting>
12187 </para>
12188 <para>
12189 The pattern we follow throughout this section is to pass a <ulink url="http://www.cplusplus.com/reference/memory/shared_ptr/"><code><phrase
12190 role="identifier">std</phrase><phrase role="special">::</phrase><phrase
12191 role="identifier">shared_ptr</phrase><phrase role="special">&lt;&gt;</phrase></code></ulink>
12192 to the relevant synchronization object to the various tasks' fiber functions.
12193 This eliminates nagging questions about the lifespan of the synchronization
12194 object relative to the last of the fibers.
12195 </para>
12196 <para>
12197 <anchor id="wait_first_simple"/><code><phrase role="identifier">wait_first_simple</phrase><phrase
12198 role="special">()</phrase></code> uses that tactic for <link linkend="wait_done"><code><phrase
12199 role="identifier">Done</phrase></code></link>:
12200 </para>
12201 <para>
12202 <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>
12203 <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>
12204 <phrase role="comment">// Use shared_ptr because each function's fiber will bind it separately,</phrase>
12205 <phrase role="comment">// and we're going to return before the last of them completes.</phrase>
12206 <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>
12207 <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>
12208 <phrase role="identifier">done</phrase><phrase role="special">-&gt;</phrase><phrase role="identifier">wait</phrase><phrase role="special">();</phrase>
12209 <phrase role="special">}</phrase>
12210 </programlisting>
12211 </para>
12212 <para>
12213 <anchor id="wait_first_simple_impl"/><code><phrase role="identifier">wait_first_simple_impl</phrase><phrase
12214 role="special">()</phrase></code> is an ordinary recursion over the argument
12215 pack, capturing <code><phrase role="identifier">Done</phrase><phrase role="special">::</phrase><phrase
12216 role="identifier">ptr</phrase></code> for each new fiber:
12217 </para>
12218 <para>
12219 <programlisting><phrase role="comment">// Degenerate case: when there are no functions to wait for, return</phrase>
12220 <phrase role="comment">// immediately.</phrase>
12221 <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>
12222 <phrase role="special">}</phrase>
12223
12224 <phrase role="comment">// When there's at least one function to wait for, launch it and recur to</phrase>
12225 <phrase role="comment">// process the rest.</phrase>
12226 <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>
12227 <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>
12228 <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>
12229 <phrase role="identifier">function</phrase><phrase role="special">();</phrase>
12230 <phrase role="identifier">done</phrase><phrase role="special">-&gt;</phrase><phrase role="identifier">notify</phrase><phrase role="special">();</phrase>
12231 <phrase role="special">}).</phrase><phrase role="identifier">detach</phrase><phrase role="special">();</phrase>
12232 <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>
12233 <phrase role="special">}</phrase>
12234 </programlisting>
12235 </para>
12236 <para>
12237 The body of the fiber's lambda is extremely simple, as promised: call the
12238 function, notify <link linkend="wait_done"><code><phrase role="identifier">Done</phrase></code></link>
12239 when it returns. The first fiber to do so allows <code><phrase role="identifier">wait_first_simple</phrase><phrase
12240 role="special">()</phrase></code> to return &mdash; which is why it's useful to
12241 have <code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase
12242 role="identifier">shared_ptr</phrase><phrase role="special">&lt;</phrase><phrase
12243 role="identifier">Done</phrase><phrase role="special">&gt;</phrase></code>
12244 manage the lifespan of our <code><phrase role="identifier">Done</phrase></code>
12245 object rather than declaring it as a stack variable in <code><phrase role="identifier">wait_first_simple</phrase><phrase
12246 role="special">()</phrase></code>.
12247 </para>
12248 <para>
12249 This is how you might call it:
12250 </para>
12251 <para>
12252 <programlisting><phrase role="identifier">wait_first_simple</phrase><phrase role="special">(</phrase>
12253 <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>
12254 <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>
12255 <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>
12256 </programlisting>
12257 </para>
12258 <para>
12259 In this example, control resumes after <code><phrase role="identifier">wait_first_simple</phrase><phrase
12260 role="special">()</phrase></code> when <link linkend="wait_sleeper"><code><phrase
12261 role="identifier">sleeper</phrase><phrase role="special">(</phrase><phrase
12262 role="string">&quot;wfs_short&quot;</phrase><phrase role="special">,</phrase>
12263 <phrase role="number">50</phrase><phrase role="special">)</phrase></code></link>
12264 completes &mdash; even though the other two <code><phrase role="identifier">sleeper</phrase><phrase
12265 role="special">()</phrase></code> fibers are still running.
12266 </para>
12267 </section>
12268 <section id="fiber.when_any.when_any.when_any__return_value">
12269 <title><link linkend="fiber.when_any.when_any.when_any__return_value">when_any,
12270 return value</link></title>
12271 <para>
12272 It seems more useful to add the ability to capture the return value from
12273 the first of the task functions to complete. Again, we assume that none
12274 will throw an exception.
12275 </para>
12276 <para>
12277 One tactic would be to adapt our <link linkend="wait_done"><code><phrase
12278 role="identifier">Done</phrase></code></link> class to store the first
12279 of the return values, rather than a simple <code><phrase role="keyword">bool</phrase></code>.
12280 However, we choose instead to use a <link linkend="class_unbounded_channel"><code>unbounded_channel&lt;&gt;</code></link>.
12281 We'll only need to enqueue the first value, so we'll <link linkend="unbounded_channel_close"><code>unbounded_channel::close()</code></link> it
12282 once we've retrieved that value. Subsequent <code><phrase role="identifier">push</phrase><phrase
12283 role="special">()</phrase></code> calls will return <code><phrase role="identifier">closed</phrase></code>.
12284 </para>
12285 <para>
12286 <anchor id="wait_first_value"/>
12287 <programlisting><phrase role="comment">// Assume that all passed functions have the same return type. The return type</phrase>
12288 <phrase role="comment">// of wait_first_value() is the return type of the first passed function. It is</phrase>
12289 <phrase role="comment">// simply invalid to pass NO functions.</phrase>
12290 <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>
12291 <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>
12292 <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>
12293 <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>
12294 <phrase role="keyword">typedef</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">unbounded_channel</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">return_t</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">channel_t</phrase><phrase role="special">;</phrase>
12295 <phrase role="keyword">auto</phrase> <phrase role="identifier">channelp</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">make_shared</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">channel_t</phrase> <phrase role="special">&gt;()</phrase> <phrase role="special">);</phrase>
12296 <phrase role="comment">// launch all the relevant fibers</phrase>
12297 <phrase role="identifier">wait_first_value_impl</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">return_t</phrase> <phrase role="special">&gt;(</phrase> <phrase role="identifier">channelp</phrase><phrase role="special">,</phrase>
12298 <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>
12299 <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>
12300 <phrase role="comment">// retrieve the first value</phrase>
12301 <phrase role="identifier">return_t</phrase> <phrase role="identifier">value</phrase><phrase role="special">(</phrase> <phrase role="identifier">channelp</phrase><phrase role="special">-&gt;</phrase><phrase role="identifier">value_pop</phrase><phrase role="special">()</phrase> <phrase role="special">);</phrase>
12302 <phrase role="comment">// close the channel: no subsequent push() has to succeed</phrase>
12303 <phrase role="identifier">channelp</phrase><phrase role="special">-&gt;</phrase><phrase role="identifier">close</phrase><phrase role="special">();</phrase>
12304 <phrase role="keyword">return</phrase> <phrase role="identifier">value</phrase><phrase role="special">;</phrase>
12305 <phrase role="special">}</phrase>
12306 </programlisting>
12307 </para>
12308 <para>
12309 <anchor id="wait_first_value_impl"/>The meat of the <code><phrase role="identifier">wait_first_value_impl</phrase><phrase
12310 role="special">()</phrase></code> function is as you might expect:
12311 </para>
12312 <para>
12313 <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>
12314 <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">unbounded_channel</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">T</phrase> <phrase role="special">&gt;</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">channel</phrase><phrase role="special">,</phrase>
12315 <phrase role="identifier">Fn</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="identifier">function</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
12316 <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">fiber</phrase><phrase role="special">(</phrase> <phrase role="special">[</phrase><phrase role="identifier">channel</phrase><phrase role="special">,</phrase> <phrase role="identifier">function</phrase><phrase role="special">](){</phrase>
12317 <phrase role="comment">// Ignore channel_op_status returned by push():</phrase>
12318 <phrase role="comment">// might be closed; we simply don't care.</phrase>
12319 <phrase role="identifier">channel</phrase><phrase role="special">-&gt;</phrase><phrase role="identifier">push</phrase><phrase role="special">(</phrase> <phrase role="identifier">function</phrase><phrase role="special">()</phrase> <phrase role="special">);</phrase>
12320 <phrase role="special">}).</phrase><phrase role="identifier">detach</phrase><phrase role="special">();</phrase>
12321 <phrase role="special">}</phrase>
12322 </programlisting>
12323 </para>
12324 <para>
12325 It calls the passed function, pushes its return value and ignores the
12326 <code><phrase role="identifier">push</phrase><phrase role="special">()</phrase></code>
12327 result. You might call it like this:
12328 </para>
12329 <para>
12330 <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>
12331 <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>
12332 <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>
12333 <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>
12334 <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>
12335 <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>
12336 </programlisting>
12337 </para>
12338 </section>
12339 <section id="fiber.when_any.when_any.when_any__produce_first_outcome__whether_result_or_exception">
12340 <title><link linkend="fiber.when_any.when_any.when_any__produce_first_outcome__whether_result_or_exception">when_any,
12341 produce first outcome, whether result or exception</link></title>
12342 <para>
12343 We may not be running in an environment in which we can guarantee no exception
12344 will be thrown by any of our task functions. In that case, the above implementations
12345 of <code><phrase role="identifier">wait_first_something</phrase><phrase
12346 role="special">()</phrase></code> would be naïve: as mentioned in <link
12347 linkend="exceptions">the section on Fiber Management</link>, an uncaught
12348 exception in one of our task fibers would cause <code><phrase role="identifier">std</phrase><phrase
12349 role="special">::</phrase><phrase role="identifier">terminate</phrase><phrase
12350 role="special">()</phrase></code> to be called.
12351 </para>
12352 <para>
12353 Let's at least ensure that such an exception would propagate to the fiber
12354 awaiting the first result. We can use <link linkend="class_future"><code>future&lt;&gt;</code></link> to transport
12355 either a return value or an exception. Therefore, we will change <link
12356 linkend="wait_first_value"><code><phrase role="identifier">wait_first_value</phrase><phrase
12357 role="special">()</phrase></code></link>'s <link linkend="class_unbounded_channel"><code>unbounded_channel&lt;&gt;</code></link> to
12358 hold <code><phrase role="identifier">future</phrase><phrase role="special">&lt;</phrase>
12359 <phrase role="identifier">T</phrase> <phrase role="special">&gt;</phrase></code>
12360 items instead of simply <code><phrase role="identifier">T</phrase></code>.
12361 </para>
12362 <para>
12363 Once we have a <code><phrase role="identifier">future</phrase><phrase role="special">&lt;&gt;</phrase></code>
12364 in hand, all we need do is call <link linkend="future_get"><code>future::get()</code></link>, which will either
12365 return the value or rethrow the exception.
12366 </para>
12367 <para>
12368 <anchor id="wait_first_outcome"/>
12369 <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>
12370 <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>
12371 <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>
12372 <phrase role="comment">// In this case, the value we pass through the channel is actually a</phrase>
12373 <phrase role="comment">// future -- which is already ready. future can carry either a value or an</phrase>
12374 <phrase role="comment">// exception.</phrase>
12375 <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>
12376 <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>
12377 <phrase role="keyword">typedef</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">unbounded_channel</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">future_t</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">channel_t</phrase><phrase role="special">;</phrase>
12378 <phrase role="keyword">auto</phrase> <phrase role="identifier">channelp</phrase><phrase role="special">(</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">make_shared</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">channel_t</phrase> <phrase role="special">&gt;()</phrase> <phrase role="special">);</phrase>
12379 <phrase role="comment">// launch all the relevant fibers</phrase>
12380 <phrase role="identifier">wait_first_outcome_impl</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">return_t</phrase> <phrase role="special">&gt;(</phrase> <phrase role="identifier">channelp</phrase><phrase role="special">,</phrase>
12381 <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>
12382 <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>
12383 <phrase role="comment">// retrieve the first future</phrase>
12384 <phrase role="identifier">future_t</phrase> <phrase role="identifier">future</phrase><phrase role="special">(</phrase> <phrase role="identifier">channelp</phrase><phrase role="special">-&gt;</phrase><phrase role="identifier">value_pop</phrase><phrase role="special">()</phrase> <phrase role="special">);</phrase>
12385 <phrase role="comment">// close the channel: no subsequent push() has to succeed</phrase>
12386 <phrase role="identifier">channelp</phrase><phrase role="special">-&gt;</phrase><phrase role="identifier">close</phrase><phrase role="special">();</phrase>
12387 <phrase role="comment">// either return value or throw exception</phrase>
12388 <phrase role="keyword">return</phrase> <phrase role="identifier">future</phrase><phrase role="special">.</phrase><phrase role="identifier">get</phrase><phrase role="special">();</phrase>
12389 <phrase role="special">}</phrase>
12390 </programlisting>
12391 </para>
12392 <para>
12393 So far so good &mdash; but there's a timing issue. How should we obtain the <code><phrase
12394 role="identifier">future</phrase><phrase role="special">&lt;&gt;</phrase></code>
12395 to <link linkend="unbounded_channel_push"><code>unbounded_channel::push()</code></link> on the channel?
12396 </para>
12397 <para>
12398 We could call <link linkend="fibers_async"><code>fibers::async()</code></link>. That would certainly produce
12399 a <code><phrase role="identifier">future</phrase><phrase role="special">&lt;&gt;</phrase></code>
12400 for the task function. The trouble is that it would return too quickly!
12401 We only want <code><phrase role="identifier">future</phrase><phrase role="special">&lt;&gt;</phrase></code>
12402 items for <emphasis>completed</emphasis> tasks on our <code><phrase role="identifier">unbounded_channel</phrase><phrase
12403 role="special">&lt;&gt;</phrase></code>. In fact, we only want the <code><phrase
12404 role="identifier">future</phrase><phrase role="special">&lt;&gt;</phrase></code>
12405 for the one that completes first. If each fiber launched by <code><phrase
12406 role="identifier">wait_first_outcome</phrase><phrase role="special">()</phrase></code>
12407 were to <code><phrase role="identifier">push</phrase><phrase role="special">()</phrase></code>
12408 the result of calling <code><phrase role="identifier">async</phrase><phrase
12409 role="special">()</phrase></code>, the channel would only ever report the
12410 result of the leftmost task item &mdash; <emphasis>not</emphasis> the one that
12411 completes most quickly.
12412 </para>
12413 <para>
12414 Calling <link linkend="future_get"><code>future::get()</code></link> on the future returned by <code><phrase
12415 role="identifier">async</phrase><phrase role="special">()</phrase></code>
12416 wouldn't be right. You can only call <code><phrase role="identifier">get</phrase><phrase
12417 role="special">()</phrase></code> once per <code><phrase role="identifier">future</phrase><phrase
12418 role="special">&lt;&gt;</phrase></code> instance! And if there were an
12419 exception, it would be rethrown inside the helper fiber at the producer
12420 end of the channel, rather than propagated to the consumer end.
12421 </para>
12422 <para>
12423 We could call <link linkend="future_wait"><code>future::wait()</code></link>. That would block the helper fiber
12424 until the <code><phrase role="identifier">future</phrase><phrase role="special">&lt;&gt;</phrase></code>
12425 became ready, at which point we could <code><phrase role="identifier">push</phrase><phrase
12426 role="special">()</phrase></code> it to be retrieved by <code><phrase role="identifier">wait_first_outcome</phrase><phrase
12427 role="special">()</phrase></code>.
12428 </para>
12429 <para>
12430 That would work &mdash; but there's a simpler tactic that avoids creating an extra
12431 fiber. We can wrap the task function in a <link linkend="class_packaged_task"><code>packaged_task&lt;&gt;</code></link>.
12432 While one naturally thinks of passing a <code><phrase role="identifier">packaged_task</phrase><phrase
12433 role="special">&lt;&gt;</phrase></code> to a new fiber &mdash; that is, in fact,
12434 what <code><phrase role="identifier">async</phrase><phrase role="special">()</phrase></code>
12435 does &mdash; in this case, we're already running in the helper fiber at the producer
12436 end of the channel! We can simply <emphasis>call</emphasis> the <code><phrase
12437 role="identifier">packaged_task</phrase><phrase role="special">&lt;&gt;</phrase></code>.
12438 On return from that call, the task function has completed, meaning that
12439 the <code><phrase role="identifier">future</phrase><phrase role="special">&lt;&gt;</phrase></code>
12440 obtained from the <code><phrase role="identifier">packaged_task</phrase><phrase
12441 role="special">&lt;&gt;</phrase></code> is certain to be ready. At that
12442 point we can simply <code><phrase role="identifier">push</phrase><phrase
12443 role="special">()</phrase></code> it to the channel.
12444 </para>
12445 <para>
12446 <anchor id="wait_first_outcome_impl"/>
12447 <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">CHANNELP</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Fn</phrase> <phrase role="special">&gt;</phrase>
12448 <phrase role="keyword">void</phrase> <phrase role="identifier">wait_first_outcome_impl</phrase><phrase role="special">(</phrase> <phrase role="identifier">CHANNELP</phrase> <phrase role="identifier">channel</phrase><phrase role="special">,</phrase> <phrase role="identifier">Fn</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="identifier">function</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
12449 <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>
12450 <phrase role="comment">// Use std::bind() here for C++11 compatibility. C++11 lambda capture</phrase>
12451 <phrase role="comment">// can't move a move-only Fn type, but bind() can. Let bind() move the</phrase>
12452 <phrase role="comment">// channel pointer and the function into the bound object, passing</phrase>
12453 <phrase role="comment">// references into the lambda.</phrase>
12454 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">bind</phrase><phrase role="special">(</phrase>
12455 <phrase role="special">[](</phrase> <phrase role="identifier">CHANNELP</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">channel</phrase><phrase role="special">,</phrase>
12456 <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>
12457 <phrase role="comment">// Instantiate a packaged_task to capture any exception thrown by</phrase>
12458 <phrase role="comment">// function.</phrase>
12459 <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>
12460 <phrase role="comment">// Immediately run this packaged_task on same fiber. We want</phrase>
12461 <phrase role="comment">// function() to have completed BEFORE we push the future.</phrase>
12462 <phrase role="identifier">task</phrase><phrase role="special">();</phrase>
12463 <phrase role="comment">// Pass the corresponding future to consumer. Ignore</phrase>
12464 <phrase role="comment">// channel_op_status returned by push(): might be closed; we</phrase>
12465 <phrase role="comment">// simply don't care.</phrase>
12466 <phrase role="identifier">channel</phrase><phrase role="special">-&gt;</phrase><phrase role="identifier">push</phrase><phrase role="special">(</phrase> <phrase role="identifier">task</phrase><phrase role="special">.</phrase><phrase role="identifier">get_future</phrase><phrase role="special">()</phrase> <phrase role="special">);</phrase>
12467 <phrase role="special">},</phrase>
12468 <phrase role="identifier">channel</phrase><phrase role="special">,</phrase>
12469 <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>
12470 <phrase role="special">)).</phrase><phrase role="identifier">detach</phrase><phrase role="special">();</phrase>
12471 <phrase role="special">}</phrase>
12472 </programlisting>
12473 </para>
12474 <para>
12475 Calling it might look like this:
12476 </para>
12477 <para>
12478 <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>
12479 <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>
12480 <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>
12481 <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>
12482 <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>
12483 <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>
12484
12485 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="identifier">thrown</phrase><phrase role="special">;</phrase>
12486 <phrase role="keyword">try</phrase> <phrase role="special">{</phrase>
12487 <phrase role="identifier">result</phrase> <phrase role="special">=</phrase> <phrase role="identifier">wait_first_outcome</phrase><phrase role="special">(</phrase>
12488 <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>
12489 <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>
12490 <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>
12491 <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>
12492 <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>
12493 <phrase role="special">}</phrase>
12494 <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>
12495 <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>
12496 <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>
12497 </programlisting>
12498 </para>
12499 </section>
12500 <section id="fiber.when_any.when_any.when_any__produce_first_success">
12501 <title><link linkend="fiber.when_any.when_any.when_any__produce_first_success">when_any,
12502 produce first success</link></title>
12503 <para>
12504 One scenario for <quote>when_any</quote> functionality is when we're redundantly
12505 contacting some number of possibly-unreliable web services. Not only might
12506 they be slow &mdash; any one of them might produce a failure rather than the desired
12507 result.
12508 </para>
12509 <para>
12510 In such a case, <link linkend="wait_first_outcome"><code><phrase role="identifier">wait_first_outcome</phrase><phrase
12511 role="special">()</phrase></code></link> isn't the right approach. If one
12512 of the services produces an error quickly, while another follows up with
12513 a real answer, we don't want to prefer the error just because it arrived
12514 first!
12515 </para>
12516 <para>
12517 Given the <code><phrase role="identifier">unbounded_channel</phrase><phrase
12518 role="special">&lt;</phrase> <phrase role="identifier">future</phrase><phrase
12519 role="special">&lt;</phrase> <phrase role="identifier">T</phrase> <phrase
12520 role="special">&gt;</phrase> <phrase role="special">&gt;</phrase></code>
12521 we already constructed for <code><phrase role="identifier">wait_first_outcome</phrase><phrase
12522 role="special">()</phrase></code>, though, we can readily recast the interface
12523 function to deliver the first <emphasis>successful</emphasis> result.
12524 </para>
12525 <para>
12526 That does beg the question: what if <emphasis>all</emphasis> the task functions
12527 throw an exception? In that case we'd probably better know about it.
12528 </para>
12529 <para>
12530 <anchor id="exception_list"/>The <ulink url="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4407.html#parallel.exceptions.synopsis">C++
12531 Parallelism Draft Technical Specification</ulink> proposes a <code><phrase
12532 role="identifier">std</phrase><phrase role="special">::</phrase><phrase
12533 role="identifier">exception_list</phrase></code> exception capable of delivering
12534 a collection of <code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase
12535 role="identifier">exception_ptr</phrase></code>s. Until that becomes universally
12536 available, let's fake up an <code><phrase role="identifier">exception_list</phrase></code>
12537 of our own:
12538 </para>
12539 <para>
12540 <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>
12541 <phrase role="keyword">public</phrase><phrase role="special">:</phrase>
12542 <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>
12543 <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>
12544 <phrase role="special">}</phrase>
12545
12546 <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>
12547
12548 <phrase role="comment">// N4407 proposed std::exception_list API</phrase>
12549 <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>
12550
12551 <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>
12552 <phrase role="keyword">return</phrase> <phrase role="identifier">bundle_</phrase><phrase role="special">.</phrase><phrase role="identifier">size</phrase><phrase role="special">();</phrase>
12553 <phrase role="special">}</phrase>
12554
12555 <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>
12556 <phrase role="keyword">return</phrase> <phrase role="identifier">bundle_</phrase><phrase role="special">.</phrase><phrase role="identifier">begin</phrase><phrase role="special">();</phrase>
12557 <phrase role="special">}</phrase>
12558
12559 <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>
12560 <phrase role="keyword">return</phrase> <phrase role="identifier">bundle_</phrase><phrase role="special">.</phrase><phrase role="identifier">end</phrase><phrase role="special">();</phrase>
12561 <phrase role="special">}</phrase>
12562
12563 <phrase role="comment">// extension to populate</phrase>
12564 <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>
12565 <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>
12566 <phrase role="special">}</phrase>
12567
12568 <phrase role="keyword">private</phrase><phrase role="special">:</phrase>
12569 <phrase role="identifier">bundle_t</phrase> <phrase role="identifier">bundle_</phrase><phrase role="special">;</phrase>
12570 <phrase role="special">};</phrase>
12571 </programlisting>
12572 </para>
12573 <para>
12574 Now we can build <code><phrase role="identifier">wait_first_success</phrase><phrase
12575 role="special">()</phrase></code>, using <link linkend="wait_first_outcome_impl"><code><phrase
12576 role="identifier">wait_first_outcome_impl</phrase><phrase role="special">()</phrase></code></link>.
12577 </para>
12578 <para>
12579 Instead of retrieving only the first <code><phrase role="identifier">future</phrase><phrase
12580 role="special">&lt;&gt;</phrase></code> from the channel, we must now loop
12581 over <code><phrase role="identifier">future</phrase><phrase role="special">&lt;&gt;</phrase></code>
12582 items. Of course we must limit that iteration! If we launch only <code><phrase
12583 role="identifier">count</phrase></code> producer fibers, the <code><phrase
12584 role="special">(</phrase><phrase role="identifier">count</phrase><phrase
12585 role="special">+</phrase><phrase role="number">1</phrase><phrase role="special">)</phrase></code><superscript>st</superscript>
12586 <link linkend="unbounded_channel_pop"><code>unbounded_channel::pop()</code></link> call
12587 would block forever.
12588 </para>
12589 <para>
12590 Given a ready <code><phrase role="identifier">future</phrase><phrase role="special">&lt;&gt;</phrase></code>,
12591 we can distinguish failure by calling <link linkend="future_get_exception_ptr"><code>future::get_exception_ptr()</code></link>.
12592 If the <code><phrase role="identifier">future</phrase><phrase role="special">&lt;&gt;</phrase></code>
12593 in fact contains a result rather than an exception, <code><phrase role="identifier">get_exception_ptr</phrase><phrase
12594 role="special">()</phrase></code> returns <code><phrase role="keyword">nullptr</phrase></code>.
12595 In that case, we can confidently call <link linkend="future_get"><code>future::get()</code></link> to return
12596 that result to our caller.
12597 </para>
12598 <para>
12599 If the <code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase
12600 role="identifier">exception_ptr</phrase></code> is <emphasis>not</emphasis>
12601 <code><phrase role="keyword">nullptr</phrase></code>, though, we collect
12602 it into our pending <code><phrase role="identifier">exception_list</phrase></code>
12603 and loop back for the next <code><phrase role="identifier">future</phrase><phrase
12604 role="special">&lt;&gt;</phrase></code> from the channel.
12605 </para>
12606 <para>
12607 If we fall out of the loop &mdash; if every single task fiber threw an exception
12608 &mdash; we throw the <code><phrase role="identifier">exception_list</phrase></code>
12609 exception into which we've been collecting those <code><phrase role="identifier">std</phrase><phrase
12610 role="special">::</phrase><phrase role="identifier">exception_ptr</phrase></code>s.
12611 </para>
12612 <para>
12613 <anchor id="wait_first_success"/>
12614 <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>
12615 <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>
12616 <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>
12617 <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>
12618 <phrase role="comment">// In this case, the value we pass through the channel is actually a</phrase>
12619 <phrase role="comment">// future -- which is already ready. future can carry either a value or an</phrase>
12620 <phrase role="comment">// exception.</phrase>
12621 <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>
12622 <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>
12623 <phrase role="keyword">typedef</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">unbounded_channel</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">future_t</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">channel_t</phrase><phrase role="special">;</phrase>
12624 <phrase role="keyword">auto</phrase> <phrase role="identifier">channelp</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">make_shared</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">channel_t</phrase> <phrase role="special">&gt;()</phrase> <phrase role="special">);</phrase>
12625 <phrase role="comment">// launch all the relevant fibers</phrase>
12626 <phrase role="identifier">wait_first_outcome_impl</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">return_t</phrase> <phrase role="special">&gt;(</phrase> <phrase role="identifier">channelp</phrase><phrase role="special">,</phrase>
12627 <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>
12628 <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>
12629 <phrase role="comment">// instantiate exception_list, just in case</phrase>
12630 <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>
12631 <phrase role="comment">// retrieve up to 'count' results -- but stop there!</phrase>
12632 <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>
12633 <phrase role="comment">// retrieve the next future</phrase>
12634 <phrase role="identifier">future_t</phrase> <phrase role="identifier">future</phrase><phrase role="special">(</phrase> <phrase role="identifier">channelp</phrase><phrase role="special">-&gt;</phrase><phrase role="identifier">value_pop</phrase><phrase role="special">()</phrase> <phrase role="special">);</phrase>
12635 <phrase role="comment">// retrieve exception_ptr if any</phrase>
12636 <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>
12637 <phrase role="comment">// if no error, then yay, return value</phrase>
12638 <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>
12639 <phrase role="comment">// close the channel: no subsequent push() has to succeed</phrase>
12640 <phrase role="identifier">channelp</phrase><phrase role="special">-&gt;</phrase><phrase role="identifier">close</phrase><phrase role="special">();</phrase>
12641 <phrase role="comment">// show caller the value we got</phrase>
12642 <phrase role="keyword">return</phrase> <phrase role="identifier">future</phrase><phrase role="special">.</phrase><phrase role="identifier">get</phrase><phrase role="special">();</phrase>
12643 <phrase role="special">}</phrase>
12644
12645 <phrase role="comment">// error is non-null: collect</phrase>
12646 <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>
12647 <phrase role="special">}</phrase>
12648 <phrase role="comment">// We only arrive here when every passed function threw an exception.</phrase>
12649 <phrase role="comment">// Throw our collection to inform caller.</phrase>
12650 <phrase role="keyword">throw</phrase> <phrase role="identifier">exceptions</phrase><phrase role="special">;</phrase>
12651 <phrase role="special">}</phrase>
12652 </programlisting>
12653 </para>
12654 <para>
12655 A call might look like this:
12656 </para>
12657 <para>
12658 <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>
12659 <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>
12660 <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>
12661 <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>
12662 <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>
12663 <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>
12664 </programlisting>
12665 </para>
12666 </section>
12667 <section id="fiber.when_any.when_any.when_any__heterogeneous_types">
12668 <title><link linkend="fiber.when_any.when_any.when_any__heterogeneous_types">when_any,
12669 heterogeneous types</link></title>
12670 <para>
12671 We would be remiss to ignore the case in which the various task functions
12672 have distinct return types. That means that the value returned by the first
12673 of them might have any one of those types. We can express that with <ulink
12674 url="http://www.boost.org/doc/libs/release/doc/html/variant.html">Boost.Variant</ulink>.
12675 </para>
12676 <para>
12677 To keep the example simple, we'll revert to pretending that none of them
12678 can throw an exception. That makes <code><phrase role="identifier">wait_first_value_het</phrase><phrase
12679 role="special">()</phrase></code> strongly resemble <link linkend="wait_first_value"><code><phrase
12680 role="identifier">wait_first_value</phrase><phrase role="special">()</phrase></code></link>.
12681 We can actually reuse <link linkend="wait_first_value_impl"><code><phrase
12682 role="identifier">wait_first_value_impl</phrase><phrase role="special">()</phrase></code></link>,
12683 merely passing <code><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase
12684 role="identifier">variant</phrase><phrase role="special">&lt;</phrase><phrase
12685 role="identifier">T0</phrase><phrase role="special">,</phrase> <phrase
12686 role="identifier">T1</phrase><phrase role="special">,</phrase> <phrase
12687 role="special">...&gt;</phrase></code> as the channel's value type rather
12688 than the common <code><phrase role="identifier">T</phrase></code>!
12689 </para>
12690 <para>
12691 Naturally this could be extended to use <link linkend="wait_first_success"><code><phrase
12692 role="identifier">wait_first_success</phrase><phrase role="special">()</phrase></code></link>
12693 semantics instead.
12694 </para>
12695 <para>
12696 <programlisting><phrase role="comment">// No need to break out the first Fn for interface function: let the compiler</phrase>
12697 <phrase role="comment">// complain if empty.</phrase>
12698 <phrase role="comment">// Our functions have different return types, and we might have to return any</phrase>
12699 <phrase role="comment">// of them. Use a variant, expanding std::result_of&lt;Fn()&gt;::type for each Fn in</phrase>
12700 <phrase role="comment">// parameter pack.</phrase>
12701 <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>
12702 <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>
12703 <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>
12704 <phrase role="comment">// Use unbounded_channel&lt;boost::variant&lt;T1, T2, ...&gt;&gt;; see remarks above.</phrase>
12705 <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>
12706 <phrase role="keyword">typedef</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">unbounded_channel</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">return_t</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">channel_t</phrase><phrase role="special">;</phrase>
12707 <phrase role="keyword">auto</phrase> <phrase role="identifier">channelp</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">make_shared</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">channel_t</phrase> <phrase role="special">&gt;()</phrase> <phrase role="special">);</phrase>
12708 <phrase role="comment">// launch all the relevant fibers</phrase>
12709 <phrase role="identifier">wait_first_value_impl</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">return_t</phrase> <phrase role="special">&gt;(</phrase> <phrase role="identifier">channelp</phrase><phrase role="special">,</phrase>
12710 <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>
12711 <phrase role="comment">// retrieve the first value</phrase>
12712 <phrase role="identifier">return_t</phrase> <phrase role="identifier">value</phrase><phrase role="special">(</phrase> <phrase role="identifier">channelp</phrase><phrase role="special">-&gt;</phrase><phrase role="identifier">value_pop</phrase><phrase role="special">()</phrase> <phrase role="special">);</phrase>
12713 <phrase role="comment">// close the channel: no subsequent push() has to succeed</phrase>
12714 <phrase role="identifier">channelp</phrase><phrase role="special">-&gt;</phrase><phrase role="identifier">close</phrase><phrase role="special">();</phrase>
12715 <phrase role="keyword">return</phrase> <phrase role="identifier">value</phrase><phrase role="special">;</phrase>
12716 <phrase role="special">}</phrase>
12717 </programlisting>
12718 </para>
12719 <para>
12720 It might be called like this:
12721 </para>
12722 <para>
12723 <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>
12724 <phrase role="identifier">wait_first_value_het</phrase><phrase role="special">(</phrase>
12725 <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>
12726 <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>
12727 <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>
12728 <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>
12729 <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>
12730 </programlisting>
12731 </para>
12732 </section>
12733 <section id="fiber.when_any.when_any.when_any__a_dubious_alternative">
12734 <title><link linkend="fiber.when_any.when_any.when_any__a_dubious_alternative">when_any,
12735 a dubious alternative</link></title>
12736 <para>
12737 Certain topics in C++ can arouse strong passions, and exceptions are no
12738 exception. We cannot resist mentioning &mdash; for purely informational purposes
12739 &mdash; that when you need only the <emphasis>first</emphasis> result from some
12740 number of concurrently-running fibers, it would be possible to pass a
12741 <literal>shared_ptr&lt;<link linkend="class_promise"><code>promise&lt;&gt;</code></link>&gt;</literal> to the
12742 participating fibers, then cause the initiating fiber to call <link linkend="future_get"><code>future::get()</code></link> on
12743 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
12744 that shared <code><phrase role="identifier">promise</phrase></code> will
12745 succeed; subsequent <code><phrase role="identifier">set_value</phrase><phrase
12746 role="special">()</phrase></code> calls on the same <code><phrase role="identifier">promise</phrase></code>
12747 instance will throw <code><phrase role="identifier">future_error</phrase></code>.
12748 </para>
12749 <para>
12750 Use this information at your own discretion. Beware the dark side.
12751 </para>
12752 </section>
12753 </section>
12754 <section id="fiber.when_any.when_all_functionality">
12755 <title><link linkend="fiber.when_any.when_all_functionality">when_all functionality</link></title>
12756 <section id="fiber.when_any.when_all_functionality.when_all__simple_completion">
12757 <title><link linkend="fiber.when_any.when_all_functionality.when_all__simple_completion">when_all,
12758 simple completion</link></title>
12759 <para>
12760 For the case in which we must wait for <emphasis>all</emphasis> task functions
12761 to complete &mdash; but we don't need results (or expect exceptions) from any of
12762 them &mdash; we can write <code><phrase role="identifier">wait_all_simple</phrase><phrase
12763 role="special">()</phrase></code> that looks remarkably like <link linkend="wait_first_simple"><code><phrase
12764 role="identifier">wait_first_simple</phrase><phrase role="special">()</phrase></code></link>.
12765 The difference is that instead of our <link linkend="wait_done"><code><phrase
12766 role="identifier">Done</phrase></code></link> class, we instantiate a <link linkend="class_barrier"><code>barrier</code></link> and
12767 call its <link linkend="barrier_wait"><code>barrier::wait()</code></link>.
12768 </para>
12769 <para>
12770 We initialize the <code><phrase role="identifier">barrier</phrase></code>
12771 with <code><phrase role="special">(</phrase><phrase role="identifier">count</phrase><phrase
12772 role="special">+</phrase><phrase role="number">1</phrase><phrase role="special">)</phrase></code>
12773 because we are launching <code><phrase role="identifier">count</phrase></code>
12774 fibers, plus the <code><phrase role="identifier">wait</phrase><phrase role="special">()</phrase></code>
12775 call within <code><phrase role="identifier">wait_all_simple</phrase><phrase
12776 role="special">()</phrase></code> itself.
12777 </para>
12778 <para>
12779 <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>
12780 <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>
12781 <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>
12782 <phrase role="comment">// Initialize a barrier(count+1) because we'll immediately wait on it. We</phrase>
12783 <phrase role="comment">// don't want to wake up until 'count' more fibers wait on it. Even though</phrase>
12784 <phrase role="comment">// we'll stick around until the last of them completes, use shared_ptr</phrase>
12785 <phrase role="comment">// anyway because it's easier to be confident about lifespan issues.</phrase>
12786 <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>
12787 <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>
12788 <phrase role="identifier">barrier</phrase><phrase role="special">-&gt;</phrase><phrase role="identifier">wait</phrase><phrase role="special">();</phrase>
12789 <phrase role="special">}</phrase>
12790 </programlisting>
12791 </para>
12792 <para>
12793 As stated above, the only difference between <code><phrase role="identifier">wait_all_simple_impl</phrase><phrase
12794 role="special">()</phrase></code> and <link linkend="wait_first_simple_impl"><code><phrase
12795 role="identifier">wait_first_simple_impl</phrase><phrase role="special">()</phrase></code></link>
12796 is that the former calls <code><phrase role="identifier">barrier</phrase><phrase
12797 role="special">::</phrase><phrase role="identifier">wait</phrase><phrase
12798 role="special">()</phrase></code> rather than <code><phrase role="identifier">Done</phrase><phrase
12799 role="special">::</phrase><phrase role="identifier">notify</phrase><phrase
12800 role="special">()</phrase></code>:
12801 </para>
12802 <para>
12803 <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>
12804 <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>
12805 <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>
12806 <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>
12807 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">bind</phrase><phrase role="special">(</phrase>
12808 <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>
12809 <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>
12810 <phrase role="identifier">function</phrase><phrase role="special">();</phrase>
12811 <phrase role="identifier">barrier</phrase><phrase role="special">-&gt;</phrase><phrase role="identifier">wait</phrase><phrase role="special">();</phrase>
12812 <phrase role="special">},</phrase>
12813 <phrase role="identifier">barrier</phrase><phrase role="special">,</phrase>
12814 <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>
12815 <phrase role="special">)).</phrase><phrase role="identifier">detach</phrase><phrase role="special">();</phrase>
12816 <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>
12817 <phrase role="special">}</phrase>
12818 </programlisting>
12819 </para>
12820 <para>
12821 You might call it like this:
12822 </para>
12823 <para>
12824 <programlisting><phrase role="identifier">wait_all_simple</phrase><phrase role="special">(</phrase>
12825 <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>
12826 <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>
12827 <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>
12828 </programlisting>
12829 </para>
12830 <para>
12831 Control will not return from the <code><phrase role="identifier">wait_all_simple</phrase><phrase
12832 role="special">()</phrase></code> call until the last of its task functions
12833 has completed.
12834 </para>
12835 </section>
12836 <section id="fiber.when_any.when_all_functionality.when_all__return_values">
12837 <title><link linkend="fiber.when_any.when_all_functionality.when_all__return_values">when_all,
12838 return values</link></title>
12839 <para>
12840 As soon as we want to collect return values from all the task functions,
12841 we can see right away how to reuse <link linkend="wait_first_value"><code><phrase
12842 role="identifier">wait_first_value</phrase><phrase role="special">()</phrase></code></link>'s
12843 channel&lt;T&gt; for the purpose. All we have to do is avoid closing it
12844 after the first value!
12845 </para>
12846 <para>
12847 But in fact, collecting multiple values raises an interesting question:
12848 do we <emphasis>really</emphasis> want to wait until the slowest of them
12849 has arrived? Wouldn't we rather process each result as soon as it becomes
12850 available?
12851 </para>
12852 <para>
12853 Fortunately we can present both APIs. Let's define <code><phrase role="identifier">wait_all_values_source</phrase><phrase
12854 role="special">()</phrase></code> to return <code><phrase role="identifier">shared_ptr</phrase><phrase
12855 role="special">&lt;</phrase><phrase role="identifier">unbounded_channel</phrase><phrase
12856 role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase
12857 role="special">&gt;&gt;</phrase></code>.<footnote id="fiber.when_any.when_all_functionality.when_all__return_values.f0">
12858 <para>
12859 We could have used either <link linkend="class_bounded_channel"><code>bounded_channel&lt;&gt;</code></link> or
12860 <link linkend="class_unbounded_channel"><code>unbounded_channel&lt;&gt;</code></link>. We chose <code><phrase
12861 role="identifier">unbounded_channel</phrase><phrase role="special">&lt;&gt;</phrase></code>
12862 on the assumption that its simpler semantics imply a cheaper implementation.
12863 </para>
12864 </footnote>
12865 </para>
12866 <para>
12867 <anchor id="wait_all_values"/>Given <code><phrase role="identifier">wait_all_values_source</phrase><phrase
12868 role="special">()</phrase></code>, it's straightforward to implement <code><phrase
12869 role="identifier">wait_all_values</phrase><phrase role="special">()</phrase></code>:
12870 </para>
12871 <para>
12872 <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>
12873 <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>
12874 <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>
12875 <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>
12876 <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>
12877 <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>
12878 <phrase role="identifier">vector_t</phrase> <phrase role="identifier">results</phrase><phrase role="special">;</phrase>
12879 <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>
12880
12881 <phrase role="comment">// get channel</phrase>
12882 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">shared_ptr</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">unbounded_channel</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">return_t</phrase> <phrase role="special">&gt;</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">channel</phrase> <phrase role="special">=</phrase>
12883 <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>
12884 <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>
12885 <phrase role="comment">// fill results vector</phrase>
12886 <phrase role="identifier">return_t</phrase> <phrase role="identifier">value</phrase><phrase role="special">;</phrase>
12887 <phrase role="keyword">while</phrase> <phrase role="special">(</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">channel_op_status</phrase><phrase role="special">::</phrase><phrase role="identifier">success</phrase> <phrase role="special">==</phrase> <phrase role="identifier">channel</phrase><phrase role="special">-&gt;</phrase><phrase role="identifier">pop</phrase><phrase role="special">(</phrase><phrase role="identifier">value</phrase><phrase role="special">)</phrase> <phrase role="special">)</phrase> <phrase role="special">{</phrase>
12888 <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>
12889 <phrase role="special">}</phrase>
12890 <phrase role="comment">// return vector to caller</phrase>
12891 <phrase role="keyword">return</phrase> <phrase role="identifier">results</phrase><phrase role="special">;</phrase>
12892 <phrase role="special">}</phrase>
12893 </programlisting>
12894 </para>
12895 <para>
12896 It might be called like this:
12897 </para>
12898 <para>
12899 <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>
12900 <phrase role="identifier">wait_all_values</phrase><phrase role="special">(</phrase>
12901 <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>
12902 <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>
12903 <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>
12904 </programlisting>
12905 </para>
12906 <para>
12907 As you can see from the loop in <code><phrase role="identifier">wait_all_values</phrase><phrase
12908 role="special">()</phrase></code>, instead of requiring its caller to count
12909 values, we define <code><phrase role="identifier">wait_all_values_source</phrase><phrase
12910 role="special">()</phrase></code> to <link linkend="unbounded_channel_close"><code>unbounded_channel::close()</code></link> the
12911 channel when done. But how do we do that? Each producer fiber is independent.
12912 It has no idea whether it is the last one to <link linkend="unbounded_channel_push"><code>unbounded_channel::push()</code></link> a
12913 value.
12914 </para>
12915 <para>
12916 <anchor id="wait_nchannel"/>We can address that problem with a counting
12917 façade for the <code><phrase role="identifier">unbounded_channel</phrase><phrase
12918 role="special">&lt;&gt;</phrase></code>. In fact, our façade need only
12919 support the producer end of the channel.
12920 </para>
12921 <para>
12922 <programlisting><phrase role="comment">// Introduce a channel facade that closes the channel once a specific number</phrase>
12923 <phrase role="comment">// of items has been pushed. This allows an arbitrary consumer to read until</phrase>
12924 <phrase role="comment">// 'closed' without itself having to count items.</phrase>
12925 <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>
12926 <phrase role="keyword">class</phrase> <phrase role="identifier">nchannel</phrase> <phrase role="special">{</phrase>
12927 <phrase role="keyword">public</phrase><phrase role="special">:</phrase>
12928 <phrase role="identifier">nchannel</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">shared_ptr</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">unbounded_channel</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">T</phrase> <phrase role="special">&gt;</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">cp</phrase><phrase role="special">,</phrase>
12929 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">lm</phrase><phrase role="special">):</phrase>
12930 <phrase role="identifier">channel_</phrase><phrase role="special">(</phrase> <phrase role="identifier">cp</phrase><phrase role="special">),</phrase>
12931 <phrase role="identifier">limit_</phrase><phrase role="special">(</phrase> <phrase role="identifier">lm</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
12932 <phrase role="identifier">assert</phrase><phrase role="special">(</phrase><phrase role="identifier">channel_</phrase><phrase role="special">);</phrase>
12933 <phrase role="keyword">if</phrase> <phrase role="special">(</phrase> <phrase role="number">0</phrase> <phrase role="special">==</phrase> <phrase role="identifier">limit_</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
12934 <phrase role="identifier">channel_</phrase><phrase role="special">-&gt;</phrase><phrase role="identifier">close</phrase><phrase role="special">();</phrase>
12935 <phrase role="special">}</phrase>
12936 <phrase role="special">}</phrase>
12937
12938 <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">channel_op_status</phrase> <phrase role="identifier">push</phrase><phrase role="special">(</phrase> <phrase role="identifier">T</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="identifier">va</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
12939 <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">channel_op_status</phrase> <phrase role="identifier">ok</phrase> <phrase role="special">=</phrase>
12940 <phrase role="identifier">channel_</phrase><phrase role="special">-&gt;</phrase><phrase role="identifier">push</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">forward</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">T</phrase> <phrase role="special">&gt;(</phrase> <phrase role="identifier">va</phrase><phrase role="special">)</phrase> <phrase role="special">);</phrase>
12941 <phrase role="keyword">if</phrase> <phrase role="special">(</phrase> <phrase role="identifier">ok</phrase> <phrase role="special">==</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">channel_op_status</phrase><phrase role="special">::</phrase><phrase role="identifier">success</phrase> <phrase role="special">&amp;&amp;</phrase>
12942 <phrase role="special">--</phrase><phrase role="identifier">limit_</phrase> <phrase role="special">==</phrase> <phrase role="number">0</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
12943 <phrase role="comment">// after the 'limit_'th successful push, close the channel</phrase>
12944 <phrase role="identifier">channel_</phrase><phrase role="special">-&gt;</phrase><phrase role="identifier">close</phrase><phrase role="special">();</phrase>
12945 <phrase role="special">}</phrase>
12946 <phrase role="keyword">return</phrase> <phrase role="identifier">ok</phrase><phrase role="special">;</phrase>
12947 <phrase role="special">}</phrase>
12948
12949 <phrase role="keyword">private</phrase><phrase role="special">:</phrase>
12950 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">shared_ptr</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">unbounded_channel</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">T</phrase> <phrase role="special">&gt;</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">channel_</phrase><phrase role="special">;</phrase>
12951 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">limit_</phrase><phrase role="special">;</phrase>
12952 <phrase role="special">};</phrase>
12953 </programlisting>
12954 </para>
12955 <para>
12956 <anchor id="wait_all_values_source"/>Armed with <code><phrase role="identifier">nchannel</phrase><phrase
12957 role="special">&lt;&gt;</phrase></code>, we can implement <code><phrase
12958 role="identifier">wait_all_values_source</phrase><phrase role="special">()</phrase></code>.
12959 It starts just like <link linkend="wait_first_value"><code><phrase role="identifier">wait_first_value</phrase><phrase
12960 role="special">()</phrase></code></link>. The difference is that we wrap
12961 the <code><phrase role="identifier">unbounded_channel</phrase><phrase role="special">&lt;</phrase><phrase
12962 role="identifier">T</phrase><phrase role="special">&gt;</phrase></code>
12963 with an <code><phrase role="identifier">nchannel</phrase><phrase role="special">&lt;</phrase><phrase
12964 role="identifier">T</phrase><phrase role="special">&gt;</phrase></code>
12965 to pass to the producer fibers.
12966 </para>
12967 <para>
12968 Then, of course, instead of popping the first value, closing the channel
12969 and returning it, we simply return the <code><phrase role="identifier">shared_ptr</phrase><phrase
12970 role="special">&lt;</phrase><phrase role="identifier">unbounded_channel</phrase><phrase
12971 role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase
12972 role="special">&gt;&gt;</phrase></code>.
12973 </para>
12974 <para>
12975 <programlisting><phrase role="comment">// Return a shared_ptr&lt;unbounded_channel&lt;T&gt;&gt; from which the caller can</phrase>
12976 <phrase role="comment">// retrieve each new result as it arrives, until 'closed'.</phrase>
12977 <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>
12978 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">shared_ptr</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">unbounded_channel</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">result_of</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Fn</phrase><phrase role="special">()</phrase> <phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase> <phrase role="special">&gt;</phrase> <phrase role="special">&gt;</phrase>
12979 <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>
12980 <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>
12981 <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>
12982 <phrase role="keyword">typedef</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">unbounded_channel</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">return_t</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">channel_t</phrase><phrase role="special">;</phrase>
12983 <phrase role="comment">// make the channel</phrase>
12984 <phrase role="keyword">auto</phrase> <phrase role="identifier">channelp</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">make_shared</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">channel_t</phrase> <phrase role="special">&gt;()</phrase> <phrase role="special">);</phrase>
12985 <phrase role="comment">// and make an nchannel facade to close it after 'count' items</phrase>
12986 <phrase role="keyword">auto</phrase> <phrase role="identifier">ncp</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">make_shared</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">nchannel</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">return_t</phrase> <phrase role="special">&gt;</phrase> <phrase role="special">&gt;(</phrase> <phrase role="identifier">channelp</phrase><phrase role="special">,</phrase> <phrase role="identifier">count</phrase><phrase role="special">)</phrase> <phrase role="special">);</phrase>
12987 <phrase role="comment">// pass that nchannel facade to all the relevant fibers</phrase>
12988 <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>
12989 <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>
12990 <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>
12991 <phrase role="comment">// then return the channel for consumer</phrase>
12992 <phrase role="keyword">return</phrase> <phrase role="identifier">channelp</phrase><phrase role="special">;</phrase>
12993 <phrase role="special">}</phrase>
12994 </programlisting>
12995 </para>
12996 <para>
12997 For example:
12998 </para>
12999 <para>
13000 <programlisting><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">shared_ptr</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">unbounded_channel</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="special">&gt;</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">channel</phrase> <phrase role="special">=</phrase>
13001 <phrase role="identifier">wait_all_values_source</phrase><phrase role="special">(</phrase>
13002 <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>
13003 <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>
13004 <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>
13005 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="identifier">value</phrase><phrase role="special">;</phrase>
13006 <phrase role="keyword">while</phrase> <phrase role="special">(</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">channel_op_status</phrase><phrase role="special">::</phrase><phrase role="identifier">success</phrase> <phrase role="special">==</phrase> <phrase role="identifier">channel</phrase><phrase role="special">-&gt;</phrase><phrase role="identifier">pop</phrase><phrase role="special">(</phrase><phrase role="identifier">value</phrase><phrase role="special">)</phrase> <phrase role="special">)</phrase> <phrase role="special">{</phrase>
13007 <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>
13008 <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>
13009 <phrase role="special">}</phrase>
13010 </programlisting>
13011 </para>
13012 <para>
13013 <anchor id="wait_all_values_impl"/><code><phrase role="identifier">wait_all_values_impl</phrase><phrase
13014 role="special">()</phrase></code> really is just like <link linkend="wait_first_value_impl"><code><phrase
13015 role="identifier">wait_first_value_impl</phrase><phrase role="special">()</phrase></code></link>
13016 except for the use of <code><phrase role="identifier">nchannel</phrase><phrase
13017 role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase
13018 role="special">&gt;</phrase></code> rather than <code><phrase role="identifier">unbounded_channel</phrase><phrase
13019 role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase
13020 role="special">&gt;</phrase></code>:
13021 </para>
13022 <para>
13023 <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>
13024 <phrase role="keyword">void</phrase> <phrase role="identifier">wait_all_values_impl</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">shared_ptr</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">nchannel</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">T</phrase> <phrase role="special">&gt;</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">channel</phrase><phrase role="special">,</phrase>
13025 <phrase role="identifier">Fn</phrase> <phrase role="special">&amp;&amp;</phrase> <phrase role="identifier">function</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
13026 <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">fiber</phrase><phrase role="special">(</phrase> <phrase role="special">[</phrase><phrase role="identifier">channel</phrase><phrase role="special">,</phrase> <phrase role="identifier">function</phrase><phrase role="special">](){</phrase>
13027 <phrase role="identifier">channel</phrase><phrase role="special">-&gt;</phrase><phrase role="identifier">push</phrase><phrase role="special">(</phrase><phrase role="identifier">function</phrase><phrase role="special">());</phrase>
13028 <phrase role="special">}).</phrase><phrase role="identifier">detach</phrase><phrase role="special">();</phrase>
13029 <phrase role="special">}</phrase>
13030 </programlisting>
13031 </para>
13032 </section>
13033 <section id="fiber.when_any.when_all_functionality.when_all_until_first_exception">
13034 <title><link linkend="fiber.when_any.when_all_functionality.when_all_until_first_exception">when_all
13035 until first exception</link></title>
13036 <para>
13037 Naturally, just as with <link linkend="wait_first_outcome"><code><phrase
13038 role="identifier">wait_first_outcome</phrase><phrase role="special">()</phrase></code></link>,
13039 we can elaborate <link linkend="wait_all_values"><code><phrase role="identifier">wait_all_values</phrase><phrase
13040 role="special">()</phrase></code></link> and <link linkend="wait_all_values_source"><code><phrase
13041 role="identifier">wait_all_values_source</phrase><phrase role="special">()</phrase></code></link>
13042 by passing <code><phrase role="identifier">future</phrase><phrase role="special">&lt;</phrase>
13043 <phrase role="identifier">T</phrase> <phrase role="special">&gt;</phrase></code>
13044 instead of plain <code><phrase role="identifier">T</phrase></code>.
13045 </para>
13046 <para>
13047 <anchor id="wait_all_until_error"/><code><phrase role="identifier">wait_all_until_error</phrase><phrase
13048 role="special">()</phrase></code> pops that <code><phrase role="identifier">future</phrase><phrase
13049 role="special">&lt;</phrase> <phrase role="identifier">T</phrase> <phrase
13050 role="special">&gt;</phrase></code> and calls its <link linkend="future_get"><code>future::get()</code></link>:
13051 </para>
13052 <para>
13053 <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>
13054 <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>
13055 <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>
13056 <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>
13057 <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>
13058 <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>
13059 <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>
13060 <phrase role="identifier">vector_t</phrase> <phrase role="identifier">results</phrase><phrase role="special">;</phrase>
13061 <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>
13062
13063 <phrase role="comment">// get channel</phrase>
13064 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">shared_ptr</phrase><phrase role="special">&lt;</phrase>
13065 <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">unbounded_channel</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">future_t</phrase> <phrase role="special">&gt;</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">channel</phrase><phrase role="special">(</phrase>
13066 <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>
13067 <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>
13068 <phrase role="comment">// fill results vector</phrase>
13069 <phrase role="identifier">future_t</phrase> <phrase role="identifier">future</phrase><phrase role="special">;</phrase>
13070 <phrase role="keyword">while</phrase> <phrase role="special">(</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">channel_op_status</phrase><phrase role="special">::</phrase><phrase role="identifier">success</phrase> <phrase role="special">==</phrase> <phrase role="identifier">channel</phrase><phrase role="special">-&gt;</phrase><phrase role="identifier">pop</phrase><phrase role="special">(</phrase> <phrase role="identifier">future</phrase><phrase role="special">)</phrase> <phrase role="special">)</phrase> <phrase role="special">{</phrase>
13071 <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>
13072 <phrase role="special">}</phrase>
13073 <phrase role="comment">// return vector to caller</phrase>
13074 <phrase role="keyword">return</phrase> <phrase role="identifier">results</phrase><phrase role="special">;</phrase>
13075 <phrase role="special">}</phrase>
13076 </programlisting>
13077 </para>
13078 <para>
13079 For example:
13080 </para>
13081 <para>
13082 <programlisting><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="identifier">thrown</phrase><phrase role="special">;</phrase>
13083 <phrase role="keyword">try</phrase> <phrase role="special">{</phrase>
13084 <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>
13085 <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>
13086 <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>
13087 <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>
13088 <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>
13089 <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>
13090 <phrase role="special">}</phrase>
13091 <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>
13092 <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>
13093 </programlisting>
13094 </para>
13095 <para>
13096 <anchor id="wait_all_until_error_source"/>Naturally this complicates the
13097 API for <code><phrase role="identifier">wait_all_until_error_source</phrase><phrase
13098 role="special">()</phrase></code>. The caller must both retrieve a <code><phrase
13099 role="identifier">future</phrase><phrase role="special">&lt;</phrase>
13100 <phrase role="identifier">T</phrase> <phrase role="special">&gt;</phrase></code>
13101 and call its <code><phrase role="identifier">get</phrase><phrase role="special">()</phrase></code>
13102 method. It would, of course, be possible to return a façade over the consumer
13103 end of the channel that would implicitly perform the <code><phrase role="identifier">get</phrase><phrase
13104 role="special">()</phrase></code> and return a simple <code><phrase role="identifier">T</phrase></code>
13105 (or throw).
13106 </para>
13107 <para>
13108 The implementation is just as you would expect. Notice, however, that we
13109 can reuse <link linkend="wait_first_outcome_impl"><code><phrase role="identifier">wait_first_outcome_impl</phrase><phrase
13110 role="special">()</phrase></code></link>, passing the <code><phrase role="identifier">nchannel</phrase><phrase
13111 role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase
13112 role="special">&gt;</phrase></code> rather than <code><phrase role="identifier">unbounded_channel</phrase><phrase
13113 role="special">&lt;</phrase><phrase role="identifier">T</phrase><phrase
13114 role="special">&gt;</phrase></code>.
13115 </para>
13116 <para>
13117 <programlisting><phrase role="comment">// Return a shared_ptr&lt;unbounded_channel&lt;future&lt;T&gt;&gt;&gt; from which the caller can</phrase>
13118 <phrase role="comment">// get() each new result as it arrives, until 'closed'.</phrase>
13119 <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>
13120 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">shared_ptr</phrase><phrase role="special">&lt;</phrase>
13121 <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">unbounded_channel</phrase><phrase role="special">&lt;</phrase>
13122 <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>
13123 <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>
13124 <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>
13125 <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>
13126 <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>
13127 <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>
13128 <phrase role="keyword">typedef</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">unbounded_channel</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">future_t</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">channel_t</phrase><phrase role="special">;</phrase>
13129 <phrase role="comment">// make the channel</phrase>
13130 <phrase role="keyword">auto</phrase> <phrase role="identifier">channelp</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">make_shared</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">channel_t</phrase> <phrase role="special">&gt;()</phrase> <phrase role="special">);</phrase>
13131 <phrase role="comment">// and make an nchannel facade to close it after 'count' items</phrase>
13132 <phrase role="keyword">auto</phrase> <phrase role="identifier">ncp</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">make_shared</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">nchannel</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">future_t</phrase> <phrase role="special">&gt;</phrase> <phrase role="special">&gt;(</phrase> <phrase role="identifier">channelp</phrase><phrase role="special">,</phrase> <phrase role="identifier">count</phrase><phrase role="special">)</phrase> <phrase role="special">);</phrase>
13133 <phrase role="comment">// pass that nchannel facade to all the relevant fibers</phrase>
13134 <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>
13135 <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>
13136 <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>
13137 <phrase role="comment">// then return the channel for consumer</phrase>
13138 <phrase role="keyword">return</phrase> <phrase role="identifier">channelp</phrase><phrase role="special">;</phrase>
13139 <phrase role="special">}</phrase>
13140 </programlisting>
13141 </para>
13142 <para>
13143 For example:
13144 </para>
13145 <para>
13146 <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>
13147 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">shared_ptr</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">unbounded_channel</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">future_t</phrase> <phrase role="special">&gt;</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">channel</phrase> <phrase role="special">=</phrase>
13148 <phrase role="identifier">wait_all_until_error_source</phrase><phrase role="special">(</phrase>
13149 <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>
13150 <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>
13151 <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>
13152 <phrase role="identifier">future_t</phrase> <phrase role="identifier">future</phrase><phrase role="special">;</phrase>
13153 <phrase role="keyword">while</phrase> <phrase role="special">(</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">channel_op_status</phrase><phrase role="special">::</phrase><phrase role="identifier">success</phrase> <phrase role="special">==</phrase> <phrase role="identifier">channel</phrase><phrase role="special">-&gt;</phrase><phrase role="identifier">pop</phrase><phrase role="special">(</phrase> <phrase role="identifier">future</phrase><phrase role="special">)</phrase> <phrase role="special">)</phrase> <phrase role="special">{</phrase>
13154 <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>
13155 <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>
13156 <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>
13157 <phrase role="special">}</phrase>
13158 </programlisting>
13159 </para>
13160 </section>
13161 <section id="fiber.when_any.when_all_functionality.wait_all__collecting_all_exceptions">
13162 <title><link linkend="fiber.when_any.when_all_functionality.wait_all__collecting_all_exceptions">wait_all,
13163 collecting all exceptions</link></title>
13164 <para>
13165 <anchor id="wait_all_collect_errors"/>Given <link linkend="wait_all_until_error_source"><code><phrase
13166 role="identifier">wait_all_until_error_source</phrase><phrase role="special">()</phrase></code></link>,
13167 it might be more reasonable to make a <code><phrase role="identifier">wait_all_</phrase><phrase
13168 role="special">...()</phrase></code> that collects <emphasis>all</emphasis>
13169 errors instead of presenting only the first:
13170 </para>
13171 <para>
13172 <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>
13173 <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>
13174 <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>
13175 <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>
13176 <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>
13177 <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>
13178 <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>
13179 <phrase role="identifier">vector_t</phrase> <phrase role="identifier">results</phrase><phrase role="special">;</phrase>
13180 <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>
13181 <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>
13182
13183 <phrase role="comment">// get channel</phrase>
13184 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">shared_ptr</phrase><phrase role="special">&lt;</phrase>
13185 <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">unbounded_channel</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">future_t</phrase> <phrase role="special">&gt;</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">channel</phrase><phrase role="special">(</phrase>
13186 <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>
13187 <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>
13188 <phrase role="comment">// fill results and/or exceptions vectors</phrase>
13189 <phrase role="identifier">future_t</phrase> <phrase role="identifier">future</phrase><phrase role="special">;</phrase>
13190 <phrase role="keyword">while</phrase> <phrase role="special">(</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">channel_op_status</phrase><phrase role="special">::</phrase><phrase role="identifier">success</phrase> <phrase role="special">==</phrase> <phrase role="identifier">channel</phrase><phrase role="special">-&gt;</phrase><phrase role="identifier">pop</phrase><phrase role="special">(</phrase> <phrase role="identifier">future</phrase><phrase role="special">)</phrase> <phrase role="special">)</phrase> <phrase role="special">{</phrase>
13191 <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>
13192 <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>
13193 <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>
13194 <phrase role="special">}</phrase> <phrase role="keyword">else</phrase> <phrase role="special">{</phrase>
13195 <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>
13196 <phrase role="special">}</phrase>
13197 <phrase role="special">}</phrase>
13198 <phrase role="comment">// if there were any exceptions, throw</phrase>
13199 <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>
13200 <phrase role="keyword">throw</phrase> <phrase role="identifier">exceptions</phrase><phrase role="special">;</phrase>
13201 <phrase role="special">}</phrase>
13202 <phrase role="comment">// no exceptions: return vector to caller</phrase>
13203 <phrase role="keyword">return</phrase> <phrase role="identifier">results</phrase><phrase role="special">;</phrase>
13204 <phrase role="special">}</phrase>
13205 </programlisting>
13206 </para>
13207 <para>
13208 The implementation is a simple variation on <link linkend="wait_first_success"><code><phrase
13209 role="identifier">wait_first_success</phrase><phrase role="special">()</phrase></code></link>,
13210 using the same <link linkend="exception_list"><code><phrase role="identifier">exception_list</phrase></code></link>
13211 exception class.
13212 </para>
13213 </section>
13214 <section id="fiber.when_any.when_all_functionality.when_all__heterogeneous_types">
13215 <title><link linkend="fiber.when_any.when_all_functionality.when_all__heterogeneous_types">when_all,
13216 heterogeneous types</link></title>
13217 <para>
13218 But what about the case when we must wait for all results of different
13219 types?
13220 </para>
13221 <para>
13222 We can present an API that is frankly quite cool. Consider a sample struct:
13223 </para>
13224 <para>
13225 <programlisting><phrase role="keyword">struct</phrase> <phrase role="identifier">Data</phrase> <phrase role="special">{</phrase>
13226 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="identifier">str</phrase><phrase role="special">;</phrase>
13227 <phrase role="keyword">double</phrase> <phrase role="identifier">inexact</phrase><phrase role="special">;</phrase>
13228 <phrase role="keyword">int</phrase> <phrase role="identifier">exact</phrase><phrase role="special">;</phrase>
13229
13230 <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>
13231 <phrase role="special">...</phrase>
13232 <phrase role="special">};</phrase>
13233 </programlisting>
13234 </para>
13235 <para>
13236 Let's fill its members from task functions all running concurrently:
13237 </para>
13238 <para>
13239 <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>
13240 <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>
13241 <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>
13242 <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>
13243 <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>
13244 </programlisting>
13245 </para>
13246 <para>
13247 Note that for this case, we abandon the notion of capturing the earliest
13248 result first, and so on: we must fill exactly the passed struct in left-to-right
13249 order.
13250 </para>
13251 <para>
13252 That permits a beautifully simple implementation:
13253 </para>
13254 <para>
13255 <programlisting><phrase role="comment">// Explicitly pass Result. This can be any type capable of being initialized</phrase>
13256 <phrase role="comment">// from the results of the passed functions, such as a struct.</phrase>
13257 <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>
13258 <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>
13259 <phrase role="comment">// Run each of the passed functions on a separate fiber, passing all their</phrase>
13260 <phrase role="comment">// futures to helper function for processing.</phrase>
13261 <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>
13262 <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>
13263 <phrase role="special">}</phrase>
13264 </programlisting>
13265 </para>
13266 <para>
13267 <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>
13268 <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>
13269 <phrase role="comment">// Fetch the results from the passed futures into Result's initializer</phrase>
13270 <phrase role="comment">// list. It's true that the get() calls here will block the implicit</phrase>
13271 <phrase role="comment">// iteration over futures -- but that doesn't matter because we won't be</phrase>
13272 <phrase role="comment">// done until the slowest of them finishes anyway. As results are</phrase>
13273 <phrase role="comment">// processed in argument-list order rather than order of completion, the</phrase>
13274 <phrase role="comment">// leftmost get() to throw an exception will cause that exception to</phrase>
13275 <phrase role="comment">// propagate to the caller.</phrase>
13276 <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>
13277 <phrase role="special">}</phrase>
13278 </programlisting>
13279 </para>
13280 <para>
13281 It is tempting to try to implement <code><phrase role="identifier">wait_all_members</phrase><phrase
13282 role="special">()</phrase></code> as a one-liner like this:
13283 </para>
13284 <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>
13285 </programlisting>
13286 <para>
13287 The trouble with this tactic is that it would serialize all the task functions.
13288 The runtime makes a single pass through <code><phrase role="identifier">functions</phrase></code>,
13289 calling <link linkend="fibers_async"><code>fibers::async()</code></link> for each and then immediately calling
13290 <link linkend="future_get"><code>future::get()</code></link> on its returned <code><phrase role="identifier">future</phrase><phrase
13291 role="special">&lt;&gt;</phrase></code>. That blocks the implicit loop.
13292 The above is almost equivalent to writing:
13293 </para>
13294 <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>
13295 </programlisting>
13296 <para>
13297 in which, of course, there is no concurrency at all.
13298 </para>
13299 <para>
13300 Passing the argument pack through a function-call boundary (<code><phrase
13301 role="identifier">wait_all_members_get</phrase><phrase role="special">()</phrase></code>)
13302 forces the runtime to make <emphasis>two</emphasis> passes: one in <code><phrase
13303 role="identifier">wait_all_members</phrase><phrase role="special">()</phrase></code>
13304 to collect the <code><phrase role="identifier">future</phrase><phrase role="special">&lt;&gt;</phrase></code>s
13305 from all the <code><phrase role="identifier">async</phrase><phrase role="special">()</phrase></code>
13306 calls, the second in <code><phrase role="identifier">wait_all_members_get</phrase><phrase
13307 role="special">()</phrase></code> to fetch each of the results.
13308 </para>
13309 <para>
13310 As noted in comments, within the <code><phrase role="identifier">wait_all_members_get</phrase><phrase
13311 role="special">()</phrase></code> parameter pack expansion pass, the blocking
13312 behavior of <code><phrase role="identifier">get</phrase><phrase role="special">()</phrase></code>
13313 becomes irrelevant. Along the way, we will hit the <code><phrase role="identifier">get</phrase><phrase
13314 role="special">()</phrase></code> for the slowest task function; after
13315 that every subsequent <code><phrase role="identifier">get</phrase><phrase
13316 role="special">()</phrase></code> will complete in trivial time.
13317 </para>
13318 <para>
13319 By the way, we could also use this same API to fill a vector or other collection:
13320 </para>
13321 <para>
13322 <programlisting><phrase role="comment">// If we don't care about obtaining results as soon as they arrive, and we</phrase>
13323 <phrase role="comment">// prefer a result vector in passed argument order rather than completion</phrase>
13324 <phrase role="comment">// order, wait_all_members() is another possible implementation of</phrase>
13325 <phrase role="comment">// wait_all_until_error().</phrase>
13326 <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>
13327 <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>
13328 <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>
13329 <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>
13330 <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>
13331 <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>
13332 <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>
13333 <phrase role="special">}</phrase>
13334 <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>
13335 </programlisting>
13336 </para>
13337 </section>
13338 </section>
13339 </section>
13340 <section id="fiber.integration">
13341 <title><anchor id="integration"/><link linkend="fiber.integration">Sharing a
13342 Thread with Another Main Loop</link></title>
13343 <section id="fiber.integration.overview">
13344 <title><link linkend="fiber.integration.overview">Overview</link></title>
13345 <para>
13346 As always with cooperative concurrency, it is important not to let any one
13347 fiber monopolize the processor too long: that could <quote>starve</quote>
13348 other ready fibers. This section discusses a couple of solutions.
13349 </para>
13350 </section>
13351 <section id="fiber.integration.event_driven_program">
13352 <title><link linkend="fiber.integration.event_driven_program">Event-Driven
13353 Program</link></title>
13354 <para>
13355 Consider a classic event-driven program, organized around a main loop that
13356 fetches and dispatches incoming I/O events. You are introducing <emphasis
13357 role="bold">Boost.Fiber</emphasis> because certain asynchronous I/O sequences
13358 are logically sequential, and for those you want to write and maintain code
13359 that looks and acts sequential.
13360 </para>
13361 <para>
13362 You are launching fibers on the application&#8217;s main thread because certain
13363 of their actions will affect its user interface, and the application&#8217;s UI
13364 framework permits UI operations only on the main thread. Or perhaps those
13365 fibers need access to main-thread data, and it would be too expensive in
13366 runtime (or development time) to robustly defend every such data item with
13367 thread synchronization primitives.
13368 </para>
13369 <para>
13370 You must ensure that the application&#8217;s main loop <emphasis>itself</emphasis>
13371 doesn&#8217;t monopolize the processor: that the fibers it launches will get the
13372 CPU cycles they need.
13373 </para>
13374 <para>
13375 The solution is the same as for any fiber that might claim the CPU for an
13376 extended time: introduce calls to <link linkend="this_fiber_yield"><code>this_fiber::yield()</code></link>. The
13377 most straightforward approach is to call <code><phrase role="identifier">yield</phrase><phrase
13378 role="special">()</phrase></code> on every iteration of your existing main
13379 loop. In effect, this unifies the application&#8217;s main loop with <emphasis role="bold">Boost.Fiber</emphasis>&#8217;s
13380 internal main loop. <code><phrase role="identifier">yield</phrase><phrase
13381 role="special">()</phrase></code> allows the fiber manager to run any fibers
13382 that have become ready since the previous iteration of the application&#8217;s main
13383 loop. When these fibers have had a turn, control passes to the thread&#8217;s main
13384 fiber, which returns from <code><phrase role="identifier">yield</phrase><phrase
13385 role="special">()</phrase></code> and resumes the application&#8217;s main loop.
13386 </para>
13387 </section>
13388 <section id="fiber.integration.embedded_main_loop">
13389 <title><anchor id="embedded_main_loop"/><link linkend="fiber.integration.embedded_main_loop">Embedded
13390 Main Loop</link></title>
13391 <para>
13392 More challenging is when the application&#8217;s main loop is embedded in some other
13393 library or framework. Such an application will typically, after performing
13394 all necessary setup, pass control to some form of <code><phrase role="identifier">run</phrase><phrase
13395 role="special">()</phrase></code> function from which control does not return
13396 until application shutdown.
13397 </para>
13398 <para>
13399 A <ulink url="http://www.boost.org/doc/libs/release/libs/asio/index.html">Boost.Asio</ulink>
13400 program might call <ulink url="http://www.boost.org/doc/libs/release/doc/html/boost_asio/reference/io_service/run.html"><code><phrase
13401 role="identifier">io_service</phrase><phrase role="special">::</phrase><phrase
13402 role="identifier">run</phrase><phrase role="special">()</phrase></code></ulink>
13403 in this way.
13404 </para>
13405 <para>
13406 In general, the trick is to arrange to pass control to <link linkend="this_fiber_yield"><code>this_fiber::yield()</code></link> frequently.
13407 You could use an <ulink url="http://www.boost.org/doc/libs/release/doc/html/boost_asio/reference/high_resolution_timer.html">Asio
13408 timer</ulink> for that purpose. You could instantiate the timer, arranging
13409 to call a handler function when the timer expires. The handler function could
13410 call <code><phrase role="identifier">yield</phrase><phrase role="special">()</phrase></code>,
13411 then reset the timer and arrange to wake up again on its next expiration.
13412 </para>
13413 <para>
13414 Since, in this thought experiment, we always pass control to the fiber manager
13415 via <code><phrase role="identifier">yield</phrase><phrase role="special">()</phrase></code>,
13416 the calling fiber is never blocked. Therefore there is always at least one
13417 ready fiber. Therefore the fiber manager never calls <link linkend="algorithm_suspend_until"><code>algorithm::suspend_until()</code></link>.
13418 </para>
13419 <para>
13420 Using <ulink url="http://www.boost.org/doc/libs/release/doc/html/boost_asio/reference/io_service/post.html"><code><phrase
13421 role="identifier">io_service</phrase><phrase role="special">::</phrase><phrase
13422 role="identifier">post</phrase><phrase role="special">()</phrase></code></ulink>
13423 instead of setting a timer for some nonzero interval would be unfriendly
13424 to other threads. When all I/O is pending and all fibers are blocked, the
13425 io_service and the fiber manager would simply spin the CPU, passing control
13426 back and forth to each other. Using a timer allows tuning the responsiveness
13427 of this thread relative to others.
13428 </para>
13429 </section>
13430 <section id="fiber.integration.deeper_dive_into___boost_asio__">
13431 <title><link linkend="fiber.integration.deeper_dive_into___boost_asio__">Deeper
13432 Dive into <ulink url="http://www.boost.org/doc/libs/release/libs/asio/index.html">Boost.Asio</ulink></link></title>
13433 <para>
13434 By now the alert reader is thinking: but surely, with Asio in particular,
13435 we ought to be able to do much better than periodic polling pings!
13436 </para>
13437 <para>
13438 This turns out to be surprisingly tricky. We present a possible approach
13439 in <ulink url="../../examples/asio/round_robin.hpp"><code><phrase role="identifier">examples</phrase><phrase
13440 role="special">/</phrase><phrase role="identifier">asio</phrase><phrase role="special">/</phrase><phrase
13441 role="identifier">round_robin</phrase><phrase role="special">.</phrase><phrase
13442 role="identifier">hpp</phrase></code></ulink>.
13443 </para>
13444 <para>
13445 One consequence of using <ulink url="http://www.boost.org/doc/libs/release/libs/asio/index.html">Boost.Asio</ulink>
13446 is that you must always let Asio suspend the running thread. Since Asio is
13447 aware of pending I/O requests, it can arrange to suspend the thread in such
13448 a way that the OS will wake it on I/O completion. No one else has sufficient
13449 knowledge.
13450 </para>
13451 <para>
13452 So the fiber scheduler must depend on Asio for suspension and resumption.
13453 It requires Asio handler calls to wake it.
13454 </para>
13455 <para>
13456 One dismaying implication is that we cannot support multiple threads calling
13457 <ulink url="http://www.boost.org/doc/libs/release/doc/html/boost_asio/reference/io_service/run.html"><code><phrase
13458 role="identifier">io_service</phrase><phrase role="special">::</phrase><phrase
13459 role="identifier">run</phrase><phrase role="special">()</phrase></code></ulink>
13460 on the same <code><phrase role="identifier">io_service</phrase></code> instance.
13461 The reason is that Asio provides no way to constrain a particular handler
13462 to be called only on a specified thread. A fiber scheduler instance is locked
13463 to a particular thread: that instance cannot manage any other thread&#8217;s fibers.
13464 Yet if we allow multiple threads to call <code><phrase role="identifier">io_service</phrase><phrase
13465 role="special">::</phrase><phrase role="identifier">run</phrase><phrase role="special">()</phrase></code>
13466 on the same <code><phrase role="identifier">io_service</phrase></code> instance,
13467 a fiber scheduler which needs to sleep can have no guarantee that it will
13468 reawaken in a timely manner. It can set an Asio timer, as described above
13469 &mdash; but that timer&#8217;s handler may well execute on a different thread!
13470 </para>
13471 <para>
13472 Another implication is that since an Asio-aware fiber scheduler (not to mention
13473 <link linkend="callbacks_asio"><code><phrase role="identifier">boost</phrase><phrase
13474 role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase
13475 role="special">::</phrase><phrase role="identifier">asio</phrase><phrase
13476 role="special">::</phrase><phrase role="identifier">yield</phrase></code></link>)
13477 depends on handler calls from the <code><phrase role="identifier">io_service</phrase></code>,
13478 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
13479 role="identifier">io_service</phrase><phrase role="special">::</phrase><phrase
13480 role="identifier">stop</phrase><phrase role="special">()</phrase></code></ulink>
13481 is not called until every fiber has terminated.
13482 </para>
13483 <para>
13484 It is easier to reason about the behavior of the presented <code><phrase
13485 role="identifier">asio</phrase><phrase role="special">::</phrase><phrase
13486 role="identifier">round_robin</phrase></code> scheduler if we require that
13487 after initial setup, the thread&#8217;s main fiber is the fiber that calls <code><phrase
13488 role="identifier">io_service</phrase><phrase role="special">::</phrase><phrase
13489 role="identifier">run</phrase><phrase role="special">()</phrase></code>,
13490 so let&#8217;s impose that requirement.
13491 </para>
13492 <para>
13493 Naturally, the first thing we must do on each thread using a custom fiber
13494 scheduler is call <link linkend="use_scheduling_algorithm"><code>use_scheduling_algorithm()</code></link>. However,
13495 since <code><phrase role="identifier">asio</phrase><phrase role="special">::</phrase><phrase
13496 role="identifier">round_robin</phrase></code> requires an <code><phrase role="identifier">io_service</phrase></code>
13497 instance, we must first declare that.
13498 </para>
13499 <para>
13500 <programlisting><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">asio</phrase><phrase role="special">::</phrase><phrase role="identifier">io_service</phrase> <phrase role="identifier">io_svc</phrase><phrase role="special">;</phrase>
13501 <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>
13502 </programlisting>
13503 </para>
13504 <para>
13505 <code><phrase role="identifier">use_scheduling_algorithm</phrase><phrase
13506 role="special">()</phrase></code> instantiates <code><phrase role="identifier">asio</phrase><phrase
13507 role="special">::</phrase><phrase role="identifier">round_robin</phrase></code>,
13508 which naturally calls its constructor:
13509 </para>
13510 <para>
13511 <programlisting><phrase role="identifier">round_robin</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>
13512 <phrase role="identifier">io_svc_</phrase><phrase role="special">(</phrase> <phrase role="identifier">io_svc</phrase><phrase role="special">),</phrase>
13513 <phrase role="identifier">suspend_timer_</phrase><phrase role="special">(</phrase> <phrase role="identifier">io_svc_</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
13514 <phrase role="comment">// We use add_service() very deliberately. This will throw</phrase>
13515 <phrase role="comment">// service_already_exists if you pass the same io_service instance to</phrase>
13516 <phrase role="comment">// more than one round_robin instance.</phrase>
13517 <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="identifier">io_svc_</phrase><phrase role="special">,</phrase> <phrase role="keyword">new</phrase> <phrase role="identifier">service</phrase><phrase role="special">(</phrase> <phrase role="identifier">io_svc_</phrase><phrase role="special">));</phrase>
13518 <phrase role="special">}</phrase>
13519 </programlisting>
13520 </para>
13521 <para>
13522 <code><phrase role="identifier">asio</phrase><phrase role="special">::</phrase><phrase
13523 role="identifier">round_robin</phrase></code> binds the passed <code><phrase
13524 role="identifier">io_service</phrase></code> reference and initializes a
13525 <ulink url="http://www.boost.org/doc/libs/release/doc/html/boost_asio/reference/steady_timer.html"><code><phrase
13526 role="identifier">boost</phrase><phrase role="special">::</phrase><phrase
13527 role="identifier">asio</phrase><phrase role="special">::</phrase><phrase
13528 role="identifier">steady_timer</phrase></code></ulink>:
13529 </para>
13530 <para>
13531 <programlisting><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>
13532 <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>
13533 </programlisting>
13534 </para>
13535 <para>
13536 Then it calls <ulink url="http://www.boost.org/doc/libs/release/doc/html/boost_asio/reference/add_service.html"><code><phrase
13537 role="identifier">boost</phrase><phrase role="special">::</phrase><phrase
13538 role="identifier">asio</phrase><phrase role="special">::</phrase><phrase
13539 role="identifier">add_service</phrase><phrase role="special">()</phrase></code></ulink>
13540 with a nested <code><phrase role="identifier">service</phrase></code> struct:
13541 </para>
13542 <para>
13543 <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>
13544 <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>
13545
13546 <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>
13547
13548 <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>
13549 <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>
13550 <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>
13551 <phrase role="identifier">io_svc</phrase><phrase role="special">.</phrase><phrase role="identifier">post</phrase><phrase role="special">([&amp;</phrase><phrase role="identifier">io_svc</phrase><phrase role="special">](){</phrase>
13552 </programlisting>
13553 </para>
13554 <para>
13555 ...
13556 </para>
13557 <para>
13558 <programlisting> <phrase role="special">});</phrase>
13559 <phrase role="special">}</phrase>
13560
13561 <phrase role="keyword">virtual</phrase> <phrase role="special">~</phrase><phrase role="identifier">service</phrase><phrase role="special">()</phrase> <phrase role="special">{}</phrase>
13562
13563 <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>
13564 <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>
13565
13566 <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>
13567 <phrase role="identifier">work_</phrase><phrase role="special">.</phrase><phrase role="identifier">reset</phrase><phrase role="special">();</phrase>
13568 <phrase role="special">}</phrase>
13569 <phrase role="special">};</phrase>
13570 </programlisting>
13571 </para>
13572 <para>
13573 The <code><phrase role="identifier">service</phrase></code> struct has a
13574 couple of roles.
13575 </para>
13576 <para>
13577 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
13578 role="identifier">boost</phrase><phrase role="special">::</phrase><phrase
13579 role="identifier">asio</phrase><phrase role="special">::</phrase><phrase
13580 role="identifier">io_service</phrase><phrase role="special">::</phrase><phrase
13581 role="identifier">work</phrase></code></ulink>&gt;</literal>. We want the
13582 <code><phrase role="identifier">io_service</phrase></code> instance to continue
13583 its main loop even when there is no pending Asio I/O.
13584 </para>
13585 <para>
13586 But when <ulink url="http://www.boost.org/doc/libs/release/doc/html/boost_asio/reference/io_service__service/shutdown_service.html"><code><phrase
13587 role="identifier">boost</phrase><phrase role="special">::</phrase><phrase
13588 role="identifier">asio</phrase><phrase role="special">::</phrase><phrase
13589 role="identifier">io_service</phrase><phrase role="special">::</phrase><phrase
13590 role="identifier">service</phrase><phrase role="special">::</phrase><phrase
13591 role="identifier">shutdown_service</phrase><phrase role="special">()</phrase></code></ulink>
13592 is called, we discard the <code><phrase role="identifier">io_service</phrase><phrase
13593 role="special">::</phrase><phrase role="identifier">work</phrase></code>
13594 instance so the <code><phrase role="identifier">io_service</phrase></code>
13595 can shut down properly.
13596 </para>
13597 <para>
13598 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
13599 role="identifier">post</phrase><phrase role="special">()</phrase></code></ulink>
13600 a lambda (not yet shown). Let&#8217;s walk further through the example program before
13601 coming back to explain that lambda.
13602 </para>
13603 <para>
13604 The <code><phrase role="identifier">service</phrase></code> constructor returns
13605 to <code><phrase role="identifier">asio</phrase><phrase role="special">::</phrase><phrase
13606 role="identifier">round_robin</phrase></code>&#8217;s constructor, which returns
13607 to <code><phrase role="identifier">use_scheduling_algorithm</phrase><phrase
13608 role="special">()</phrase></code>, which returns to the application code.
13609 </para>
13610 <para>
13611 Once it has called <code><phrase role="identifier">use_scheduling_algorithm</phrase><phrase
13612 role="special">()</phrase></code>, the application may now launch some number
13613 of fibers:
13614 </para>
13615 <para>
13616 <programlisting><phrase role="comment">// server</phrase>
13617 <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="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>
13618 <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">std</phrase><phrase role="special">::</phrase><phrase role="identifier">ref</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>
13619 <phrase role="comment">// client</phrase>
13620 <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>
13621 <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>
13622 <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>
13623 <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>
13624 <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>
13625 <phrase role="identifier">client</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">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>
13626 <phrase role="special">}</phrase>
13627 </programlisting>
13628 </para>
13629 <para>
13630 Since we don&#8217;t specify a <link linkend="class_launch"><code>launch</code></link>, these fibers are ready to run,
13631 but have not yet been entered.
13632 </para>
13633 <para>
13634 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
13635 role="identifier">io_service</phrase><phrase role="special">::</phrase><phrase
13636 role="identifier">run</phrase><phrase role="special">()</phrase></code></ulink>:
13637 </para>
13638 <para>
13639 <programlisting><phrase role="identifier">io_svc</phrase><phrase role="special">.</phrase><phrase role="identifier">run</phrase><phrase role="special">();</phrase>
13640 </programlisting>
13641 </para>
13642 <para>
13643 Now what?
13644 </para>
13645 <para>
13646 Because this <code><phrase role="identifier">io_service</phrase></code> instance
13647 owns an <code><phrase role="identifier">io_service</phrase><phrase role="special">::</phrase><phrase
13648 role="identifier">work</phrase></code> instance, <code><phrase role="identifier">run</phrase><phrase
13649 role="special">()</phrase></code> does not immediately return. But &mdash; none of
13650 the fibers that will perform actual work has even been entered yet!
13651 </para>
13652 <para>
13653 Without that initial <code><phrase role="identifier">post</phrase><phrase
13654 role="special">()</phrase></code> call in <code><phrase role="identifier">service</phrase></code>&#8217;s
13655 constructor, <emphasis>nothing</emphasis> would happen. The application would
13656 hang right here.
13657 </para>
13658 <para>
13659 So, what should the <code><phrase role="identifier">post</phrase><phrase
13660 role="special">()</phrase></code> handler execute? Simply <link linkend="this_fiber_yield"><code>this_fiber::yield()</code></link>?
13661 </para>
13662 <para>
13663 That would be a promising start. But we have no guarantee that any of the
13664 other fibers will initiate any Asio operations to keep the ball rolling.
13665 For all we know, every other fiber could reach a similar <code><phrase role="identifier">this_fiber</phrase><phrase
13666 role="special">::</phrase><phrase role="identifier">yield</phrase><phrase
13667 role="special">()</phrase></code> call first. Control would return to the
13668 <code><phrase role="identifier">post</phrase><phrase role="special">()</phrase></code>
13669 handler, which would return to Asio, and... the application would hang.
13670 </para>
13671 <para>
13672 The <code><phrase role="identifier">post</phrase><phrase role="special">()</phrase></code>
13673 handler could <code><phrase role="identifier">post</phrase><phrase role="special">()</phrase></code>
13674 itself again. But as discussed in <link linkend="embedded_main_loop">the
13675 previous section</link>, once there are actual I/O operations in flight &mdash; once
13676 we reach a state in which no fiber is ready &mdash;
13677 that would cause the thread to
13678 spin.
13679 </para>
13680 <para>
13681 We could, of course, set an Asio timer &mdash; again as <link linkend="embedded_main_loop">previously
13682 discussed</link>. But in this <quote>deeper dive,</quote> we&#8217;re trying to
13683 do a little better.
13684 </para>
13685 <para>
13686 The key to doing better is that since we&#8217;re in a fiber, we can run an actual
13687 loop &mdash; not just a chain of callbacks. We can wait for <quote>something to happen</quote>
13688 by calling <ulink url="http://www.boost.org/doc/libs/release/doc/html/boost_asio/reference/io_service/run_one.html"><code><phrase
13689 role="identifier">io_service</phrase><phrase role="special">::</phrase><phrase
13690 role="identifier">run_one</phrase><phrase role="special">()</phrase></code></ulink>
13691 &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
13692 role="identifier">io_service</phrase><phrase role="special">::</phrase><phrase
13693 role="identifier">poll</phrase><phrase role="special">()</phrase></code></ulink>.
13694 </para>
13695 <para>
13696 Here&#8217;s the body of the lambda passed to the <code><phrase role="identifier">post</phrase><phrase
13697 role="special">()</phrase></code> call.
13698 </para>
13699 <para>
13700 <programlisting><phrase role="keyword">while</phrase> <phrase role="special">(</phrase> <phrase role="special">!</phrase> <phrase role="identifier">io_svc</phrase><phrase role="special">.</phrase><phrase role="identifier">stopped</phrase><phrase role="special">()</phrase> <phrase role="special">)</phrase> <phrase role="special">{</phrase>
13701 <phrase role="keyword">if</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">has_ready_fibers</phrase><phrase role="special">()</phrase> <phrase role="special">)</phrase> <phrase role="special">{</phrase>
13702 <phrase role="comment">// run all pending handlers in round_robin</phrase>
13703 <phrase role="keyword">while</phrase> <phrase role="special">(</phrase> <phrase role="identifier">io_svc</phrase><phrase role="special">.</phrase><phrase role="identifier">poll</phrase><phrase role="special">()</phrase> <phrase role="special">);</phrase>
13704 <phrase role="comment">// run pending (ready) fibers</phrase>
13705 <phrase role="identifier">this_fiber</phrase><phrase role="special">::</phrase><phrase role="identifier">yield</phrase><phrase role="special">();</phrase>
13706 <phrase role="special">}</phrase> <phrase role="keyword">else</phrase> <phrase role="special">{</phrase>
13707 <phrase role="comment">// run one handler inside io_service</phrase>
13708 <phrase role="comment">// if no handler available, block this thread</phrase>
13709 <phrase role="keyword">if</phrase> <phrase role="special">(</phrase> <phrase role="special">!</phrase> <phrase role="identifier">io_svc</phrase><phrase role="special">.</phrase><phrase role="identifier">run_one</phrase><phrase role="special">()</phrase> <phrase role="special">)</phrase> <phrase role="special">{</phrase>
13710 <phrase role="keyword">break</phrase><phrase role="special">;</phrase>
13711 <phrase role="special">}</phrase>
13712 <phrase role="special">}</phrase>
13713 <phrase role="special">}</phrase>
13714 </programlisting>
13715 </para>
13716 <para>
13717 We want this loop to exit once the <code><phrase role="identifier">io_service</phrase></code>
13718 instance has been <ulink url="http://www.boost.org/doc/libs/release/doc/html/boost_asio/reference/io_service/stopped.html"><code><phrase
13719 role="identifier">stopped</phrase><phrase role="special">()</phrase></code></ulink>.
13720 </para>
13721 <para>
13722 As long as there are ready fibers, we interleave running ready Asio handlers
13723 with running ready fibers.
13724 </para>
13725 <para>
13726 If there are no ready fibers, we wait by calling <code><phrase role="identifier">run_one</phrase><phrase
13727 role="special">()</phrase></code>. Once any Asio handler has been called
13728 &mdash; no matter which &mdash; <code><phrase role="identifier">run_one</phrase><phrase role="special">()</phrase></code>
13729 returns. That handler may have transitioned some fiber to ready state, so
13730 we loop back to check again.
13731 </para>
13732 <para>
13733 (We won&#8217;t describe <code><phrase role="identifier">awakened</phrase><phrase
13734 role="special">()</phrase></code>, <code><phrase role="identifier">pick_next</phrase><phrase
13735 role="special">()</phrase></code> or <code><phrase role="identifier">has_ready_fibers</phrase><phrase
13736 role="special">()</phrase></code>, as these are just like <link linkend="round_robin_awakened"><code>round_robin::awakened()</code></link>,
13737 <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>.)
13738 </para>
13739 <para>
13740 That leaves <code><phrase role="identifier">suspend_until</phrase><phrase
13741 role="special">()</phrase></code> and <code><phrase role="identifier">notify</phrase><phrase
13742 role="special">()</phrase></code>.
13743 </para>
13744 <para>
13745 Doubtless you have been asking yourself: why are we calling <code><phrase
13746 role="identifier">io_service</phrase><phrase role="special">::</phrase><phrase
13747 role="identifier">run_one</phrase><phrase role="special">()</phrase></code>
13748 in the lambda loop? Why not call it in <code><phrase role="identifier">suspend_until</phrase><phrase
13749 role="special">()</phrase></code>, whose very API was designed for just such
13750 a purpose?
13751 </para>
13752 <para>
13753 Under normal circumstances, when the fiber manager finds no ready fibers,
13754 it calls <link linkend="algorithm_suspend_until"><code>algorithm::suspend_until()</code></link>. Why test <code><phrase
13755 role="identifier">has_ready_fibers</phrase><phrase role="special">()</phrase></code>
13756 in the lambda loop? Why not leverage the normal mechanism?
13757 </para>
13758 <para>
13759 The answer is: it matters who&#8217;s asking.
13760 </para>
13761 <para>
13762 Consider the lambda loop shown above. The only <emphasis role="bold">Boost.Fiber</emphasis>
13763 APIs it engages are <code><phrase role="identifier">has_ready_fibers</phrase><phrase
13764 role="special">()</phrase></code> and <link linkend="this_fiber_yield"><code>this_fiber::yield()</code></link>.
13765 <code><phrase role="identifier">yield</phrase><phrase role="special">()</phrase></code>
13766 does not <emphasis>block</emphasis> the calling fiber: the calling fiber
13767 does not become unready. It is immediately passed back to <link linkend="algorithm_awakened"><code>algorithm::awakened()</code></link>,
13768 to be resumed in its turn when all other ready fibers have had a chance to
13769 run. In other words: during a <code><phrase role="identifier">yield</phrase><phrase
13770 role="special">()</phrase></code> call, <emphasis>there is always at least
13771 one ready fiber.</emphasis>
13772 </para>
13773 <para>
13774 As long as this lambda loop is still running, the fiber manager does not
13775 call <code><phrase role="identifier">suspend_until</phrase><phrase role="special">()</phrase></code>
13776 because it always has a fiber ready to run.
13777 </para>
13778 <para>
13779 However, the lambda loop <emphasis>itself</emphasis> can detect the case
13780 when no <emphasis>other</emphasis> fibers are ready to run: the running fiber
13781 is not <emphasis>ready</emphasis> but <emphasis>running.</emphasis>
13782 </para>
13783 <para>
13784 That said, <code><phrase role="identifier">suspend_until</phrase><phrase
13785 role="special">()</phrase></code> and <code><phrase role="identifier">notify</phrase><phrase
13786 role="special">()</phrase></code> are in fact called during orderly shutdown
13787 processing, so let&#8217;s try a plausible implementation.
13788 </para>
13789 <para>
13790 <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>
13791 <phrase role="comment">// Set a timer so at least one handler will eventually fire, causing</phrase>
13792 <phrase role="comment">// run_one() to eventually return. Set a timer even if abs_time ==</phrase>
13793 <phrase role="comment">// time_point::max() so the timer can be canceled by our notify()</phrase>
13794 <phrase role="comment">// method -- which calls the handler.</phrase>
13795 <phrase role="keyword">if</phrase> <phrase role="special">(</phrase> <phrase role="identifier">suspend_timer_</phrase><phrase role="special">.</phrase><phrase role="identifier">expires_at</phrase><phrase role="special">()</phrase> <phrase role="special">!=</phrase> <phrase role="identifier">abs_time</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
13796 <phrase role="comment">// Each expires_at(time_point) call cancels any previous pending</phrase>
13797 <phrase role="comment">// call. We could inadvertently spin like this:</phrase>
13798 <phrase role="comment">// dispatcher calls suspend_until() with earliest wake time</phrase>
13799 <phrase role="comment">// suspend_until() sets suspend_timer_</phrase>
13800 <phrase role="comment">// lambda loop calls run_one()</phrase>
13801 <phrase role="comment">// some other asio handler runs before timer expires</phrase>
13802 <phrase role="comment">// run_one() returns to lambda loop</phrase>
13803 <phrase role="comment">// lambda loop yields to dispatcher</phrase>
13804 <phrase role="comment">// dispatcher finds no ready fibers</phrase>
13805 <phrase role="comment">// dispatcher calls suspend_until() with SAME wake time</phrase>
13806 <phrase role="comment">// suspend_until() sets suspend_timer_ to same time, canceling</phrase>
13807 <phrase role="comment">// previous async_wait()</phrase>
13808 <phrase role="comment">// lambda loop calls run_one()</phrase>
13809 <phrase role="comment">// asio calls suspend_timer_ handler with operation_aborted</phrase>
13810 <phrase role="comment">// run_one() returns to lambda loop... etc. etc.</phrase>
13811 <phrase role="comment">// So only actually set the timer when we're passed a DIFFERENT</phrase>
13812 <phrase role="comment">// abs_time value.</phrase>
13813 <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>
13814 <phrase role="comment">// It really doesn't matter what the suspend_timer_ handler does,</phrase>
13815 <phrase role="comment">// or even whether it's called because the timer ran out or was</phrase>
13816 <phrase role="comment">// canceled. The whole point is to cause the run_one() call to</phrase>
13817 <phrase role="comment">// return. So just pass a no-op lambda with proper signature.</phrase>
13818 <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>
13819 <phrase role="special">}</phrase>
13820 <phrase role="special">}</phrase>
13821 </programlisting>
13822 </para>
13823 <para>
13824 As you might expect, <code><phrase role="identifier">suspend_until</phrase><phrase
13825 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
13826 role="identifier">asio</phrase><phrase role="special">::</phrase><phrase
13827 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
13828 role="identifier">expires_at</phrase><phrase role="special">()</phrase></code></ulink>
13829 the passed <ulink url="http://en.cppreference.com/w/cpp/chrono/steady_clock"><code><phrase
13830 role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase
13831 role="special">::</phrase><phrase role="identifier">steady_clock</phrase><phrase
13832 role="special">::</phrase><phrase role="identifier">time_point</phrase></code></ulink>.
13833 Usually.
13834 </para>
13835 <para>
13836 As indicated in comments, we avoid setting <code><phrase role="identifier">suspend_timer_</phrase></code>
13837 multiple times to the <emphasis>same</emphasis> <code><phrase role="identifier">time_point</phrase></code>
13838 value since every <code><phrase role="identifier">expires_at</phrase><phrase
13839 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
13840 role="identifier">async_wait</phrase><phrase role="special">()</phrase></code></ulink>
13841 call. There is a chance that we could spin. Reaching <code><phrase role="identifier">suspend_until</phrase><phrase
13842 role="special">()</phrase></code> means the fiber manager intends to yield
13843 the processor to Asio. Cancelling the previous <code><phrase role="identifier">async_wait</phrase><phrase
13844 role="special">()</phrase></code> call would fire its handler, causing <code><phrase
13845 role="identifier">run_one</phrase><phrase role="special">()</phrase></code>
13846 to return, potentially causing the fiber manager to call <code><phrase role="identifier">suspend_until</phrase><phrase
13847 role="special">()</phrase></code> again with the same <code><phrase role="identifier">time_point</phrase></code>
13848 value...
13849 </para>
13850 <para>
13851 Given that we suspend the thread by calling <code><phrase role="identifier">io_service</phrase><phrase
13852 role="special">::</phrase><phrase role="identifier">run_one</phrase><phrase
13853 role="special">()</phrase></code>, what&#8217;s important is that our <code><phrase
13854 role="identifier">async_wait</phrase><phrase role="special">()</phrase></code>
13855 call will cause a handler to run, which will cause <code><phrase role="identifier">run_one</phrase><phrase
13856 role="special">()</phrase></code> to return. It&#8217;s not so important specifically
13857 what that handler does.
13858 </para>
13859 <para>
13860 <programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">notify</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase> <phrase role="special">{</phrase>
13861 <phrase role="comment">// Something has happened that should wake one or more fibers BEFORE</phrase>
13862 <phrase role="comment">// suspend_timer_ expires. Reset the timer to cause it to fire</phrase>
13863 <phrase role="comment">// immediately, causing the run_one() call to return. In theory we</phrase>
13864 <phrase role="comment">// could use cancel() because we don't care whether suspend_timer_'s</phrase>
13865 <phrase role="comment">// handler is called with operation_aborted or success. However --</phrase>
13866 <phrase role="comment">// cancel() doesn't change the expiration time, and we use</phrase>
13867 <phrase role="comment">// suspend_timer_'s expiration time to decide whether it's already</phrase>
13868 <phrase role="comment">// set. If suspend_until() set some specific wake time, then notify()</phrase>
13869 <phrase role="comment">// canceled it, then suspend_until() was called again with the same</phrase>
13870 <phrase role="comment">// wake time, it would match suspend_timer_'s expiration time and we'd</phrase>
13871 <phrase role="comment">// refrain from setting the timer. So instead of simply calling</phrase>
13872 <phrase role="comment">// cancel(), reset the timer, which cancels the pending sleep AND sets</phrase>
13873 <phrase role="comment">// a new expiration time. This will cause us to spin the loop twice --</phrase>
13874 <phrase role="comment">// once for the operation_aborted handler, once for timer expiration</phrase>
13875 <phrase role="comment">// -- but that shouldn't be a big problem.</phrase>
13876 <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>
13877 <phrase role="special">}</phrase>
13878 </programlisting>
13879 </para>
13880 <para>
13881 Since an <code><phrase role="identifier">expires_at</phrase><phrase role="special">()</phrase></code>
13882 call cancels any previous <code><phrase role="identifier">async_wait</phrase><phrase
13883 role="special">()</phrase></code> call, we can make <code><phrase role="identifier">notify</phrase><phrase
13884 role="special">()</phrase></code> simply call <code><phrase role="identifier">steady_timer</phrase><phrase
13885 role="special">::</phrase><phrase role="identifier">expires_at</phrase><phrase
13886 role="special">()</phrase></code>. That should cause the <code><phrase role="identifier">io_service</phrase></code>
13887 to call the <code><phrase role="identifier">async_wait</phrase><phrase role="special">()</phrase></code>
13888 handler with <code><phrase role="identifier">operation_aborted</phrase></code>.
13889 </para>
13890 <para>
13891 The comments in <code><phrase role="identifier">notify</phrase><phrase role="special">()</phrase></code>
13892 explain why we call <code><phrase role="identifier">expires_at</phrase><phrase
13893 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
13894 role="identifier">cancel</phrase><phrase role="special">()</phrase></code></ulink>.
13895 </para>
13896 <para>
13897 This <code><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase
13898 role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase
13899 role="identifier">asio</phrase><phrase role="special">::</phrase><phrase
13900 role="identifier">round_robin</phrase></code> implementation is used in
13901 <ulink url="../../examples/asio/autoecho.cpp"><code><phrase role="identifier">examples</phrase><phrase
13902 role="special">/</phrase><phrase role="identifier">asio</phrase><phrase role="special">/</phrase><phrase
13903 role="identifier">autoecho</phrase><phrase role="special">.</phrase><phrase
13904 role="identifier">cpp</phrase></code></ulink>.
13905 </para>
13906 <para>
13907 It seems possible that you could put together a more elegant Fiber / Asio
13908 integration. But as noted at the outset: it&#8217;s tricky.
13909 </para>
13910 </section>
13911 </section>
13912 <section id="fiber.performance">
13913 <title><link linkend="fiber.performance">Performance</link></title>
13914 <para>
13915 Performance measurements were taken using <code><phrase role="identifier">std</phrase><phrase
13916 role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase
13917 role="special">::</phrase><phrase role="identifier">highresolution_clock</phrase></code>,
13918 with overhead corrections. The code was compiled using the build options: variant
13919 = release, optimization = speed <footnote id="fiber.performance.f0">
13920 <para>
13921 Intel Core2 Q6700, x86_64, 3GHz
13922 </para>
13923 </footnote>.
13924 </para>
13925 <para>
13926 The columns labeled <emphasis role="bold">fiber (atomics)</emphasis> were compiled
13927 with default fiber synchronization, capable of synchronizing fibers running
13928 on different threads. The columns labeled <emphasis role="bold">fiber (raw)</emphasis>
13929 were compiled with <link linkend="cross_thread_sync"><code><phrase role="identifier">BOOST_FIBERS_NO_ATOMICS</phrase></code></link>.
13930 </para>
13931 <table frame="all" id="fiber.performance.overhead_of_join__contains_fiber_context_destruction__fiber_stack_deallocation_">
13932 <title>Overhead of join (contains fiber-context destruction, fiber-stack deallocation)</title>
13933 <tgroup cols="5">
13934 <thead>
13935 <row>
13936 <entry>
13937 <para>
13938 thread
13939 </para>
13940 </entry>
13941 <entry>
13942 <para>
13943 fiber (atomics)
13944 </para>
13945 </entry>
13946 <entry>
13947 <para>
13948 fiber (raw)
13949 </para>
13950 </entry>
13951 <entry>
13952 <para>
13953 tbb
13954 </para>
13955 </entry>
13956 <entry>
13957 <para>
13958 qthread
13959 </para>
13960 </entry>
13961 </row>
13962 </thead>
13963 <tbody>
13964 <row>
13965 <entry>
13966 <para>
13967 18 &#xb5;s
13968 </para>
13969 </entry>
13970 <entry>
13971 <para>
13972 950 ns
13973 </para>
13974 </entry>
13975 <entry>
13976 <para>
13977 900 ns
13978 </para>
13979 </entry>
13980 <entry>
13981 <para>
13982 570 ns
13983 </para>
13984 </entry>
13985 <entry>
13986 <para>
13987 620 ns
13988 </para>
13989 </entry>
13990 </row>
13991 </tbody>
13992 </tgroup>
13993 </table>
13994 <para>
13995 (from <ulink url="../../performance/fiber/overhead_join.cpp">overhead_join.cpp</ulink>)
13996 </para>
13997 <table frame="all" id="fiber.performance.overhead_of_detach">
13998 <title>Overhead of detach</title>
13999 <tgroup cols="3">
14000 <thead>
14001 <row>
14002 <entry>
14003 <para>
14004 thread
14005 </para>
14006 </entry>
14007 <entry>
14008 <para>
14009 fiber (atomics)
14010 </para>
14011 </entry>
14012 <entry>
14013 <para>
14014 fiber (raw)
14015 </para>
14016 </entry>
14017 </row>
14018 </thead>
14019 <tbody>
14020 <row>
14021 <entry>
14022 <para>
14023 126 ns
14024 </para>
14025 </entry>
14026 <entry>
14027 <para>
14028 21 ns
14029 </para>
14030 </entry>
14031 <entry>
14032 <para>
14033 20 ns
14034 </para>
14035 </entry>
14036 </row>
14037 </tbody>
14038 </tgroup>
14039 </table>
14040 <para>
14041 (from <ulink url="../../performance/fiber/overhead_detach.cpp">overhead_detach.cpp</ulink>)
14042 </para>
14043 <table frame="all" id="fiber.performance.overhead_of_yield">
14044 <title>Overhead of yield</title>
14045 <tgroup cols="3">
14046 <thead>
14047 <row>
14048 <entry>
14049 <para>
14050 thread
14051 </para>
14052 </entry>
14053 <entry>
14054 <para>
14055 fiber (atomics)
14056 </para>
14057 </entry>
14058 <entry>
14059 <para>
14060 fiber (raw)
14061 </para>
14062 </entry>
14063 </row>
14064 </thead>
14065 <tbody>
14066 <row>
14067 <entry>
14068 <para>
14069 1.5 &#xb5;s
14070 </para>
14071 </entry>
14072 <entry>
14073 <para>
14074 310 ns
14075 </para>
14076 </entry>
14077 <entry>
14078 <para>
14079 330 ns
14080 </para>
14081 </entry>
14082 </row>
14083 </tbody>
14084 </tgroup>
14085 </table>
14086 <para>
14087 (from <ulink url="../../performance/fiber/overhead_yield.cpp">overhead_yield.cpp</ulink>)
14088 </para>
14089 <table frame="all" id="fiber.performance.overhead_of_waiting_on_a_future">
14090 <title>Overhead of waiting on a future</title>
14091 <tgroup cols="3">
14092 <thead>
14093 <row>
14094 <entry>
14095 <para>
14096 thread
14097 </para>
14098 </entry>
14099 <entry>
14100 <para>
14101 fiber (atomics)
14102 </para>
14103 </entry>
14104 <entry>
14105 <para>
14106 fiber (raw)
14107 </para>
14108 </entry>
14109 </row>
14110 </thead>
14111 <tbody>
14112 <row>
14113 <entry>
14114 <para>
14115 16 &#xb5;s
14116 </para>
14117 </entry>
14118 <entry>
14119 <para>
14120 1.40 &#xb5;s
14121 </para>
14122 </entry>
14123 <entry>
14124 <para>
14125 1.38 &#xb5;s
14126 </para>
14127 </entry>
14128 </row>
14129 </tbody>
14130 </tgroup>
14131 </table>
14132 <para>
14133 (from <ulink url="../../performance/fiber/overhead_future.cpp">overhead_future.cpp</ulink>)
14134 </para>
14135 <table frame="all" id="fiber.performance.overhead_of_fiber_creation__contains_fiber_stack_allocation_and_preparation__fiber_context_construction__scheduler_handling_">
14136 <title>Overhead of fiber creation (contains fiber-stack allocation and preparation,
14137 fiber-context construction, scheduler handling)</title>
14138 <tgroup cols="3">
14139 <thead>
14140 <row>
14141 <entry>
14142 <para>
14143 thread
14144 </para>
14145 </entry>
14146 <entry>
14147 <para>
14148 fiber (atomics)
14149 </para>
14150 </entry>
14151 <entry>
14152 <para>
14153 fiber (raw)
14154 </para>
14155 </entry>
14156 </row>
14157 </thead>
14158 <tbody>
14159 <row>
14160 <entry>
14161 <para>
14162 18 &#xb5;s
14163 </para>
14164 </entry>
14165 <entry>
14166 <para>
14167 450 ns
14168 </para>
14169 </entry>
14170 <entry>
14171 <para>
14172 445 ns
14173 </para>
14174 </entry>
14175 </row>
14176 </tbody>
14177 </tgroup>
14178 </table>
14179 <para>
14180 (from <ulink url="../../performance/fiber/overhead_create.cpp">overhead_create.cpp</ulink>)
14181 </para>
14182 <table frame="all" id="fiber.performance.scaling_of_creating_and_joining">
14183 <title>Scaling of creating and joining</title>
14184 <tgroup cols="4">
14185 <thead>
14186 <row>
14187 <entry>
14188 <para>
14189 average of
14190 </para>
14191 </entry>
14192 <entry>
14193 <para>
14194 thread
14195 </para>
14196 </entry>
14197 <entry>
14198 <para>
14199 fiber (atomics)
14200 </para>
14201 </entry>
14202 <entry>
14203 <para>
14204 fiber (raw)
14205 </para>
14206 </entry>
14207 </row>
14208 </thead>
14209 <tbody>
14210 <row>
14211 <entry>
14212 <para>
14213 10
14214 </para>
14215 </entry>
14216 <entry>
14217 <para>
14218 8.21 &#xb5;s
14219 </para>
14220 </entry>
14221 <entry>
14222 <para>
14223 1.96 &#xb5;s
14224 </para>
14225 </entry>
14226 <entry>
14227 <para>
14228 1.85 &#xb5;s
14229 </para>
14230 </entry>
14231 </row>
14232 <row>
14233 <entry>
14234 <para>
14235 50
14236 </para>
14237 </entry>
14238 <entry>
14239 <para>
14240 6.67 &#xb5;s
14241 </para>
14242 </entry>
14243 <entry>
14244 <para>
14245 1.40 &#xb5;s
14246 </para>
14247 </entry>
14248 <entry>
14249 <para>
14250 1.27 &#xb5;s
14251 </para>
14252 </entry>
14253 </row>
14254 <row>
14255 <entry>
14256 <para>
14257 100
14258 </para>
14259 </entry>
14260 <entry>
14261 <para>
14262 6.79 &#xb5;s
14263 </para>
14264 </entry>
14265 <entry>
14266 <para>
14267 1.84 &#xb5;s
14268 </para>
14269 </entry>
14270 <entry>
14271 <para>
14272 1.81 &#xb5;s
14273 </para>
14274 </entry>
14275 </row>
14276 <row>
14277 <entry>
14278 <para>
14279 500
14280 </para>
14281 </entry>
14282 <entry>
14283 <para>
14284 8.25 &#xb5;s
14285 </para>
14286 </entry>
14287 <entry>
14288 <para>
14289 1.13 &#xb5;s
14290 </para>
14291 </entry>
14292 <entry>
14293 <para>
14294 1.10 &#xb5;s
14295 </para>
14296 </entry>
14297 </row>
14298 <row>
14299 <entry>
14300 <para>
14301 1000
14302 </para>
14303 </entry>
14304 <entry>
14305 <para>
14306 7.71 &#xb5;s
14307 </para>
14308 </entry>
14309 <entry>
14310 <para>
14311 1.46 &#xb5;s
14312 </para>
14313 </entry>
14314 <entry>
14315 <para>
14316 1.26 &#xb5;s
14317 </para>
14318 </entry>
14319 </row>
14320 <row>
14321 <entry>
14322 <para>
14323 5000
14324 </para>
14325 </entry>
14326 <entry>
14327 <para>
14328 5.67 &#xb5;s
14329 </para>
14330 </entry>
14331 <entry>
14332 <para>
14333 2.11 &#xb5;s
14334 </para>
14335 </entry>
14336 <entry>
14337 <para>
14338 1.90 &#xb5;s
14339 </para>
14340 </entry>
14341 </row>
14342 <row>
14343 <entry>
14344 <para>
14345 10000
14346 </para>
14347 </entry>
14348 <entry>
14349 <para>
14350 5.25 &#xb5;s
14351 </para>
14352 </entry>
14353 <entry>
14354 <para>
14355 2.36 &#xb5;s
14356 </para>
14357 </entry>
14358 <entry>
14359 <para>
14360 1.89 &#xb5;s
14361 </para>
14362 </entry>
14363 </row>
14364 </tbody>
14365 </tgroup>
14366 </table>
14367 <para>
14368 (from <ulink url="../../performance/fiber/scale_join.cpp">scale_join.cpp</ulink>)
14369 </para>
14370 <para>
14371 Numbers of the <ulink url="https://github.com/atemerev/skynet">microbenchmark
14372 <emphasis>syknet</emphasis></ulink> from Alexander Temerev <footnote id="fiber.performance.f1">
14373 <para>
14374 Intel Core2 Q6700, x86_64, 3GHz
14375 </para>
14376 </footnote>:
14377 </para>
14378 <table frame="all" id="fiber.performance.performance_of_n_100000_actors_goroutines_fibers">
14379 <title>performance of N=100000 actors/goroutines/fibers</title>
14380 <tgroup cols="5">
14381 <thead>
14382 <row>
14383 <entry>
14384 <para>
14385 Haskell | stack-1.0.4
14386 </para>
14387 </entry>
14388 <entry>
14389 <para>
14390 fiber (single threaded/raw) | gcc-5.2.1
14391 </para>
14392 </entry>
14393 <entry>
14394 <para>
14395 fiber (single threaded/atomics) | gcc-5.2.1
14396 </para>
14397 </entry>
14398 <entry>
14399 <para>
14400 Erlang | erts-7.0
14401 </para>
14402 </entry>
14403 <entry>
14404 <para>
14405 Go | go1.4.2
14406 </para>
14407 </entry>
14408 </row>
14409 </thead>
14410 <tbody>
14411 <row>
14412 <entry>
14413 <para>
14414 58ms - 108ms
14415 </para>
14416 </entry>
14417 <entry>
14418 <para>
14419 205ms - 263ms
14420 </para>
14421 </entry>
14422 <entry>
14423 <para>
14424 221ms - 278ms
14425 </para>
14426 </entry>
14427 <entry>
14428 <para>
14429 237ms- 470ms
14430 </para>
14431 </entry>
14432 <entry>
14433 <para>
14434 614ms - 883ms
14435 </para>
14436 </entry>
14437 </row>
14438 </tbody>
14439 </tgroup>
14440 </table>
14441 </section>
14442 <section id="fiber.custom">
14443 <title><anchor id="custom"/><link linkend="fiber.custom">Customization</link></title>
14444 <bridgehead renderas="sect3" id="fiber.custom.h0">
14445 <phrase id="fiber.custom.overview"/><link linkend="fiber.custom.overview">Overview</link>
14446 </bridgehead>
14447 <para>
14448 As noted in the <link linkend="scheduling">Scheduling</link> section, by default
14449 <emphasis role="bold">Boost.Fiber</emphasis> uses its own <link linkend="class_round_robin"><code>round_robin</code></link> scheduler
14450 for each thread. To control the way <emphasis role="bold">Boost.Fiber</emphasis>
14451 schedules ready fibers on a particular thread, in general you must follow several
14452 steps. This section discusses those steps, whereas <link linkend="scheduling">Scheduling</link>
14453 serves as a reference for the classes involved.
14454 </para>
14455 <para>
14456 The library's fiber manager keeps track of suspended (blocked) fibers. Only
14457 when a fiber becomes ready to run is it passed to the scheduler. Of course,
14458 if there are fewer than two ready fibers, the scheduler's job is trivial. Only
14459 when there are two or more ready fibers does the particular scheduler implementation
14460 start to influence the overall sequence of fiber execution.
14461 </para>
14462 <para>
14463 In this section we illustrate a simple custom scheduler that honors an integer
14464 fiber priority. We will implement it such that a fiber with higher priority
14465 is preferred over a fiber with lower priority. Any fibers with equal priority
14466 values are serviced on a round-robin basis.
14467 </para>
14468 <para>
14469 The full source code for the examples below is found in <ulink url="../../examples/priority.cpp">priority.cpp</ulink>.
14470 </para>
14471 <bridgehead renderas="sect3" id="fiber.custom.h1">
14472 <phrase id="fiber.custom.custom_property_class"/><link linkend="fiber.custom.custom_property_class">Custom
14473 Property Class</link>
14474 </bridgehead>
14475 <para>
14476 The first essential point is that we must associate an integer priority with
14477 each fiber.<footnote id="fiber.custom.f0">
14478 <para>
14479 A previous version of the Fiber library implicitly tracked an int priority
14480 for each fiber, even though the default scheduler ignored it. This has been
14481 dropped, since the library now supports arbitrary scheduler-specific fiber
14482 properties.
14483 </para>
14484 </footnote>
14485 </para>
14486 <para>
14487 One might suggest deriving a custom <link linkend="class_fiber"><code>fiber</code></link> subclass to store such
14488 properties. There are a couple of reasons for the present mechanism.
14489 </para>
14490 <orderedlist>
14491 <listitem>
14492 <simpara>
14493 <emphasis role="bold">Boost.Fiber</emphasis> provides a number of different
14494 ways to launch a fiber. (Consider <link linkend="fibers_async"><code>fibers::async()</code></link>.) Higher-level
14495 libraries might introduce additional such wrapper functions. A custom scheduler
14496 must associate its custom properties with <emphasis>every</emphasis> fiber
14497 in the thread, not only the ones explicitly launched by instantiating a
14498 custom <code><phrase role="identifier">fiber</phrase></code> subclass.
14499 </simpara>
14500 </listitem>
14501 <listitem>
14502 <simpara>
14503 Consider a large existing program that launches fibers in many different
14504 places in the code. We discover a need to introduce a custom scheduler
14505 for a particular thread. If supporting that scheduler's custom properties
14506 required a particular <code><phrase role="identifier">fiber</phrase></code>
14507 subclass, we would have to hunt down and modify every place that launches
14508 a fiber on that thread.
14509 </simpara>
14510 </listitem>
14511 <listitem>
14512 <simpara>
14513 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.
14514 A subclass of <code><phrase role="identifier">fiber</phrase></code> would
14515 not add data to <code><phrase role="identifier">context</phrase></code>.
14516 </simpara>
14517 </listitem>
14518 </orderedlist>
14519 <para>
14520 The present mechanism allows you to <quote>drop in</quote> a custom scheduler
14521 with its attendant custom properties <emphasis>without</emphasis> altering
14522 the rest of your application.
14523 </para>
14524 <para>
14525 Instead of deriving a custom scheduler fiber properties subclass from <link linkend="class_fiber"><code>fiber</code></link>,
14526 you must instead derive it from <link linkend="class_fiber_properties"><code>fiber_properties</code></link>.
14527 </para>
14528 <para>
14529 <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>
14530 <phrase role="keyword">public</phrase><phrase role="special">:</phrase>
14531 <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>
14532 <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" />
14533 <phrase role="identifier">priority_</phrase><phrase role="special">(</phrase> <phrase role="number">0</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase>
14534 <phrase role="special">}</phrase>
14535
14536 <phrase role="keyword">int</phrase> <phrase role="identifier">get_priority</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase> <phrase role="special">{</phrase>
14537 <phrase role="keyword">return</phrase> <phrase role="identifier">priority_</phrase><phrase role="special">;</phrase> <co id="fiber.custom.c2" linkends="fiber.custom.c3" />
14538 <phrase role="special">}</phrase>
14539
14540 <phrase role="comment">// Call this method to alter priority, because we must notify</phrase>
14541 <phrase role="comment">// priority_scheduler of any change.</phrase>
14542 <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" />
14543 <phrase role="comment">// Of course, it's only worth reshuffling the queue and all if we're</phrase>
14544 <phrase role="comment">// actually changing the priority.</phrase>
14545 <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>
14546 <phrase role="identifier">priority_</phrase> <phrase role="special">=</phrase> <phrase role="identifier">p</phrase><phrase role="special">;</phrase>
14547 <phrase role="identifier">notify</phrase><phrase role="special">();</phrase>
14548 <phrase role="special">}</phrase>
14549 <phrase role="special">}</phrase>
14550
14551 <phrase role="comment">// The fiber name of course is solely for purposes of this example</phrase>
14552 <phrase role="comment">// program; it has nothing to do with implementing scheduler priority.</phrase>
14553 <phrase role="comment">// This is a public data member -- not requiring set/get access methods --</phrase>
14554 <phrase role="comment">// because we need not inform the scheduler of any change.</phrase>
14555 <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" />
14556 <phrase role="keyword">private</phrase><phrase role="special">:</phrase>
14557 <phrase role="keyword">int</phrase> <phrase role="identifier">priority_</phrase><phrase role="special">;</phrase>
14558 <phrase role="special">};</phrase>
14559 </programlisting>
14560 </para>
14561 <calloutlist>
14562 <callout arearefs="fiber.custom.c0" id="fiber.custom.c1">
14563 <para>
14564 Your subclass constructor must accept a <literal><link linkend="class_context"><code>context</code></link>*</literal>
14565 and pass it to the <code><phrase role="identifier">fiber_properties</phrase></code>
14566 constructor.
14567 </para>
14568 </callout>
14569 <callout arearefs="fiber.custom.c2" id="fiber.custom.c3">
14570 <para>
14571 Provide read access methods at your own discretion.
14572 </para>
14573 </callout>
14574 <callout arearefs="fiber.custom.c4" id="fiber.custom.c5">
14575 <para>
14576 It's important to call <code><phrase role="identifier">notify</phrase><phrase
14577 role="special">()</phrase></code> on any change in a property that can
14578 affect the scheduler's behavior. Therefore, such modifications should only
14579 be performed through an access method.
14580 </para>
14581 </callout>
14582 <callout arearefs="fiber.custom.c6" id="fiber.custom.c7">
14583 <para>
14584 A property that does not affect the scheduler does not need access methods.
14585 </para>
14586 </callout>
14587 </calloutlist>
14588 <bridgehead renderas="sect3" id="fiber.custom.h2">
14589 <phrase id="fiber.custom.custom_scheduler_class"/><link linkend="fiber.custom.custom_scheduler_class">Custom
14590 Scheduler Class</link>
14591 </bridgehead>
14592 <para>
14593 Now we can derive a custom scheduler from <link linkend="class_algorithm_with_properties"><code>algorithm_with_properties&lt;&gt;</code></link>,
14594 specifying our custom property class <code><phrase role="identifier">priority_props</phrase></code>
14595 as the template parameter.
14596 </para>
14597 <para>
14598 <programlisting><phrase role="keyword">class</phrase> <phrase role="identifier">priority_scheduler</phrase> <phrase role="special">:</phrase>
14599 <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>
14600 <phrase role="keyword">private</phrase><phrase role="special">:</phrase>
14601 <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_t</phrase><co id="fiber.custom.c8" linkends="fiber.custom.c9" /> <phrase role="identifier">rqueue_t</phrase><phrase role="special">;</phrase>
14602
14603 <phrase role="identifier">rqueue_t</phrase> <phrase role="identifier">rqueue_</phrase><phrase role="special">;</phrase>
14604 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">mutex</phrase> <phrase role="identifier">mtx_</phrase><phrase role="special">{};</phrase>
14605 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">condition_variable</phrase> <phrase role="identifier">cnd_</phrase><phrase role="special">{};</phrase>
14606 <phrase role="keyword">bool</phrase> <phrase role="identifier">flag_</phrase><phrase role="special">{</phrase> <phrase role="keyword">false</phrase> <phrase role="special">};</phrase>
14607
14608 <phrase role="keyword">public</phrase><phrase role="special">:</phrase>
14609 <phrase role="identifier">priority_scheduler</phrase><phrase role="special">()</phrase> <phrase role="special">:</phrase>
14610 <phrase role="identifier">rqueue_</phrase><phrase role="special">()</phrase> <phrase role="special">{</phrase>
14611 <phrase role="special">}</phrase>
14612
14613 <phrase role="comment">// For a subclass of algorithm_with_properties&lt;&gt;, it's important to</phrase>
14614 <phrase role="comment">// override the correct awakened() overload.</phrase>
14615 <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>
14616 <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" />
14617 <phrase role="comment">// With this scheduler, fibers with higher priority values are</phrase>
14618 <phrase role="comment">// preferred over fibers with lower priority values. But fibers with</phrase>
14619 <phrase role="comment">// equal priority values are processed in round-robin fashion. So when</phrase>
14620 <phrase role="comment">// we're handed a new context*, put it at the end of the fibers</phrase>
14621 <phrase role="comment">// with that same priority. In other words: search for the first fiber</phrase>
14622 <phrase role="comment">// in the queue with LOWER priority, and insert before that one.</phrase>
14623 <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>
14624 <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>
14625 <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>
14626 <phrase role="comment">// Now, whether or not we found a fiber with lower priority,</phrase>
14627 <phrase role="comment">// insert this new fiber here.</phrase>
14628 <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>
14629 <phrase role="special">}</phrase>
14630
14631 <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>
14632 <phrase role="comment">// if ready queue is empty, just tell caller</phrase>
14633 <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>
14634 <phrase role="keyword">return</phrase> <phrase role="keyword">nullptr</phrase><phrase role="special">;</phrase>
14635 <phrase role="special">}</phrase>
14636 <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>
14637 <phrase role="identifier">rqueue_</phrase><phrase role="special">.</phrase><phrase role="identifier">pop_front</phrase><phrase role="special">();</phrase>
14638 <phrase role="keyword">return</phrase> <phrase role="identifier">ctx</phrase><phrase role="special">;</phrase>
14639 <phrase role="special">}</phrase>
14640
14641 <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>
14642 <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>
14643 <phrase role="special">}</phrase>
14644
14645 <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>
14646 <phrase role="comment">// Although our priority_props class defines multiple properties, only</phrase>
14647 <phrase role="comment">// one of them (priority) actually calls notify() when changed. The</phrase>
14648 <phrase role="comment">// point of a property_change() override is to reshuffle the ready</phrase>
14649 <phrase role="comment">// queue according to the updated priority value.</phrase>
14650
14651 <phrase role="comment">// 'ctx' might not be in our queue at all, if caller is changing the</phrase>
14652 <phrase role="comment">// priority of (say) the running fiber. If it's not there, no need to</phrase>
14653 <phrase role="comment">// move it: we'll handle it next time it hits awakened().</phrase>
14654 <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" />
14655 <phrase role="keyword">return</phrase><phrase role="special">;</phrase>
14656 <phrase role="special">}</phrase>
14657
14658 <phrase role="comment">// Found ctx: unlink it</phrase>
14659 <phrase role="identifier">ctx</phrase><phrase role="special">-&gt;</phrase><phrase role="identifier">ready_unlink</phrase><phrase role="special">();</phrase>
14660
14661 <phrase role="comment">// Here we know that ctx was in our ready queue, but we've unlinked</phrase>
14662 <phrase role="comment">// it. We happen to have a method that will (re-)add a context* to the</phrase>
14663 <phrase role="comment">// right place in the ready queue.</phrase>
14664 <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>
14665 <phrase role="special">}</phrase>
14666
14667 <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>
14668 <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>
14669 <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>
14670 <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>
14671 <phrase role="identifier">flag_</phrase> <phrase role="special">=</phrase> <phrase role="keyword">false</phrase><phrase role="special">;</phrase>
14672 <phrase role="special">}</phrase> <phrase role="keyword">else</phrase> <phrase role="special">{</phrase>
14673 <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>
14674 <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>
14675 <phrase role="identifier">flag_</phrase> <phrase role="special">=</phrase> <phrase role="keyword">false</phrase><phrase role="special">;</phrase>
14676 <phrase role="special">}</phrase>
14677 <phrase role="special">}</phrase>
14678
14679 <phrase role="keyword">void</phrase> <phrase role="identifier">notify</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase> <phrase role="special">{</phrase>
14680 <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>
14681 <phrase role="identifier">flag_</phrase> <phrase role="special">=</phrase> <phrase role="keyword">true</phrase><phrase role="special">;</phrase>
14682 <phrase role="identifier">lk</phrase><phrase role="special">.</phrase><phrase role="identifier">unlock</phrase><phrase role="special">();</phrase>
14683 <phrase role="identifier">cnd_</phrase><phrase role="special">.</phrase><phrase role="identifier">notify_all</phrase><phrase role="special">();</phrase>
14684 <phrase role="special">}</phrase>
14685 <phrase role="special">};</phrase>
14686 </programlisting>
14687 </para>
14688 <calloutlist>
14689 <callout arearefs="fiber.custom.c8" id="fiber.custom.c9">
14690 <para>
14691 See <link linkend="ready_queue_t">ready_queue_t</link>.
14692 </para>
14693 </callout>
14694 <callout arearefs="fiber.custom.c10" id="fiber.custom.c11">
14695 <para>
14696 You must override the <link linkend="algorithm_with_properties_awakened"><code>algorithm_with_properties::awakened()</code></link>
14697 method.
14698 This is how your scheduler receives notification of a fiber that has become
14699 ready to run.
14700 </para>
14701 </callout>
14702 <callout arearefs="fiber.custom.c12" id="fiber.custom.c13">
14703 <para>
14704 <code><phrase role="identifier">props</phrase></code> is the instance of
14705 priority_props associated with the passed fiber <code><phrase role="identifier">ctx</phrase></code>.
14706 </para>
14707 </callout>
14708 <callout arearefs="fiber.custom.c14" id="fiber.custom.c15">
14709 <para>
14710 You must override the <link linkend="algorithm_with_properties_pick_next"><code>algorithm_with_properties::pick_next()</code></link>
14711 method.
14712 This is how your scheduler actually advises the fiber manager of the next
14713 fiber to run.
14714 </para>
14715 </callout>
14716 <callout arearefs="fiber.custom.c16" id="fiber.custom.c17">
14717 <para>
14718 You must override <link linkend="algorithm_with_properties_has_ready_fibers"><code>algorithm_with_properties::has_ready_fibers()</code></link>
14719 to
14720 inform the fiber manager of the state of your ready queue.
14721 </para>
14722 </callout>
14723 <callout arearefs="fiber.custom.c18" id="fiber.custom.c19">
14724 <para>
14725 Overriding <link linkend="algorithm_with_properties_property_change"><code>algorithm_with_properties::property_change()</code></link>
14726 is
14727 optional. This override handles the case in which the running fiber changes
14728 the priority of another ready fiber: a fiber already in our queue. In that
14729 case, move the updated fiber within the queue.
14730 </para>
14731 </callout>
14732 <callout arearefs="fiber.custom.c20" id="fiber.custom.c21">
14733 <para>
14734 Your <code><phrase role="identifier">property_change</phrase><phrase role="special">()</phrase></code>
14735 override must be able to handle the case in which the passed <code><phrase
14736 role="identifier">ctx</phrase></code> is not in your ready queue. It might
14737 be running, or it might be blocked.
14738 </para>
14739 </callout>
14740 </calloutlist>
14741 <para>
14742 Our example <code><phrase role="identifier">priority_scheduler</phrase></code>
14743 doesn't override <link linkend="algorithm_with_properties_new_properties"><code>algorithm_with_properties::new_properties()</code></link>:
14744 we're content with allocating <code><phrase role="identifier">priority_props</phrase></code>
14745 instances on the heap.
14746 </para>
14747 <bridgehead renderas="sect3" id="fiber.custom.h3">
14748 <phrase id="fiber.custom.replace_default_scheduler"/><link linkend="fiber.custom.replace_default_scheduler">Replace
14749 Default Scheduler</link>
14750 </bridgehead>
14751 <para>
14752 You must call <link linkend="use_scheduling_algorithm"><code>use_scheduling_algorithm()</code></link> at the start
14753 of each thread on which you want <emphasis role="bold">Boost.Fiber</emphasis>
14754 to use your custom scheduler rather than its own default <link linkend="class_round_robin"><code>round_robin</code></link>.
14755 Specifically, you must call <code><phrase role="identifier">use_scheduling_algorithm</phrase><phrase
14756 role="special">()</phrase></code> before performing any other <emphasis role="bold">Boost.Fiber</emphasis>
14757 operations on that thread.
14758 </para>
14759 <para>
14760 <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>
14761 <phrase role="comment">// make sure we use our priority_scheduler rather than default round_robin</phrase>
14762 <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>
14763 <phrase role="special">...</phrase>
14764 <phrase role="special">}</phrase>
14765 </programlisting>
14766 </para>
14767 <bridgehead renderas="sect3" id="fiber.custom.h4">
14768 <phrase id="fiber.custom.use_properties"/><link linkend="fiber.custom.use_properties">Use
14769 Properties</link>
14770 </bridgehead>
14771 <para>
14772 The running fiber can access its own <link linkend="class_fiber_properties"><code>fiber_properties</code></link> subclass
14773 instance by calling <link linkend="this_fiber_properties"><code>this_fiber::properties()</code></link>. Although
14774 <code><phrase role="identifier">properties</phrase><phrase role="special">&lt;&gt;()</phrase></code>
14775 is a nullary function, you must pass, as a template parameter, the <code><phrase
14776 role="identifier">fiber_properties</phrase></code> subclass.
14777 </para>
14778 <para>
14779 <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>
14780 </programlisting>
14781 </para>
14782 <para>
14783 Given a <link linkend="class_fiber"><code>fiber</code></link> instance still connected with a running fiber (that
14784 is, not <link linkend="fiber_detach"><code>fiber::detach()</code></link>ed), you may access that fiber's properties
14785 using <link linkend="fiber_properties"><code>fiber::properties()</code></link>. As with <code><phrase role="identifier">this_fiber</phrase><phrase
14786 role="special">::</phrase><phrase role="identifier">properties</phrase><phrase
14787 role="special">&lt;&gt;()</phrase></code>, you must pass your <code><phrase
14788 role="identifier">fiber_properties</phrase></code> subclass as the template
14789 parameter.
14790 </para>
14791 <para>
14792 <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>
14793 <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>
14794 <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>
14795 <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>
14796 <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>
14797 <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>
14798 <phrase role="keyword">return</phrase> <phrase role="identifier">fiber</phrase><phrase role="special">;</phrase>
14799 <phrase role="special">}</phrase>
14800 </programlisting>
14801 </para>
14802 <para>
14803 Launching a new fiber schedules that fiber as ready, but does <emphasis>not</emphasis>
14804 immediately enter its <emphasis>fiber-function</emphasis>. The current fiber
14805 retains control until it blocks (or yields, or terminates) for some other reason.
14806 As shown in the <code><phrase role="identifier">launch</phrase><phrase role="special">()</phrase></code>
14807 function above, it is reasonable to launch a fiber and immediately set relevant
14808 properties -- such as, for instance, its priority. Your custom scheduler can
14809 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>.
14810 </para>
14811 </section>
14812 <section id="fiber.rationale">
14813 <title><link linkend="fiber.rationale">Rationale</link></title>
14814 <bridgehead renderas="sect3" id="fiber.rationale.h0">
14815 <phrase id="fiber.rationale.distinction_between_coroutines_and_fibers"/><link
14816 linkend="fiber.rationale.distinction_between_coroutines_and_fibers">distinction
14817 between coroutines and fibers</link>
14818 </bridgehead>
14819 <para>
14820 The fiber library extends the coroutine library by adding a scheduler and synchronization
14821 mechanisms.
14822 </para>
14823 <itemizedlist>
14824 <listitem>
14825 <simpara>
14826 a coroutine yields
14827 </simpara>
14828 </listitem>
14829 <listitem>
14830 <simpara>
14831 a fiber blocks
14832 </simpara>
14833 </listitem>
14834 </itemizedlist>
14835 <para>
14836 When a coroutine yields, it passes control directly to its caller (or, in the
14837 case of symmetric coroutines, a designated other coroutine). When a fiber blocks,
14838 it implicitly passes control to the fiber scheduler. Coroutines have no scheduler
14839 because they need no scheduler.<footnote id="fiber.rationale.f0">
14840 <para>
14841 <ulink url="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4024.pdf">'N4024:
14842 Distinguishing coroutines and fibers'</ulink>
14843 </para>
14844 </footnote>.
14845 </para>
14846 <bridgehead renderas="sect3" id="fiber.rationale.h1">
14847 <phrase id="fiber.rationale.what_about_transactional_memory"/><link linkend="fiber.rationale.what_about_transactional_memory">what
14848 about transactional memory</link>
14849 </bridgehead>
14850 <para>
14851 GCC supports transactional memory since version 4.7. Unfortunately tests show
14852 that transactional memory is slower (ca. 4x) than spinlocks using atomics.
14853 Once transactional memory is improved (supporting hybrid tm), spinlocks will
14854 be replaced by __transaction_atomic{} statements surrounding the critical sections.
14855 </para>
14856 <bridgehead renderas="sect3" id="fiber.rationale.h2">
14857 <phrase id="fiber.rationale.synchronization_between_fibers_running_in_different_threads"/><link
14858 linkend="fiber.rationale.synchronization_between_fibers_running_in_different_threads">synchronization
14859 between fibers running in different threads</link>
14860 </bridgehead>
14861 <para>
14862 Synchronization classes from <ulink url="http://www.boost.org/doc/libs/release/libs/thread/index.html">Boost.Thread</ulink>
14863 block the entire thread. In contrast, the synchronization classes from <emphasis
14864 role="bold">Boost.Fiber</emphasis> block only specific fibers, so that the
14865 scheduler can still keep the thread busy running other fibers in the meantime.
14866 The synchronization classes from <emphasis role="bold">Boost.Fiber</emphasis>
14867 are designed to be thread-safe, i.e. it is possible to synchronize fibers running
14868 in different threads as well as fibers running in the same thread. (However,
14869 there is a build option to disable cross-thread fiber synchronization support;
14870 see <link linkend="cross_thread_sync">this description</link>.)
14871 </para>
14872 <anchor id="spurious_wakeup"/>
14873 <bridgehead renderas="sect3" id="fiber.rationale.h3">
14874 <phrase id="fiber.rationale.spurious_wakeup"/><link linkend="fiber.rationale.spurious_wakeup">spurious
14875 wakeup</link>
14876 </bridgehead>
14877 <para>
14878 Spurious wakeup can happen when using <ulink url="http://en.cppreference.com/w/cpp/thread/condition_variable"><code><phrase
14879 role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">condition_variable</phrase></code></ulink>:
14880 the condition variable appears to be have been signaled while the awaited condition
14881 may still be false. Spurious wakeup can happen repeatedly and is caused on
14882 some multiprocessor systems where making <code><phrase role="identifier">std</phrase><phrase
14883 role="special">::</phrase><phrase role="identifier">condition_variable</phrase></code>
14884 wakeup completely predictable would slow down all <code><phrase role="identifier">std</phrase><phrase
14885 role="special">::</phrase><phrase role="identifier">condition_variable</phrase></code>
14886 operations.<footnote id="fiber.rationale.f1">
14887 <para>
14888 David R. Butenhof <quote>Programming with POSIX Threads</quote>
14889 </para>
14890 </footnote>
14891 </para>
14892 <para>
14893 <link linkend="class_condition_variable"><code>condition_variable</code></link> is not subject to spurious wakeup.
14894 Nonetheless it is prudent to test the business-logic condition in a <code><phrase
14895 role="identifier">wait</phrase><phrase role="special">()</phrase></code> loop
14896 &mdash; or, equivalently, use one of the <code><phrase role="identifier">wait</phrase><phrase
14897 role="special">(</phrase> <phrase role="identifier">lock</phrase><phrase role="special">,</phrase>
14898 <phrase role="identifier">predicate</phrase> <phrase role="special">)</phrase></code>
14899 overloads.
14900 </para>
14901 <para>
14902 See also <link linkend="condition_variable_spurious_wakeups">No Spurious Wakeups</link>.
14903 </para>
14904 <bridgehead renderas="sect3" id="fiber.rationale.h4">
14905 <phrase id="fiber.rationale.migrating_fibers_between_threads"/><link linkend="fiber.rationale.migrating_fibers_between_threads">migrating
14906 fibers between threads</link>
14907 </bridgehead>
14908 <para>
14909 Support for migrating fibers between threads has been integrated. The user-defined
14910 scheduler must call <link linkend="context_detach"><code>context::detach()</code></link> on a fiber-context on the
14911 source thread and <link linkend="context_attach"><code>context::attach()</code></link> on the destination thread,
14912 passing the fiber-context to migrate. (For more information about custom schedulers,
14913 see <link linkend="custom">Customization</link>.) Examples <code><phrase role="identifier">work_sharing</phrase></code>
14914 and <code><phrase role="identifier">work_stealing</phrase></code> in directory
14915 <code><phrase role="identifier">examples</phrase></code> might be used as a
14916 blueprint.
14917 </para>
14918 <para>
14919 See also <link linkend="migration">Migrating fibers between threads</link>.
14920 </para>
14921 <bridgehead renderas="sect3" id="fiber.rationale.h5">
14922 <phrase id="fiber.rationale.support_for_boost_asio"/><link linkend="fiber.rationale.support_for_boost_asio">support
14923 for Boost.Asio</link>
14924 </bridgehead>
14925 <para>
14926 Support for <ulink url="http://www.boost.org/doc/libs/release/libs/asio/index.html">Boost.Asio</ulink>&#8217;s
14927 <emphasis>async-result</emphasis> is not part of the official API. However,
14928 to integrate with a <ulink url="http://www.boost.org/doc/libs/release/doc/html/boost_asio/reference/io_service.html"><code><phrase
14929 role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">asio</phrase><phrase
14930 role="special">::</phrase><phrase role="identifier">io_service</phrase></code></ulink>,
14931 see <link linkend="integration">Sharing a Thread with Another Main Loop</link>.
14932 To interface smoothly with an arbitrary Asio async I/O operation, see <link
14933 linkend="callbacks_asio">Then There&#8217;s <ulink url="http://www.boost.org/doc/libs/release/libs/asio/index.html">Boost.Asio</ulink></link>.
14934 </para>
14935 <bridgehead renderas="sect3" id="fiber.rationale.h6">
14936 <phrase id="fiber.rationale.tested_compilers"/><link linkend="fiber.rationale.tested_compilers">tested
14937 compilers</link>
14938 </bridgehead>
14939 <para>
14940 The library was tested with GCC-5.1.1, Clang-3.6.0 and MSVC-14.0 in c++11-mode.
14941 </para>
14942 <bridgehead renderas="sect3" id="fiber.rationale.h7">
14943 <phrase id="fiber.rationale.supported_architectures"/><link linkend="fiber.rationale.supported_architectures">supported
14944 architectures</link>
14945 </bridgehead>
14946 <para>
14947 <emphasis role="bold">Boost.Fiber</emphasis> depends on <ulink url="http://www.boost.org/doc/libs/release/libs/context/index.html">Boost.Context</ulink>
14948 - 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>.
14949 </para>
14950 </section>
14951 <section id="fiber.acknowledgements">
14952 <title><link linkend="fiber.acknowledgements">Acknowledgments</link></title>
14953 <para>
14954 I'd like to thank Agustín Bergé, Eugene Yakubovich, Giovanni Piero Deretta
14955 and especially Nat Goodspeed.
14956 </para>
14957 </section>
14958 <section id="fiber.installing">
14959 <title><link linkend="fiber.installing">Appendix: Installing and Running Tests</link></title>
14960 <bridgehead renderas="sect3" id="fiber.installing.h0">
14961 <phrase id="fiber.installing.installing_the_fiber_library"/><link linkend="fiber.installing.installing_the_fiber_library">Installing
14962 the Fiber library</link>
14963 </bridgehead>
14964 <para>
14965 As Fiber is not yet officially part of Boost, it is necessary to embed it in
14966 an existing <ulink url="http://www.boost.org/users/download/">Boost source
14967 tree</ulink>.
14968 </para>
14969 <para>
14970 The <ulink url="https://github.com/olk/boost-fiber/archive/master.zip">downloaded
14971 Fiber library</ulink> can be placed into an existing Boost source tree by moving
14972 the top-level Fiber directory to <code><phrase role="identifier">libs</phrase><phrase
14973 role="special">/</phrase><phrase role="identifier">fiber</phrase></code> under
14974 the top-level Boost directory, then further moving <code><phrase role="identifier">libs</phrase><phrase
14975 role="special">/</phrase><phrase role="identifier">fiber</phrase><phrase role="special">/</phrase><phrase
14976 role="identifier">include</phrase><phrase role="special">/</phrase><phrase
14977 role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">fiber</phrase></code>
14978 (in other words, the Fiber library's <code><phrase role="identifier">include</phrase><phrase
14979 role="special">/</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase
14980 role="identifier">fiber</phrase></code> directory) to <code><phrase role="identifier">boost</phrase><phrase
14981 role="special">/</phrase><phrase role="identifier">fiber</phrase></code> under
14982 the top-level Boost directory.
14983 </para>
14984 <para>
14985 On a Posix system such as Linux or OS X, you may use symlinks instead.
14986 </para>
14987 <para>
14988 Create a symlink from the Boost directory's <code><phrase role="identifier">libs</phrase><phrase
14989 role="special">/</phrase><phrase role="identifier">fiber</phrase></code> to
14990 the top-level Fiber directory, e.g.:
14991 </para>
14992 <programlisting><phrase role="identifier">cd</phrase> <phrase role="special">~/</phrase><phrase role="identifier">boost_1_61_0</phrase>
14993 <phrase role="identifier">ln</phrase> <phrase role="special">-</phrase><phrase role="identifier">s</phrase> <phrase role="special">~/</phrase><phrase role="identifier">boost</phrase><phrase role="special">-</phrase><phrase role="identifier">fiber</phrase><phrase role="special">-</phrase><phrase role="identifier">master</phrase> <phrase role="identifier">libs</phrase><phrase role="special">/</phrase><phrase role="identifier">fiber</phrase>
14994 </programlisting>
14995 <para>
14996 Then create a symlink from the Boost directory's <code><phrase role="identifier">boost</phrase><phrase
14997 role="special">/</phrase><phrase role="identifier">fiber</phrase></code> to
14998 the Fiber library's <code><phrase role="identifier">include</phrase><phrase
14999 role="special">/</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase
15000 role="identifier">fiber</phrase></code> directory:
15001 </para>
15002 <programlisting><phrase role="identifier">cd</phrase> <phrase role="identifier">boost</phrase>
15003 <phrase role="identifier">ln</phrase> <phrase role="special">-</phrase><phrase role="identifier">s</phrase> <phrase role="special">../</phrase><phrase role="identifier">libs</phrase><phrase role="special">/</phrase><phrase role="identifier">fiber</phrase><phrase role="special">/</phrase><phrase role="identifier">include</phrase><phrase role="special">/</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">fiber</phrase> <phrase role="identifier">fiber</phrase>
15004 </programlisting>
15005 <para>
15006 For some versions of the Boost.Build system, it was important to use a relative
15007 symlink of that form for <code><phrase role="identifier">boost</phrase><phrase
15008 role="special">/</phrase><phrase role="identifier">fiber</phrase></code>.
15009 </para>
15010 <anchor id="tests"/>
15011 <bridgehead renderas="sect3" id="fiber.installing.h1">
15012 <phrase id="fiber.installing.running_tests"/><link linkend="fiber.installing.running_tests">Running
15013 Tests</link>
15014 </bridgehead>
15015 <para>
15016 Once the Fiber library has been overlaid (or symlinked) into the Boost source
15017 tree this way, the Boost.Build system can build it like any other Boost library.
15018 In particular:
15019 </para>
15020 <programlisting><phrase role="identifier">cd</phrase> <phrase role="special">~/</phrase><phrase role="identifier">boost_1_61_0</phrase>
15021 <phrase role="special">./</phrase><phrase role="identifier">bootstrap</phrase><phrase role="special">.</phrase><phrase role="identifier">sh</phrase>
15022 <phrase role="special">./</phrase><phrase role="identifier">b2</phrase> <phrase role="identifier">libs</phrase><phrase role="special">/</phrase><phrase role="identifier">fiber</phrase><phrase role="special">/</phrase><phrase role="identifier">test</phrase>
15023 </programlisting>
15024 <para>
15025 On Windows, the commands would look more like:
15026 </para>
15027 <programlisting><phrase role="identifier">cd</phrase> <phrase role="special">/</phrase><phrase role="identifier">D</phrase> <phrase role="special">%</phrase><phrase role="identifier">HOMEDRIVE</phrase><phrase role="special">%%</phrase><phrase role="identifier">HOMEPATH</phrase><phrase role="special">%\</phrase><phrase role="identifier">boost_1_61_0</phrase>
15028 <phrase role="identifier">bootstrap</phrase>
15029 <phrase role="identifier">b2</phrase> <phrase role="identifier">libs</phrase><phrase role="special">\</phrase><phrase role="identifier">fiber</phrase><phrase role="special">\</phrase><phrase role="identifier">test</phrase>
15030 </programlisting>
15031 </section>
15032 </library>