1<?xml version="1.0" encoding="UTF-8"?> 2<!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd"> 3<library id="fiber" name="Fiber" dirname="fiber" last-revision="$Date: 2018/10/22 08:13:04 $" 4 xmlns:xi="http://www.w3.org/2001/XInclude"> 5 <libraryinfo> 6 <authorgroup> 7 <author> 8 <firstname>Oliver</firstname> <surname>Kowalke</surname> 9 </author> 10 </authorgroup> 11 <copyright> 12 <year>2013</year> <holder>Oliver Kowalke</holder> 13 </copyright> 14 <legalnotice id="fiber.legal"> 15 <para> 16 Distributed under the Boost Software License, Version 1.0. (See accompanying 17 file LICENSE_1_0.txt or copy at <ulink url="http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</ulink>) 18 </para> 19 </legalnotice> 20 <librarypurpose> 21 C++ Library to cooperatively schedule and synchronize micro-threads 22 </librarypurpose> 23 <librarycategory name="category:text"></librarycategory> 24 </libraryinfo> 25 <title>Fiber</title> 26 <section id="fiber.overview"> 27 <title><link linkend="fiber.overview">Overview</link></title> 28 <para> 29 <emphasis role="bold">Boost.Fiber</emphasis> provides a framework for micro-/userland-threads 30 (fibers) scheduled cooperatively. The API contains classes and functions to 31 manage and synchronize fibers similiarly to <ulink url="http://en.cppreference.com/w/cpp/thread">standard 32 thread support library</ulink>. 33 </para> 34 <para> 35 Each fiber has its own stack. 36 </para> 37 <para> 38 A fiber can save the current execution state, including all registers and CPU 39 flags, the instruction pointer, and the stack pointer and later restore this 40 state. The idea is to have multiple execution paths running on a single thread 41 using cooperative scheduling (versus threads, which are preemptively scheduled). 42 The running fiber decides explicitly when it should yield to allow another 43 fiber to run (context switching). <emphasis role="bold">Boost.Fiber</emphasis> 44 internally uses <ulink url="http://www.boost.org/doc/libs/release/libs/context/doc/html/context/cc.html"><emphasis>call/cc</emphasis></ulink> 45 from <ulink url="http://www.boost.org/doc/libs/release/libs/context/index.html">Boost.Context</ulink>; 46 the classes in this library manage, schedule and, when needed, synchronize 47 those execution contexts. A context switch between threads usually costs thousands 48 of CPU cycles on x86, compared to a fiber switch with less than a hundred cycles. 49 A fiber runs on a single thread at any point in time. 50 </para> 51 <para> 52 In order to use the classes and functions described here, you can either include 53 the specific headers specified by the descriptions of each class or function, 54 or include the master library header: 55 </para> 56<programlisting><phrase role="preprocessor">#include</phrase> <phrase role="special"><</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">></phrase> 57</programlisting> 58 <para> 59 which includes all the other headers in turn. 60 </para> 61 <para> 62 The namespaces used are: 63 </para> 64<programlisting><phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase> 65<phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">this_fiber</phrase> 66</programlisting> 67 <bridgehead renderas="sect3" id="fiber.overview.h0"> 68 <phrase id="fiber.overview.fibers_and_threads"/><link linkend="fiber.overview.fibers_and_threads">Fibers 69 and Threads</link> 70 </bridgehead> 71 <para> 72 Control is cooperatively passed between fibers launched on a given thread. 73 At a given moment, on a given thread, at most one fiber is running. 74 </para> 75 <para> 76 Spawning additional fibers on a given thread does not distribute your program 77 across more hardware cores, though it can make more effective use of the core 78 on which it's running. 79 </para> 80 <para> 81 On the other hand, a fiber may safely access any resource exclusively owned 82 by its parent thread without explicitly needing to defend that resource against 83 concurrent access by other fibers on the same thread. You are already guaranteed 84 that no other fiber on that thread is concurrently touching that resource. 85 This can be particularly important when introducing concurrency in legacy code. 86 You can safely spawn fibers running old code, using asynchronous I/O to interleave 87 execution. 88 </para> 89 <para> 90 In effect, fibers provide a natural way to organize concurrent code based on 91 asynchronous I/O. Instead of chaining together completion handlers, code running 92 on a fiber can make what looks like a normal blocking function call. That call 93 can cheaply suspend the calling fiber, allowing other fibers on the same thread 94 to run. When the operation has completed, the suspended fiber resumes, without 95 having to explicitly save or restore its state. Its local stack variables persist 96 across the call. 97 </para> 98 <para> 99 A fiber can be migrated from one thread to another, though the library does 100 not do this by default. It is possible for you to supply a custom scheduler 101 that migrates fibers between threads. You may specify custom fiber properties 102 to help your scheduler decide which fibers are permitted to migrate. Please 103 see <link linkend="migration">Migrating fibers between threads</link> and 104 <link linkend="custom">Customization</link> for more details. 105 </para> 106 <para> 107 <emphasis role="bold">Boost.Fiber</emphasis> allows to <emphasis role="bold"><code><phrase 108 role="identifier">multiplex</phrase> <phrase role="identifier">fibers</phrase> 109 <phrase role="identifier">across</phrase> <phrase role="identifier">multiple</phrase> 110 <phrase role="identifier">cores</phrase></code></emphasis> (see <link linkend="class_numa_work_stealing"><code>numa::work_stealing</code></link>). 111 </para> 112 <para> 113 A fiber launched on a particular thread continues running on that thread unless 114 migrated. It might be unblocked (see <link linkend="blocking">Blocking</link> 115 below) by some other thread, but that only transitions the fiber from <quote>blocked</quote> 116 to <quote>ready</quote> on its current thread — it does not cause the fiber to 117 resume on the thread that unblocked it. 118 </para> 119 <anchor id="thread_local_storage"/> 120 <bridgehead renderas="sect3" id="fiber.overview.h1"> 121 <phrase id="fiber.overview.thread_local_storage"/><link linkend="fiber.overview.thread_local_storage">thread-local 122 storage</link> 123 </bridgehead> 124 <para> 125 Unless migrated, a fiber may access thread-local storage; however that storage 126 will be shared among all fibers running on the same thread. For fiber-local 127 storage, please see <link linkend="class_fiber_specific_ptr"><code>fiber_specific_ptr</code></link>. 128 </para> 129 <anchor id="cross_thread_sync"/> 130 <bridgehead renderas="sect3" id="fiber.overview.h2"> 131 <phrase id="fiber.overview.boost_fibers_no_atomics"/><link linkend="fiber.overview.boost_fibers_no_atomics">BOOST_FIBERS_NO_ATOMICS</link> 132 </bridgehead> 133 <para> 134 The fiber synchronization objects provided by this library will, by default, 135 safely synchronize fibers running on different threads. However, this level 136 of synchronization can be removed (for performance) by building the library 137 with <emphasis role="bold"><code><phrase role="identifier">BOOST_FIBERS_NO_ATOMICS</phrase></code></emphasis> 138 defined. When the library is built with that macro, you must ensure that all 139 the fibers referencing a particular synchronization object are running in the 140 same thread. Please see <link linkend="synchronization">Synchronization</link>. 141 </para> 142 <anchor id="blocking"/> 143 <bridgehead renderas="sect3" id="fiber.overview.h3"> 144 <phrase id="fiber.overview.blocking"/><link linkend="fiber.overview.blocking">Blocking</link> 145 </bridgehead> 146 <para> 147 Normally, when this documentation states that a particular fiber <emphasis>blocks</emphasis> 148 (or equivalently, <emphasis>suspends),</emphasis> it means that it yields control, 149 allowing other fibers on the same thread to run. The synchronization mechanisms 150 provided by <emphasis role="bold">Boost.Fiber</emphasis> have this behavior. 151 </para> 152 <para> 153 A fiber may, of course, use normal thread synchronization mechanisms; however 154 a fiber that invokes any of these mechanisms will block its entire thread, 155 preventing any other fiber from running on that thread in the meantime. For 156 instance, when a fiber wants to wait for a value from another fiber in the 157 same thread, using <code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase 158 role="identifier">future</phrase></code> would be unfortunate: <code><phrase 159 role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">future</phrase><phrase 160 role="special">::</phrase><phrase role="identifier">get</phrase><phrase role="special">()</phrase></code> 161 would block the whole thread, preventing the other fiber from delivering its 162 value. Use <link linkend="class_future"><code>future<></code></link> instead. 163 </para> 164 <para> 165 Similarly, a fiber that invokes a normal blocking I/O operation will block 166 its entire thread. Fiber authors are encouraged to consistently use asynchronous 167 I/O. <ulink url="http://www.boost.org/doc/libs/release/libs/asio/index.html">Boost.Asio</ulink> 168 and other asynchronous I/O operations can straightforwardly be adapted for 169 <emphasis role="bold">Boost.Fiber</emphasis>: see <link linkend="callbacks">Integrating 170 Fibers with Asynchronous Callbacks</link>. 171 </para> 172 <para> 173 <emphasis role="bold">Boost.Fiber</emphasis> depends upon <ulink url="http://www.boost.org/doc/libs/release/libs/context/index.html">Boost.Context</ulink>. 174 Boost version 1.61.0 or greater is required. 175 </para> 176 <note> 177 <para> 178 This library requires C++11! 179 </para> 180 </note> 181 <section id="fiber.overview.implementations__fcontext_t__ucontext_t_and_winfiber"> 182 <title><anchor id="implementation"/><link linkend="fiber.overview.implementations__fcontext_t__ucontext_t_and_winfiber">Implementations: 183 fcontext_t, ucontext_t and WinFiber</link></title> 184 <para> 185 <emphasis role="bold">Boost.Fiber</emphasis> uses <ulink url="http://www.boost.org/doc/libs/release/libs/context/doc/html/context/cc.html"><emphasis>call/cc</emphasis></ulink> 186 from <ulink url="http://www.boost.org/doc/libs/release/libs/context/index.html">Boost.Context</ulink> 187 as building-block. 188 </para> 189 <bridgehead renderas="sect4" id="fiber.overview.implementations__fcontext_t__ucontext_t_and_winfiber.h0"> 190 <phrase id="fiber.overview.implementations__fcontext_t__ucontext_t_and_winfiber.fcontext_t"/><link 191 linkend="fiber.overview.implementations__fcontext_t__ucontext_t_and_winfiber.fcontext_t">fcontext_t</link> 192 </bridgehead> 193 <para> 194 The implementation uses <code><phrase role="identifier">fcontext_t</phrase></code> 195 per default. fcontext_t is based on assembler and not available for all platforms. 196 It provides a much better performance than <code><phrase role="identifier">ucontext_t</phrase></code> 197 (the context switch takes two magnitudes of order less CPU cycles; see section 198 <ulink url="http://www.boost.org/doc/libs/release/libs/context/doc/html/context/performance.html"><emphasis>performance</emphasis></ulink>) 199 and <code><phrase role="identifier">WinFiber</phrase></code>. 200 </para> 201 <bridgehead renderas="sect4" id="fiber.overview.implementations__fcontext_t__ucontext_t_and_winfiber.h1"> 202 <phrase id="fiber.overview.implementations__fcontext_t__ucontext_t_and_winfiber.ucontext_t"/><link 203 linkend="fiber.overview.implementations__fcontext_t__ucontext_t_and_winfiber.ucontext_t">ucontext_t</link> 204 </bridgehead> 205 <para> 206 As an alternative, <ulink url="https://en.wikipedia.org/wiki/Setcontext"><code><phrase 207 role="identifier">ucontext_t</phrase></code></ulink> can be used by compiling 208 with <code><phrase role="identifier">BOOST_USE_UCONTEXT</phrase></code> and 209 b2 property <code><phrase role="identifier">context</phrase><phrase role="special">-</phrase><phrase 210 role="identifier">impl</phrase><phrase role="special">=</phrase><phrase role="identifier">ucontext</phrase></code>. 211 <code><phrase role="identifier">ucontext_t</phrase></code> might be available 212 on a broader range of POSIX-platforms but has some <ulink url="http://www.boost.org/doc/libs/release/libs/context/doc/html/context/rational.html#ucontext"><emphasis>disadvantages</emphasis></ulink> 213 (for instance deprecated since POSIX.1-2003, not C99 conform). 214 </para> 215 <note> 216 <para> 217 <ulink url="http://www.boost.org/doc/libs/release/libs/context/doc/html/context/cc.html"><emphasis>call/cc</emphasis></ulink> 218 supports <link linkend="segmented"><emphasis>Segmented stacks</emphasis></link> 219 only with <code><phrase role="identifier">ucontext_t</phrase></code> as 220 its implementation. 221 </para> 222 </note> 223 <bridgehead renderas="sect4" id="fiber.overview.implementations__fcontext_t__ucontext_t_and_winfiber.h2"> 224 <phrase id="fiber.overview.implementations__fcontext_t__ucontext_t_and_winfiber.winfiber"/><link 225 linkend="fiber.overview.implementations__fcontext_t__ucontext_t_and_winfiber.winfiber">WinFiber</link> 226 </bridgehead> 227 <para> 228 With <code><phrase role="identifier">BOOST_USE_WINFIB</phrase></code> and 229 b2 property <code><phrase role="identifier">context</phrase><phrase role="special">-</phrase><phrase 230 role="identifier">impl</phrase><phrase role="special">=</phrase><phrase role="identifier">winfib</phrase></code> 231 Win32-Fibers are used as implementation for <ulink url="http://www.boost.org/doc/libs/release/libs/context/doc/html/context/cc.html"><emphasis>call/cc</emphasis></ulink>. 232 </para> 233 <para> 234 Because the TIB (thread information block) is not fully described in the 235 MSDN, it might be possible that not all required TIB-parts are swapped. 236 </para> 237 <note> 238 <para> 239 The first call of <ulink url="http://www.boost.org/doc/libs/release/libs/context/doc/html/context/cc.html"><emphasis>call/cc</emphasis></ulink> 240 converts the thread into a Windows fiber by invoking <code><phrase role="identifier">ConvertThreadToFiber</phrase><phrase 241 role="special">()</phrase></code>. If desired, <code><phrase role="identifier">ConvertFiberToThread</phrase><phrase 242 role="special">()</phrase></code> has to be called by the user explicitly 243 in order to release resources allocated by <code><phrase role="identifier">ConvertThreadToFiber</phrase><phrase 244 role="special">()</phrase></code> (e.g. after using boost.context). 245 </para> 246 </note> 247 </section> 248 <important> 249 <para> 250 Windows using fcontext_t: turn off global program optimization (/GL) and 251 change /EHsc (compiler assumes that functions declared as extern "C" 252 never throw a C++ exception) to /EHs (tells compiler assumes that functions 253 declared as extern "C" may throw an exception). 254 </para> 255 </important> 256 </section> 257 <section id="fiber.fiber_mgmt"> 258 <title><link linkend="fiber.fiber_mgmt">Fiber management</link></title> 259 <bridgehead renderas="sect3" id="fiber.fiber_mgmt.h0"> 260 <phrase id="fiber.fiber_mgmt.synopsis"/><link linkend="fiber.fiber_mgmt.synopsis">Synopsis</link> 261 </bridgehead> 262<programlisting><phrase role="preprocessor">#include</phrase> <phrase role="special"><</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">></phrase> 263 264<phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase> 265<phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase> 266 267<phrase role="keyword">class</phrase> <phrase role="identifier">fiber</phrase><phrase role="special">;</phrase> 268<phrase role="keyword">bool</phrase> <phrase role="keyword">operator</phrase><phrase role="special"><(</phrase> <phrase role="identifier">fiber</phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">l</phrase><phrase role="special">,</phrase> <phrase role="identifier">fiber</phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">r</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 269<phrase role="keyword">void</phrase> <phrase role="identifier">swap</phrase><phrase role="special">(</phrase> <phrase role="identifier">fiber</phrase> <phrase role="special">&</phrase> <phrase role="identifier">l</phrase><phrase role="special">,</phrase> <phrase role="identifier">fiber</phrase> <phrase role="special">&</phrase> <phrase role="identifier">r</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 270 271<phrase role="keyword">template</phrase><phrase role="special"><</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">></phrase> 272<phrase role="keyword">void</phrase> <phrase role="identifier">use_scheduling_algorithm</phrase><phrase role="special">(</phrase> <phrase role="identifier">Args</phrase> <phrase role="special">&&</phrase> <phrase role="special">...</phrase> <phrase role="identifier">args</phrase><phrase role="special">);</phrase> 273<phrase role="keyword">bool</phrase> <phrase role="identifier">has_ready_fibers</phrase><phrase role="special">();</phrase> 274 275<phrase role="keyword">namespace</phrase> <phrase role="identifier">algo</phrase> <phrase role="special">{</phrase> 276 277<phrase role="keyword">struct</phrase> <phrase role="identifier">algorithm</phrase><phrase role="special">;</phrase> 278<phrase role="keyword">template</phrase><phrase role="special"><</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">PROPS</phrase> <phrase role="special">></phrase> 279<phrase role="keyword">struct</phrase> <phrase role="identifier">algorithm_with_properties</phrase><phrase role="special">;</phrase> 280<phrase role="keyword">class</phrase> <phrase role="identifier">round_robin</phrase><phrase role="special">;</phrase> 281<phrase role="keyword">class</phrase> <phrase role="identifier">shared_round_robin</phrase><phrase role="special">;</phrase> 282 283<phrase role="special">}}</phrase> 284 285<phrase role="keyword">namespace</phrase> <phrase role="identifier">this_fiber</phrase> <phrase role="special">{</phrase> 286 287<phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">id</phrase> <phrase role="identifier">get_id</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 288<phrase role="keyword">void</phrase> <phrase role="identifier">yield</phrase><phrase role="special">();</phrase> 289<phrase role="keyword">template</phrase><phrase role="special"><</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Clock</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Duration</phrase> <phrase role="special">></phrase> 290<phrase role="keyword">void</phrase> <phrase role="identifier">sleep_until</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">time_point</phrase><phrase role="special"><</phrase> <phrase role="identifier">Clock</phrase><phrase role="special">,</phrase> <phrase role="identifier">Duration</phrase> <phrase role="special">></phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">abs_time</phrase><phrase role="special">)</phrase> 291<phrase role="keyword">template</phrase><phrase role="special"><</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Rep</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Period</phrase> <phrase role="special">></phrase> 292<phrase role="keyword">void</phrase> <phrase role="identifier">sleep_for</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">duration</phrase><phrase role="special"><</phrase> <phrase role="identifier">Rep</phrase><phrase role="special">,</phrase> <phrase role="identifier">Period</phrase> <phrase role="special">></phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">rel_time</phrase><phrase role="special">);</phrase> 293<phrase role="keyword">template</phrase><phrase role="special"><</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">PROPS</phrase> <phrase role="special">></phrase> 294<phrase role="identifier">PROPS</phrase> <phrase role="special">&</phrase> <phrase role="identifier">properties</phrase><phrase role="special">();</phrase> 295 296<phrase role="special">}</phrase> 297</programlisting> 298 <bridgehead renderas="sect3" id="fiber.fiber_mgmt.h1"> 299 <phrase id="fiber.fiber_mgmt.tutorial"/><link linkend="fiber.fiber_mgmt.tutorial">Tutorial</link> 300 </bridgehead> 301 <para> 302 Each <link linkend="class_fiber"><code>fiber</code></link> represents a micro-thread which will be launched and managed 303 cooperatively by a scheduler. Objects of type <link linkend="class_fiber"><code>fiber</code></link> are move-only. 304 </para> 305<programlisting><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">fiber</phrase> <phrase role="identifier">f1</phrase><phrase role="special">;</phrase> <phrase role="comment">// not-a-fiber</phrase> 306 307<phrase role="keyword">void</phrase> <phrase role="identifier">f</phrase><phrase role="special">()</phrase> <phrase role="special">{</phrase> 308 <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">fiber</phrase> <phrase role="identifier">f2</phrase><phrase role="special">(</phrase> <phrase role="identifier">some_fn</phrase><phrase role="special">);</phrase> 309 310 <phrase role="identifier">f1</phrase> <phrase role="special">=</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">move</phrase><phrase role="special">(</phrase> <phrase role="identifier">f2</phrase><phrase role="special">);</phrase> <phrase role="comment">// f2 moved to f1</phrase> 311<phrase role="special">}</phrase> 312</programlisting> 313 <bridgehead renderas="sect3" id="fiber.fiber_mgmt.h2"> 314 <phrase id="fiber.fiber_mgmt.launching"/><link linkend="fiber.fiber_mgmt.launching">Launching</link> 315 </bridgehead> 316 <para> 317 A new fiber is launched by passing an object of a callable type that can be 318 invoked with no parameters. If the object must not be copied or moved, then 319 <emphasis>std::ref</emphasis> can be used to pass in a reference to the function 320 object. In this case, the user must ensure that the referenced object outlives 321 the newly-created fiber. 322 </para> 323<programlisting><phrase role="keyword">struct</phrase> <phrase role="identifier">callable</phrase> <phrase role="special">{</phrase> 324 <phrase role="keyword">void</phrase> <phrase role="keyword">operator</phrase><phrase role="special">()();</phrase> 325<phrase role="special">};</phrase> 326 327<phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">fiber</phrase> <phrase role="identifier">copies_are_safe</phrase><phrase role="special">()</phrase> <phrase role="special">{</phrase> 328 <phrase role="identifier">callable</phrase> <phrase role="identifier">x</phrase><phrase role="special">;</phrase> 329 <phrase role="keyword">return</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">fiber</phrase><phrase role="special">(</phrase> <phrase role="identifier">x</phrase><phrase role="special">);</phrase> 330<phrase role="special">}</phrase> <phrase role="comment">// x is destroyed, but the newly-created fiber has a copy, so this is OK</phrase> 331 332<phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">fiber</phrase> <phrase role="identifier">oops</phrase><phrase role="special">()</phrase> <phrase role="special">{</phrase> 333 <phrase role="identifier">callable</phrase> <phrase role="identifier">x</phrase><phrase role="special">;</phrase> 334 <phrase role="keyword">return</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">fiber</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">ref</phrase><phrase role="special">(</phrase> <phrase role="identifier">x</phrase><phrase role="special">)</phrase> <phrase role="special">);</phrase> 335<phrase role="special">}</phrase> <phrase role="comment">// x is destroyed, but the newly-created fiber still has a reference</phrase> 336 <phrase role="comment">// this leads to undefined behaviour</phrase> 337</programlisting> 338 <para> 339 The spawned <link linkend="class_fiber"><code>fiber</code></link> does not immediately start running. It is enqueued 340 in the list of ready-to-run fibers, and will run when the scheduler gets around 341 to it. 342 </para> 343 <anchor id="exceptions"/> 344 <bridgehead renderas="sect3" id="fiber.fiber_mgmt.h3"> 345 <phrase id="fiber.fiber_mgmt.exceptions"/><link linkend="fiber.fiber_mgmt.exceptions">Exceptions</link> 346 </bridgehead> 347 <para> 348 An exception escaping from the function or callable object passed to the <link linkend="class_fiber"><code>fiber</code></link> 349constructor 350 calls <code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase 351 role="identifier">terminate</phrase><phrase role="special">()</phrase></code>. 352 If you need to know which exception was thrown, use <link linkend="class_future"><code>future<></code></link> or 353 <link linkend="class_packaged_task"><code>packaged_task<></code></link>. 354 </para> 355 <bridgehead renderas="sect3" id="fiber.fiber_mgmt.h4"> 356 <phrase id="fiber.fiber_mgmt.detaching"/><link linkend="fiber.fiber_mgmt.detaching">Detaching</link> 357 </bridgehead> 358 <para> 359 A <link linkend="class_fiber"><code>fiber</code></link> can be detached by explicitly invoking the <link linkend="fiber_detach"><code>fiber::detach()</code></link> member 360 function. After <link linkend="fiber_detach"><code>fiber::detach()</code></link> is called on a fiber object, that 361 object represents <emphasis>not-a-fiber</emphasis>. The fiber object may then 362 safely be destroyed. 363 </para> 364<programlisting><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">fiber</phrase><phrase role="special">(</phrase> <phrase role="identifier">some_fn</phrase><phrase role="special">).</phrase><phrase role="identifier">detach</phrase><phrase role="special">();</phrase> 365</programlisting> 366 <para> 367 <emphasis role="bold">Boost.Fiber</emphasis> provides a number of ways to wait 368 for a running fiber to complete. You can coordinate even with a detached fiber 369 using a <link linkend="class_mutex"><code>mutex</code></link>, or <link linkend="class_condition_variable"><code>condition_variable</code></link>, or 370 any of the other <link linkend="synchronization">synchronization objects</link> 371 provided by the library. 372 </para> 373 <para> 374 If a detached fiber is still running when the thread’s main fiber terminates, 375 the thread will not shut down. 376 </para> 377 <bridgehead renderas="sect3" id="fiber.fiber_mgmt.h5"> 378 <phrase id="fiber.fiber_mgmt.joining"/><link linkend="fiber.fiber_mgmt.joining">Joining</link> 379 </bridgehead> 380 <para> 381 In order to wait for a fiber to finish, the <link linkend="fiber_join"><code>fiber::join()</code></link> member function 382 of the <link linkend="class_fiber"><code>fiber</code></link> object can be used. <link linkend="fiber_join"><code>fiber::join()</code></link> will block 383 until the <link linkend="class_fiber"><code>fiber</code></link> object has completed. 384 </para> 385<programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">some_fn</phrase><phrase role="special">()</phrase> <phrase role="special">{</phrase> 386 <phrase role="special">...</phrase> 387<phrase role="special">}</phrase> 388 389<phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">fiber</phrase> <phrase role="identifier">f</phrase><phrase role="special">(</phrase> <phrase role="identifier">some_fn</phrase><phrase role="special">);</phrase> 390<phrase role="special">...</phrase> 391<phrase role="identifier">f</phrase><phrase role="special">.</phrase><phrase role="identifier">join</phrase><phrase role="special">();</phrase> 392</programlisting> 393 <para> 394 If the fiber has already completed, then <link linkend="fiber_join"><code>fiber::join()</code></link> returns immediately 395 and the joined <link linkend="class_fiber"><code>fiber</code></link> object becomes <emphasis>not-a-fiber</emphasis>. 396 </para> 397 <bridgehead renderas="sect3" id="fiber.fiber_mgmt.h6"> 398 <phrase id="fiber.fiber_mgmt.destruction"/><link linkend="fiber.fiber_mgmt.destruction">Destruction</link> 399 </bridgehead> 400 <para> 401 When a <link linkend="class_fiber"><code>fiber</code></link> object representing a valid execution context (the fiber 402 is <link linkend="fiber_joinable"><code>fiber::joinable()</code></link>) is destroyed, the program terminates. If 403 you intend the fiber to outlive the <link linkend="class_fiber"><code>fiber</code></link> object that launched it, 404 use the <link linkend="fiber_detach"><code>fiber::detach()</code></link> method. 405 </para> 406<programlisting><phrase role="special">{</phrase> 407 <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">fiber</phrase> <phrase role="identifier">f</phrase><phrase role="special">(</phrase> <phrase role="identifier">some_fn</phrase><phrase role="special">);</phrase> 408<phrase role="special">}</phrase> <phrase role="comment">// std::terminate() will be called</phrase> 409 410<phrase role="special">{</phrase> 411 <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">fiber</phrase> <phrase role="identifier">f</phrase><phrase role="special">(</phrase><phrase role="identifier">some_fn</phrase><phrase role="special">);</phrase> 412 <phrase role="identifier">f</phrase><phrase role="special">.</phrase><phrase role="identifier">detach</phrase><phrase role="special">();</phrase> 413<phrase role="special">}</phrase> <phrase role="comment">// okay, program continues</phrase> 414</programlisting> 415 <anchor id="class_fiber_id"/> 416 <bridgehead renderas="sect3" id="fiber.fiber_mgmt.h7"> 417 <phrase id="fiber.fiber_mgmt.fiber_ids"/><link linkend="fiber.fiber_mgmt.fiber_ids">Fiber 418 IDs</link> 419 </bridgehead> 420 <para> 421 Objects of class <link linkend="class_fiber_id"><code><phrase role="identifier">fiber</phrase><phrase 422 role="special">::</phrase><phrase role="identifier">id</phrase></code></link> can be 423 used to identify fibers. Each running <link linkend="class_fiber"><code>fiber</code></link> has a unique <link linkend="class_fiber_id"><code><phrase 424 role="identifier">fiber</phrase><phrase role="special">::</phrase><phrase role="identifier">id</phrase></code></link> obtainable 425 from the corresponding <link linkend="class_fiber"><code>fiber</code></link> 426by calling the <link linkend="fiber_get_id"><code>fiber::get_id()</code></link> member 427 function. Objects of class <link linkend="class_fiber_id"><code><phrase role="identifier">fiber</phrase><phrase 428 role="special">::</phrase><phrase role="identifier">id</phrase></code></link> can be 429 copied, and used as keys in associative containers: the full range of comparison 430 operators is provided. They can also be written to an output stream using the 431 stream insertion operator, though the output format is unspecified. 432 </para> 433 <para> 434 Each instance of <link linkend="class_fiber_id"><code><phrase role="identifier">fiber</phrase><phrase 435 role="special">::</phrase><phrase role="identifier">id</phrase></code></link> either 436 refers to some fiber, or <emphasis>not-a-fiber</emphasis>. Instances that refer 437 to <emphasis>not-a-fiber</emphasis> compare equal to each other, but not equal 438 to any instances that refer to an actual fiber. The comparison operators on 439 <link linkend="class_fiber_id"><code><phrase role="identifier">fiber</phrase><phrase role="special">::</phrase><phrase 440 role="identifier">id</phrase></code></link> yield a total order for every non-equal 441 <link linkend="class_fiber_id"><code><phrase role="identifier">fiber</phrase><phrase role="special">::</phrase><phrase 442 role="identifier">id</phrase></code></link>. 443 </para> 444 <anchor id="class_launch"/> 445 <bridgehead renderas="sect3" id="fiber.fiber_mgmt.h8"> 446 <phrase id="fiber.fiber_mgmt.enumeration__code__phrase_role__identifier__launch__phrase___code_"/><link 447 linkend="fiber.fiber_mgmt.enumeration__code__phrase_role__identifier__launch__phrase___code_">Enumeration 448 <code><phrase role="identifier">launch</phrase></code></link> 449 </bridgehead> 450 <para> 451 <code><phrase role="identifier">launch</phrase></code> specifies whether control 452 passes immediately into a newly-launched fiber. 453 </para> 454<programlisting><phrase role="keyword">enum</phrase> <phrase role="keyword">class</phrase> <phrase role="identifier">launch</phrase> <phrase role="special">{</phrase> 455 <phrase role="identifier">dispatch</phrase><phrase role="special">,</phrase> 456 <phrase role="identifier">post</phrase> 457<phrase role="special">};</phrase> 458</programlisting> 459 <bridgehead renderas="sect3" id="fiber.fiber_mgmt.h9"> 460 <phrase id="fiber.fiber_mgmt._code__phrase_role__identifier__dispatch__phrase___code_"/><link 461 linkend="fiber.fiber_mgmt._code__phrase_role__identifier__dispatch__phrase___code_"><code><phrase 462 role="identifier">dispatch</phrase></code></link> 463 </bridgehead> 464 <variablelist> 465 <title></title> 466 <varlistentry> 467 <term>Effects:</term> 468 <listitem> 469 <para> 470 A fiber launched with <code><phrase role="identifier">launch</phrase> 471 <phrase role="special">==</phrase> <phrase role="identifier">dispatch</phrase></code> 472 is entered immediately. In other words, launching a fiber with <code><phrase 473 role="identifier">dispatch</phrase></code> suspends the caller (the previously-running 474 fiber) until the fiber scheduler has a chance to resume it later. 475 </para> 476 </listitem> 477 </varlistentry> 478 </variablelist> 479 <bridgehead renderas="sect3" id="fiber.fiber_mgmt.h10"> 480 <phrase id="fiber.fiber_mgmt._code__phrase_role__identifier__post__phrase___code_"/><link 481 linkend="fiber.fiber_mgmt._code__phrase_role__identifier__post__phrase___code_"><code><phrase 482 role="identifier">post</phrase></code></link> 483 </bridgehead> 484 <variablelist> 485 <title></title> 486 <varlistentry> 487 <term>Effects:</term> 488 <listitem> 489 <para> 490 A fiber launched with <code><phrase role="identifier">launch</phrase> 491 <phrase role="special">==</phrase> <phrase role="identifier">post</phrase></code> 492 is passed to the fiber scheduler as ready, but it is not yet entered. 493 The caller (the previously-running fiber) continues executing. The newly-launched 494 fiber will be entered when the fiber scheduler has a chance to resume 495 it later. 496 </para> 497 </listitem> 498 </varlistentry> 499 <varlistentry> 500 <term>Note:</term> 501 <listitem> 502 <para> 503 If <code><phrase role="identifier">launch</phrase></code> is not explicitly 504 specified, <code><phrase role="identifier">post</phrase></code> is the 505 default. 506 </para> 507 </listitem> 508 </varlistentry> 509 </variablelist> 510 <section id="fiber.fiber_mgmt.fiber"> 511 <title><anchor id="class_fiber"/><link linkend="fiber.fiber_mgmt.fiber">Class 512 <code><phrase role="identifier">fiber</phrase></code></link></title> 513<programlisting><phrase role="preprocessor">#include</phrase> <phrase role="special"><</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">></phrase> 514 515<phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase> 516<phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase> 517 518<phrase role="keyword">class</phrase> <phrase role="identifier">fiber</phrase> <phrase role="special">{</phrase> 519<phrase role="keyword">public</phrase><phrase role="special">:</phrase> 520 <phrase role="keyword">class</phrase> <phrase role="identifier">id</phrase><phrase role="special">;</phrase> 521 522 <phrase role="keyword">constexpr</phrase> <phrase role="identifier">fiber</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 523 524 <phrase role="keyword">template</phrase><phrase role="special"><</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">></phrase> 525 <phrase role="identifier">fiber</phrase><phrase role="special">(</phrase> <phrase role="identifier">Fn</phrase> <phrase role="special">&&,</phrase> <phrase role="identifier">Args</phrase> <phrase role="special">&&</phrase> <phrase role="special">...);</phrase> 526 527 <phrase role="keyword">template</phrase><phrase role="special"><</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Fn</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="special">...</phrase> <phrase role="identifier">Args</phrase> <phrase role="special">></phrase> 528 <phrase role="identifier">fiber</phrase><phrase role="special">(</phrase> <link linkend="class_launch"><code><phrase role="identifier">launch</phrase></code></link><phrase role="special">,</phrase> <phrase role="identifier">Fn</phrase> <phrase role="special">&&,</phrase> <phrase role="identifier">Args</phrase> <phrase role="special">&&</phrase> <phrase role="special">...);</phrase> 529 530 <phrase role="keyword">template</phrase><phrase role="special"><</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">></phrase> 531 <phrase role="identifier">fiber</phrase><phrase role="special">(</phrase> <ulink url="http://en.cppreference.com/w/cpp/memory/allocator_arg_t"><code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">allocator_arg_t</phrase></code></ulink><phrase role="special">,</phrase> <phrase role="identifier">StackAllocator</phrase> <phrase role="special">&&,</phrase> <phrase role="identifier">Fn</phrase> <phrase role="special">&&,</phrase> <phrase role="identifier">Args</phrase> <phrase role="special">&&</phrase> <phrase role="special">...);</phrase> 532 533 <phrase role="keyword">template</phrase><phrase role="special"><</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">></phrase> 534 <phrase role="identifier">fiber</phrase><phrase role="special">(</phrase> <link linkend="class_launch"><code><phrase role="identifier">launch</phrase></code></link><phrase role="special">,</phrase> <ulink url="http://en.cppreference.com/w/cpp/memory/allocator_arg_t"><code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">allocator_arg_t</phrase></code></ulink><phrase role="special">,</phrase> <phrase role="identifier">StackAllocator</phrase> <phrase role="special">&&,</phrase> <phrase role="identifier">Fn</phrase> <phrase role="special">&&,</phrase> <phrase role="identifier">Args</phrase> <phrase role="special">&&</phrase> <phrase role="special">...);</phrase> 535 536 <phrase role="special">~</phrase><phrase role="identifier">fiber</phrase><phrase role="special">();</phrase> 537 538 <phrase role="identifier">fiber</phrase><phrase role="special">(</phrase> <phrase role="identifier">fiber</phrase> <phrase role="keyword">const</phrase><phrase role="special">&)</phrase> <phrase role="special">=</phrase> <phrase role="keyword">delete</phrase><phrase role="special">;</phrase> 539 540 <phrase role="identifier">fiber</phrase> <phrase role="special">&</phrase> <phrase role="keyword">operator</phrase><phrase role="special">=(</phrase> <phrase role="identifier">fiber</phrase> <phrase role="keyword">const</phrase><phrase role="special">&)</phrase> <phrase role="special">=</phrase> <phrase role="keyword">delete</phrase><phrase role="special">;</phrase> 541 542 <phrase role="identifier">fiber</phrase><phrase role="special">(</phrase> <phrase role="identifier">fiber</phrase> <phrase role="special">&&)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 543 544 <phrase role="identifier">fiber</phrase> <phrase role="special">&</phrase> <phrase role="keyword">operator</phrase><phrase role="special">=(</phrase> <phrase role="identifier">fiber</phrase> <phrase role="special">&&)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 545 546 <phrase role="keyword">void</phrase> <phrase role="identifier">swap</phrase><phrase role="special">(</phrase> <phrase role="identifier">fiber</phrase> <phrase role="special">&)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 547 548 <phrase role="keyword">bool</phrase> <phrase role="identifier">joinable</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 549 550 <phrase role="identifier">id</phrase> <phrase role="identifier">get_id</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 551 552 <phrase role="keyword">void</phrase> <phrase role="identifier">detach</phrase><phrase role="special">();</phrase> 553 554 <phrase role="keyword">void</phrase> <phrase role="identifier">join</phrase><phrase role="special">();</phrase> 555 556 <phrase role="keyword">template</phrase><phrase role="special"><</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">PROPS</phrase> <phrase role="special">></phrase> 557 <phrase role="identifier">PROPS</phrase> <phrase role="special">&</phrase> <phrase role="identifier">properties</phrase><phrase role="special">();</phrase> 558<phrase role="special">};</phrase> 559 560<phrase role="keyword">bool</phrase> <phrase role="keyword">operator</phrase><phrase role="special"><(</phrase> <phrase role="identifier">fiber</phrase> <phrase role="keyword">const</phrase><phrase role="special">&,</phrase> <phrase role="identifier">fiber</phrase> <phrase role="keyword">const</phrase><phrase role="special">&)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 561 562<phrase role="keyword">void</phrase> <phrase role="identifier">swap</phrase><phrase role="special">(</phrase> <phrase role="identifier">fiber</phrase> <phrase role="special">&,</phrase> <phrase role="identifier">fiber</phrase> <phrase role="special">&)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 563 564<phrase role="keyword">template</phrase><phrase role="special"><</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">></phrase> 565<phrase role="keyword">void</phrase> <phrase role="identifier">use_scheduling_algorithm</phrase><phrase role="special">(</phrase> <phrase role="identifier">Args</phrase> <phrase role="special">&&</phrase> <phrase role="special">...)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 566 567<phrase role="keyword">bool</phrase> <phrase role="identifier">has_ready_fibers</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 568 569<phrase role="special">}}</phrase> 570</programlisting> 571 <bridgehead renderas="sect4" id="fiber.fiber_mgmt.fiber.h0"> 572 <phrase id="fiber.fiber_mgmt.fiber.default_constructor"/><link linkend="fiber.fiber_mgmt.fiber.default_constructor">Default 573 constructor</link> 574 </bridgehead> 575<programlisting><phrase role="keyword">constexpr</phrase> <phrase role="identifier">fiber</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 576</programlisting> 577 <variablelist> 578 <title></title> 579 <varlistentry> 580 <term>Effects:</term> 581 <listitem> 582 <para> 583 Constructs a <link linkend="class_fiber"><code>fiber</code></link> instance that refers to <emphasis>not-a-fiber</emphasis>. 584 </para> 585 </listitem> 586 </varlistentry> 587 <varlistentry> 588 <term>Postconditions:</term> 589 <listitem> 590 <para> 591 <code><phrase role="keyword">this</phrase><phrase role="special">-></phrase><phrase 592 role="identifier">get_id</phrase><phrase role="special">()</phrase> 593 <phrase role="special">==</phrase> <phrase role="identifier">fiber</phrase><phrase 594 role="special">::</phrase><phrase role="identifier">id</phrase><phrase 595 role="special">()</phrase></code> 596 </para> 597 </listitem> 598 </varlistentry> 599 <varlistentry> 600 <term>Throws:</term> 601 <listitem> 602 <para> 603 Nothing 604 </para> 605 </listitem> 606 </varlistentry> 607 </variablelist> 608 <anchor id="fiber_fiber"/> 609 <bridgehead renderas="sect4" id="fiber.fiber_mgmt.fiber.h1"> 610 <phrase id="fiber.fiber_mgmt.fiber.constructor"/><link linkend="fiber.fiber_mgmt.fiber.constructor">Constructor</link> 611 </bridgehead> 612<programlisting><phrase role="keyword">template</phrase><phrase role="special"><</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">></phrase> 613<phrase role="identifier">fiber</phrase><phrase role="special">(</phrase> <phrase role="identifier">Fn</phrase> <phrase role="special">&&</phrase> <phrase role="identifier">fn</phrase><phrase role="special">,</phrase> <phrase role="identifier">Args</phrase> <phrase role="special">&&</phrase> <phrase role="special">...</phrase> <phrase role="identifier">args</phrase><phrase role="special">);</phrase> 614 615<phrase role="keyword">template</phrase><phrase role="special"><</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Fn</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="special">...</phrase> <phrase role="identifier">Args</phrase> <phrase role="special">></phrase> 616<phrase role="identifier">fiber</phrase><phrase role="special">(</phrase> <link linkend="class_launch"><code><phrase role="identifier">launch</phrase></code></link> <phrase role="identifier">policy</phrase><phrase role="special">,</phrase> <phrase role="identifier">Fn</phrase> <phrase role="special">&&</phrase> <phrase role="identifier">fn</phrase><phrase role="special">,</phrase> <phrase role="identifier">Args</phrase> <phrase role="special">&&</phrase> <phrase role="special">...</phrase> <phrase role="identifier">args</phrase><phrase role="special">);</phrase> 617 618<phrase role="keyword">template</phrase><phrase role="special"><</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">></phrase> 619<phrase role="identifier">fiber</phrase><phrase role="special">(</phrase> <ulink url="http://en.cppreference.com/w/cpp/memory/allocator_arg_t"><code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">allocator_arg_t</phrase></code></ulink><phrase role="special">,</phrase> <phrase role="identifier">StackAllocator</phrase> <phrase role="special">&&</phrase> <phrase role="identifier">salloc</phrase><phrase role="special">,</phrase> <phrase role="identifier">Fn</phrase> <phrase role="special">&&</phrase> <phrase role="identifier">fn</phrase><phrase role="special">,</phrase> <phrase role="identifier">Args</phrase> <phrase role="special">&&</phrase> <phrase role="special">...</phrase> <phrase role="identifier">args</phrase><phrase role="special">);</phrase> 620 621<phrase role="keyword">template</phrase><phrase role="special"><</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">></phrase> 622<phrase role="identifier">fiber</phrase><phrase role="special">(</phrase> <link linkend="class_launch"><code><phrase role="identifier">launch</phrase></code></link> <phrase role="identifier">policy</phrase><phrase role="special">,</phrase> <ulink url="http://en.cppreference.com/w/cpp/memory/allocator_arg_t"><code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">allocator_arg_t</phrase></code></ulink><phrase role="special">,</phrase> <phrase role="identifier">StackAllocator</phrase> <phrase role="special">&&</phrase> <phrase role="identifier">salloc</phrase><phrase role="special">,</phrase> 623 <phrase role="identifier">Fn</phrase> <phrase role="special">&&</phrase> <phrase role="identifier">fn</phrase><phrase role="special">,</phrase> <phrase role="identifier">Args</phrase> <phrase role="special">&&</phrase> <phrase role="special">...</phrase> <phrase role="identifier">args</phrase><phrase role="special">);</phrase> 624</programlisting> 625 <variablelist> 626 <title></title> 627 <varlistentry> 628 <term>Preconditions:</term> 629 <listitem> 630 <para> 631 <code><phrase role="identifier">Fn</phrase></code> must be copyable 632 or movable. 633 </para> 634 </listitem> 635 </varlistentry> 636 <varlistentry> 637 <term>Effects:</term> 638 <listitem> 639 <para> 640 <code><phrase role="identifier">fn</phrase></code> is copied or moved 641 into internal storage for access by the new fiber. If <link linkend="class_launch"><code>launch</code></link> is 642 specified (or defaulted) to <code><phrase role="identifier">post</phrase></code>, 643 the new fiber is marked <quote>ready</quote> and will be entered at 644 the next opportunity. If <code><phrase role="identifier">launch</phrase></code> 645 is specified as <code><phrase role="identifier">dispatch</phrase></code>, 646 the calling fiber is suspended and the new fiber is entered immediately. 647 </para> 648 </listitem> 649 </varlistentry> 650 <varlistentry> 651 <term>Postconditions:</term> 652 <listitem> 653 <para> 654 <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code> 655 refers to the newly created fiber of execution. 656 </para> 657 </listitem> 658 </varlistentry> 659 <varlistentry> 660 <term>Throws:</term> 661 <listitem> 662 <para> 663 <code><phrase role="identifier">fiber_error</phrase></code> if an error 664 occurs. 665 </para> 666 </listitem> 667 </varlistentry> 668 <varlistentry> 669 <term>Note:</term> 670 <listitem> 671 <para> 672 <link linkend="stack_allocator_concept"><code><phrase role="identifier">StackAllocator</phrase></code></link> 673 is required to allocate a stack for the internal __econtext__. If 674 <code><phrase role="identifier">StackAllocator</phrase></code> is not 675 explicitly passed, the default stack allocator depends on <code><phrase 676 role="identifier">BOOST_USE_SEGMENTED_STACKS</phrase></code>: if defined, 677 you will get a <link linkend="class_segmented_stack"><code>segmented_stack</code></link>, else a <link linkend="class_fixedsize_stack"><code>fixedsize_stack</code></link>. 678 </para> 679 </listitem> 680 </varlistentry> 681 <varlistentry> 682 <term>See also:</term> 683 <listitem> 684 <para> 685 <ulink url="http://en.cppreference.com/w/cpp/memory/allocator_arg_t"><code><phrase 686 role="identifier">std</phrase><phrase role="special">::</phrase><phrase 687 role="identifier">allocator_arg_t</phrase></code></ulink>, <link linkend="stack">Stack 688 allocation</link> 689 </para> 690 </listitem> 691 </varlistentry> 692 </variablelist> 693 <bridgehead renderas="sect4" id="fiber.fiber_mgmt.fiber.h2"> 694 <phrase id="fiber.fiber_mgmt.fiber.move_constructor"/><link linkend="fiber.fiber_mgmt.fiber.move_constructor">Move 695 constructor</link> 696 </bridgehead> 697<programlisting><phrase role="identifier">fiber</phrase><phrase role="special">(</phrase> <phrase role="identifier">fiber</phrase> <phrase role="special">&&</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 698</programlisting> 699 <variablelist> 700 <title></title> 701 <varlistentry> 702 <term>Effects:</term> 703 <listitem> 704 <para> 705 Transfers ownership of the fiber managed by <code><phrase role="identifier">other</phrase></code> 706 to the newly constructed <link linkend="class_fiber"><code>fiber</code></link> instance. 707 </para> 708 </listitem> 709 </varlistentry> 710 <varlistentry> 711 <term>Postconditions:</term> 712 <listitem> 713 <para> 714 <code><phrase role="identifier">other</phrase><phrase role="special">.</phrase><phrase 715 role="identifier">get_id</phrase><phrase role="special">()</phrase> 716 <phrase role="special">==</phrase> <phrase role="identifier">fiber</phrase><phrase 717 role="special">::</phrase><phrase role="identifier">id</phrase><phrase 718 role="special">()</phrase></code> and <code><phrase role="identifier">get_id</phrase><phrase 719 role="special">()</phrase></code> returns the value of <code><phrase 720 role="identifier">other</phrase><phrase role="special">.</phrase><phrase 721 role="identifier">get_id</phrase><phrase role="special">()</phrase></code> 722 prior to the construction 723 </para> 724 </listitem> 725 </varlistentry> 726 <varlistentry> 727 <term>Throws:</term> 728 <listitem> 729 <para> 730 Nothing 731 </para> 732 </listitem> 733 </varlistentry> 734 </variablelist> 735 <bridgehead renderas="sect4" id="fiber.fiber_mgmt.fiber.h3"> 736 <phrase id="fiber.fiber_mgmt.fiber.move_assignment_operator"/><link linkend="fiber.fiber_mgmt.fiber.move_assignment_operator">Move 737 assignment operator</link> 738 </bridgehead> 739<programlisting><phrase role="identifier">fiber</phrase> <phrase role="special">&</phrase> <phrase role="keyword">operator</phrase><phrase role="special">=(</phrase> <phrase role="identifier">fiber</phrase> <phrase role="special">&&</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 740</programlisting> 741 <variablelist> 742 <title></title> 743 <varlistentry> 744 <term>Effects:</term> 745 <listitem> 746 <para> 747 Transfers ownership of the fiber managed by <code><phrase role="identifier">other</phrase></code> 748 (if any) to <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>. 749 </para> 750 </listitem> 751 </varlistentry> 752 <varlistentry> 753 <term>Postconditions:</term> 754 <listitem> 755 <para> 756 <code><phrase role="identifier">other</phrase><phrase role="special">-></phrase><phrase 757 role="identifier">get_id</phrase><phrase role="special">()</phrase> 758 <phrase role="special">==</phrase> <phrase role="identifier">fiber</phrase><phrase 759 role="special">::</phrase><phrase role="identifier">id</phrase><phrase 760 role="special">()</phrase></code> and <code><phrase role="identifier">get_id</phrase><phrase 761 role="special">()</phrase></code> returns the value of <code><phrase 762 role="identifier">other</phrase><phrase role="special">.</phrase><phrase 763 role="identifier">get_id</phrase><phrase role="special">()</phrase></code> 764 prior to the assignment. 765 </para> 766 </listitem> 767 </varlistentry> 768 <varlistentry> 769 <term>Throws:</term> 770 <listitem> 771 <para> 772 Nothing 773 </para> 774 </listitem> 775 </varlistentry> 776 </variablelist> 777 <bridgehead renderas="sect4" id="fiber.fiber_mgmt.fiber.h4"> 778 <phrase id="fiber.fiber_mgmt.fiber.destructor"/><link linkend="fiber.fiber_mgmt.fiber.destructor">Destructor</link> 779 </bridgehead> 780<programlisting><phrase role="special">~</phrase><phrase role="identifier">fiber</phrase><phrase role="special">();</phrase> 781</programlisting> 782 <variablelist> 783 <title></title> 784 <varlistentry> 785 <term>Effects:</term> 786 <listitem> 787 <para> 788 If the fiber is <link linkend="fiber_joinable"><code>fiber::joinable()</code></link>, calls std::terminate. 789 Destroys <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>. 790 </para> 791 </listitem> 792 </varlistentry> 793 <varlistentry> 794 <term>Note:</term> 795 <listitem> 796 <para> 797 The programmer must ensure that the destructor is never executed while 798 the fiber is still <link linkend="fiber_joinable"><code>fiber::joinable()</code></link>. Even if you know 799 that the fiber has completed, you must still call either <link linkend="fiber_join"><code>fiber::join()</code></link> or 800 <link linkend="fiber_detach"><code>fiber::detach()</code></link> before destroying the <code><phrase role="identifier">fiber</phrase></code> 801 object. 802 </para> 803 </listitem> 804 </varlistentry> 805 </variablelist> 806 <para> 807 <bridgehead renderas="sect4" id="fiber_joinable_bridgehead"> 808 <phrase id="fiber_joinable"/> 809 <link linkend="fiber_joinable">Member function <code>joinable</code>()</link> 810</bridgehead> 811 </para> 812<programlisting><phrase role="keyword">bool</phrase> <phrase role="identifier">joinable</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 813</programlisting> 814 <variablelist> 815 <title></title> 816 <varlistentry> 817 <term>Returns:</term> 818 <listitem> 819 <para> 820 <code><phrase role="keyword">true</phrase></code> if <code><phrase 821 role="special">*</phrase><phrase role="keyword">this</phrase></code> 822 refers to a fiber of execution, which may or may not have completed; 823 otherwise <code><phrase role="keyword">false</phrase></code>. 824 </para> 825 </listitem> 826 </varlistentry> 827 <varlistentry> 828 <term>Throws:</term> 829 <listitem> 830 <para> 831 Nothing 832 </para> 833 </listitem> 834 </varlistentry> 835 </variablelist> 836 <para> 837 <bridgehead renderas="sect4" id="fiber_join_bridgehead"> 838 <phrase id="fiber_join"/> 839 <link linkend="fiber_join">Member function <code>join</code>()</link> 840</bridgehead> 841 </para> 842<programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">join</phrase><phrase role="special">();</phrase> 843</programlisting> 844 <variablelist> 845 <title></title> 846 <varlistentry> 847 <term>Preconditions:</term> 848 <listitem> 849 <para> 850 the fiber is <link linkend="fiber_joinable"><code>fiber::joinable()</code></link>. 851 </para> 852 </listitem> 853 </varlistentry> 854 <varlistentry> 855 <term>Effects:</term> 856 <listitem> 857 <para> 858 Waits for the referenced fiber of execution to complete. 859 </para> 860 </listitem> 861 </varlistentry> 862 <varlistentry> 863 <term>Postconditions:</term> 864 <listitem> 865 <para> 866 The fiber of execution referenced on entry has completed. <code><phrase 867 role="special">*</phrase><phrase role="keyword">this</phrase></code> 868 no longer refers to any fiber of execution. 869 </para> 870 </listitem> 871 </varlistentry> 872 <varlistentry> 873 <term>Throws:</term> 874 <listitem> 875 <para> 876 <code><phrase role="identifier">fiber_error</phrase></code> 877 </para> 878 </listitem> 879 </varlistentry> 880 <varlistentry> 881 <term>Error Conditions:</term> 882 <listitem> 883 <para> 884 <emphasis role="bold">resource_deadlock_would_occur</emphasis>: if 885 <code><phrase role="keyword">this</phrase><phrase role="special">-></phrase><phrase 886 role="identifier">get_id</phrase><phrase role="special">()</phrase> 887 <phrase role="special">==</phrase> <phrase role="identifier">boost</phrase><phrase 888 role="special">::</phrase><phrase role="identifier">this_fiber</phrase><phrase 889 role="special">::</phrase><phrase role="identifier">get_id</phrase><phrase 890 role="special">()</phrase></code>. <emphasis role="bold">invalid_argument</emphasis>: 891 if the fiber is not <link linkend="fiber_joinable"><code>fiber::joinable()</code></link>. 892 </para> 893 </listitem> 894 </varlistentry> 895 </variablelist> 896 <para> 897 <bridgehead renderas="sect4" id="fiber_detach_bridgehead"> 898 <phrase id="fiber_detach"/> 899 <link linkend="fiber_detach">Member function <code>detach</code>()</link> 900</bridgehead> 901 </para> 902<programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">detach</phrase><phrase role="special">();</phrase> 903</programlisting> 904 <variablelist> 905 <title></title> 906 <varlistentry> 907 <term>Preconditions:</term> 908 <listitem> 909 <para> 910 the fiber is <link linkend="fiber_joinable"><code>fiber::joinable()</code></link>. 911 </para> 912 </listitem> 913 </varlistentry> 914 <varlistentry> 915 <term>Effects:</term> 916 <listitem> 917 <para> 918 The fiber of execution becomes detached, and no longer has an associated 919 <link linkend="class_fiber"><code>fiber</code></link> object. 920 </para> 921 </listitem> 922 </varlistentry> 923 <varlistentry> 924 <term>Postconditions:</term> 925 <listitem> 926 <para> 927 <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code> 928 no longer refers to any fiber of execution. 929 </para> 930 </listitem> 931 </varlistentry> 932 <varlistentry> 933 <term>Throws:</term> 934 <listitem> 935 <para> 936 <code><phrase role="identifier">fiber_error</phrase></code> 937 </para> 938 </listitem> 939 </varlistentry> 940 <varlistentry> 941 <term>Error Conditions:</term> 942 <listitem> 943 <para> 944 <emphasis role="bold">invalid_argument</emphasis>: if the fiber is 945 not <link linkend="fiber_joinable"><code>fiber::joinable()</code></link>. 946 </para> 947 </listitem> 948 </varlistentry> 949 </variablelist> 950 <para> 951 <bridgehead renderas="sect4" id="fiber_get_id_bridgehead"> 952 <phrase id="fiber_get_id"/> 953 <link linkend="fiber_get_id">Member function <code>get_id</code>()</link> 954</bridgehead> 955 </para> 956<programlisting><phrase role="identifier">fiber</phrase><phrase role="special">::</phrase><phrase role="identifier">id</phrase> <phrase role="identifier">get_id</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 957</programlisting> 958 <variablelist> 959 <title></title> 960 <varlistentry> 961 <term>Returns:</term> 962 <listitem> 963 <para> 964 If <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code> 965 refers to a fiber of execution, an instance of <link linkend="class_fiber_id"><code><phrase 966 role="identifier">fiber</phrase><phrase role="special">::</phrase><phrase 967 role="identifier">id</phrase></code></link> that represents that fiber. Otherwise 968 returns a default-constructed <link linkend="class_fiber_id"><code><phrase role="identifier">fiber</phrase><phrase 969 role="special">::</phrase><phrase role="identifier">id</phrase></code></link>. 970 </para> 971 </listitem> 972 </varlistentry> 973 <varlistentry> 974 <term>Throws:</term> 975 <listitem> 976 <para> 977 Nothing 978 </para> 979 </listitem> 980 </varlistentry> 981 <varlistentry> 982 <term>See also:</term> 983 <listitem> 984 <para> 985 <link linkend="this_fiber_get_id"><code>this_fiber::get_id()</code></link> 986 </para> 987 </listitem> 988 </varlistentry> 989 </variablelist> 990 <para> 991 <bridgehead renderas="sect4" id="fiber_properties_bridgehead"> 992 <phrase id="fiber_properties"/> 993 <link linkend="fiber_properties">Templated member 994 function <code>properties</code>()</link> 995</bridgehead> 996 </para> 997<programlisting><phrase role="keyword">template</phrase><phrase role="special"><</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">PROPS</phrase> <phrase role="special">></phrase> 998<phrase role="identifier">PROPS</phrase> <phrase role="special">&</phrase> <phrase role="identifier">properties</phrase><phrase role="special">();</phrase> 999</programlisting> 1000 <variablelist> 1001 <title></title> 1002 <varlistentry> 1003 <term>Preconditions:</term> 1004 <listitem> 1005 <para> 1006 <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code> 1007 refers to a fiber of execution. <link linkend="use_scheduling_algorithm"><code>use_scheduling_algorithm()</code></link> has 1008 been called from this thread with a subclass of <link linkend="class_algorithm_with_properties"><code>algorithm_with_properties<></code></link> with 1009 the same template argument <code><phrase role="identifier">PROPS</phrase></code>. 1010 </para> 1011 </listitem> 1012 </varlistentry> 1013 <varlistentry> 1014 <term>Returns:</term> 1015 <listitem> 1016 <para> 1017 a reference to the scheduler properties instance for <code><phrase 1018 role="special">*</phrase><phrase role="keyword">this</phrase></code>. 1019 </para> 1020 </listitem> 1021 </varlistentry> 1022 <varlistentry> 1023 <term>Throws:</term> 1024 <listitem> 1025 <para> 1026 <code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase 1027 role="identifier">bad_cast</phrase></code> if <code><phrase role="identifier">use_scheduling_algorithm</phrase><phrase 1028 role="special">()</phrase></code> was called with a <code><phrase role="identifier">algorithm_with_properties</phrase></code> 1029 subclass with some other template parameter than <code><phrase role="identifier">PROPS</phrase></code>. 1030 </para> 1031 </listitem> 1032 </varlistentry> 1033 <varlistentry> 1034 <term>Note:</term> 1035 <listitem> 1036 <para> 1037 <link linkend="class_algorithm_with_properties"><code>algorithm_with_properties<></code></link> provides 1038 a way for a user-coded scheduler to associate extended properties, 1039 such as priority, with a fiber instance. This method allows access 1040 to those user-provided properties. 1041 </para> 1042 </listitem> 1043 </varlistentry> 1044 <varlistentry> 1045 <term>See also:</term> 1046 <listitem> 1047 <para> 1048 <link linkend="custom">Customization</link> 1049 </para> 1050 </listitem> 1051 </varlistentry> 1052 </variablelist> 1053 <para> 1054 <bridgehead renderas="sect4" id="fiber_swap_bridgehead"> 1055 <phrase id="fiber_swap"/> 1056 <link linkend="fiber_swap">Member function <code>swap</code>()</link> 1057</bridgehead> 1058 </para> 1059<programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">swap</phrase><phrase role="special">(</phrase> <phrase role="identifier">fiber</phrase> <phrase role="special">&</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 1060</programlisting> 1061 <variablelist> 1062 <title></title> 1063 <varlistentry> 1064 <term>Effects:</term> 1065 <listitem> 1066 <para> 1067 Exchanges the fiber of execution associated with <code><phrase role="special">*</phrase><phrase 1068 role="keyword">this</phrase></code> and <code><phrase role="identifier">other</phrase></code>, 1069 so <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code> 1070 becomes associated with the fiber formerly associated with <code><phrase 1071 role="identifier">other</phrase></code>, and vice-versa. 1072 </para> 1073 </listitem> 1074 </varlistentry> 1075 <varlistentry> 1076 <term>Postconditions:</term> 1077 <listitem> 1078 <para> 1079 <code><phrase role="keyword">this</phrase><phrase role="special">-></phrase><phrase 1080 role="identifier">get_id</phrase><phrase role="special">()</phrase></code> 1081 returns the same value as <code><phrase role="identifier">other</phrase><phrase 1082 role="special">.</phrase><phrase role="identifier">get_id</phrase><phrase 1083 role="special">()</phrase></code> prior to the call. <code><phrase 1084 role="identifier">other</phrase><phrase role="special">.</phrase><phrase 1085 role="identifier">get_id</phrase><phrase role="special">()</phrase></code> 1086 returns the same value as <code><phrase role="keyword">this</phrase><phrase 1087 role="special">-></phrase><phrase role="identifier">get_id</phrase><phrase 1088 role="special">()</phrase></code> prior to the call. 1089 </para> 1090 </listitem> 1091 </varlistentry> 1092 <varlistentry> 1093 <term>Throws:</term> 1094 <listitem> 1095 <para> 1096 Nothing 1097 </para> 1098 </listitem> 1099 </varlistentry> 1100 </variablelist> 1101 <para> 1102 <bridgehead renderas="sect4" id="swap_for_fiber_bridgehead"> 1103 <phrase id="swap_for_fiber"/> 1104 <link linkend="swap_for_fiber">Non-member function 1105 <code>swap()</code></link> 1106</bridgehead> 1107 </para> 1108<programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">swap</phrase><phrase role="special">(</phrase> <phrase role="identifier">fiber</phrase> <phrase role="special">&</phrase> <phrase role="identifier">l</phrase><phrase role="special">,</phrase> <phrase role="identifier">fiber</phrase> <phrase role="special">&</phrase> <phrase role="identifier">r</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 1109</programlisting> 1110 <variablelist> 1111 <title></title> 1112 <varlistentry> 1113 <term>Effects:</term> 1114 <listitem> 1115 <para> 1116 Same as <code><phrase role="identifier">l</phrase><phrase role="special">.</phrase><phrase 1117 role="identifier">swap</phrase><phrase role="special">(</phrase> <phrase 1118 role="identifier">r</phrase><phrase role="special">)</phrase></code>. 1119 </para> 1120 </listitem> 1121 </varlistentry> 1122 <varlistentry> 1123 <term>Throws:</term> 1124 <listitem> 1125 <para> 1126 Nothing 1127 </para> 1128 </listitem> 1129 </varlistentry> 1130 </variablelist> 1131 <para> 1132 <bridgehead renderas="sect4" id="operator<_bridgehead"> 1133 <phrase id="operator<"/> 1134 <link linkend="operator<">Non-member function <code>operator<()</code></link> 1135</bridgehead> 1136 </para> 1137<programlisting><phrase role="keyword">bool</phrase> <phrase role="keyword">operator</phrase><phrase role="special"><(</phrase> <phrase role="identifier">fiber</phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">l</phrase><phrase role="special">,</phrase> <phrase role="identifier">fiber</phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">r</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 1138</programlisting> 1139 <variablelist> 1140 <title></title> 1141 <varlistentry> 1142 <term>Returns:</term> 1143 <listitem> 1144 <para> 1145 <code><phrase role="keyword">true</phrase></code> if <code><phrase 1146 role="identifier">l</phrase><phrase role="special">.</phrase><phrase 1147 role="identifier">get_id</phrase><phrase role="special">()</phrase> 1148 <phrase role="special"><</phrase> <phrase role="identifier">r</phrase><phrase 1149 role="special">.</phrase><phrase role="identifier">get_id</phrase><phrase 1150 role="special">()</phrase></code> is <code><phrase role="keyword">true</phrase></code>, 1151 false otherwise. 1152 </para> 1153 </listitem> 1154 </varlistentry> 1155 <varlistentry> 1156 <term>Throws:</term> 1157 <listitem> 1158 <para> 1159 Nothing. 1160 </para> 1161 </listitem> 1162 </varlistentry> 1163 </variablelist> 1164 <para> 1165 <bridgehead renderas="sect4" id="use_scheduling_algorithm_bridgehead"> 1166 <phrase id="use_scheduling_algorithm"/> 1167 <link linkend="use_scheduling_algorithm">Non-member 1168 function <code>use_scheduling_algorithm()</code></link> 1169</bridgehead> 1170 </para> 1171<programlisting><phrase role="keyword">template</phrase><phrase role="special"><</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">></phrase> 1172<phrase role="keyword">void</phrase> <phrase role="identifier">use_scheduling_algorithm</phrase><phrase role="special">(</phrase> <phrase role="identifier">Args</phrase> <phrase role="special">&&</phrase> <phrase role="special">...</phrase> <phrase role="identifier">args</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 1173</programlisting> 1174 <variablelist> 1175 <title></title> 1176 <varlistentry> 1177 <term>Effects:</term> 1178 <listitem> 1179 <para> 1180 Directs <emphasis role="bold">Boost.Fiber</emphasis> to use <code><phrase 1181 role="identifier">SchedAlgo</phrase></code>, which must be a concrete 1182 subclass of <link linkend="class_algorithm"><code>algorithm</code></link>, as the scheduling algorithm for 1183 all fibers in the current thread. Pass any required <code><phrase role="identifier">SchedAlgo</phrase></code> 1184 constructor arguments as <code><phrase role="identifier">args</phrase></code>. 1185 </para> 1186 </listitem> 1187 </varlistentry> 1188 <varlistentry> 1189 <term>Note:</term> 1190 <listitem> 1191 <para> 1192 If you want a given thread to use a non-default scheduling algorithm, 1193 make that thread call <code><phrase role="identifier">use_scheduling_algorithm</phrase><phrase 1194 role="special">()</phrase></code> before any other <emphasis role="bold">Boost.Fiber</emphasis> 1195 entry point. If no scheduler has been set for the current thread by 1196 the time <emphasis role="bold">Boost.Fiber</emphasis> needs to use 1197 it, the library will create a default <link linkend="class_round_robin"><code>round_robin</code></link> instance 1198 for this thread. 1199 </para> 1200 </listitem> 1201 </varlistentry> 1202 <varlistentry> 1203 <term>Throws:</term> 1204 <listitem> 1205 <para> 1206 Nothing 1207 </para> 1208 </listitem> 1209 </varlistentry> 1210 <varlistentry> 1211 <term>See also:</term> 1212 <listitem> 1213 <para> 1214 <link linkend="scheduling">Scheduling</link>, <link linkend="custom">Customization</link> 1215 </para> 1216 </listitem> 1217 </varlistentry> 1218 </variablelist> 1219 <para> 1220 <bridgehead renderas="sect4" id="has_ready_fibers_bridgehead"> 1221 <phrase id="has_ready_fibers"/> 1222 <link linkend="has_ready_fibers">Non-member function 1223 <code>has_ready_fibers()</code></link> 1224</bridgehead> 1225 </para> 1226<programlisting><phrase role="keyword">bool</phrase> <phrase role="identifier">has_ready_fibers</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 1227</programlisting> 1228 <variablelist> 1229 <title></title> 1230 <varlistentry> 1231 <term>Returns:</term> 1232 <listitem> 1233 <para> 1234 <code><phrase role="keyword">true</phrase></code> if scheduler has 1235 fibers ready to run. 1236 </para> 1237 </listitem> 1238 </varlistentry> 1239 <varlistentry> 1240 <term>Throws:</term> 1241 <listitem> 1242 <para> 1243 Nothing 1244 </para> 1245 </listitem> 1246 </varlistentry> 1247 <varlistentry> 1248 <term>Note:</term> 1249 <listitem> 1250 <para> 1251 Can be used for work-stealing to find an idle scheduler. 1252 </para> 1253 </listitem> 1254 </varlistentry> 1255 </variablelist> 1256 </section> 1257 <section id="fiber.fiber_mgmt.id"> 1258 <title><anchor id="class_id"/><link linkend="fiber.fiber_mgmt.id">Class fiber::id</link></title> 1259<programlisting><phrase role="preprocessor">#include</phrase> <phrase role="special"><</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">></phrase> 1260 1261<phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase> 1262<phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase> 1263 1264<phrase role="keyword">class</phrase> <phrase role="identifier">id</phrase> <phrase role="special">{</phrase> 1265<phrase role="keyword">public</phrase><phrase role="special">:</phrase> 1266 <phrase role="keyword">constexpr</phrase> <phrase role="identifier">id</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 1267 1268 <phrase role="keyword">bool</phrase> <phrase role="keyword">operator</phrase><phrase role="special">==(</phrase> <phrase role="identifier">id</phrase> <phrase role="keyword">const</phrase><phrase role="special">&)</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 1269 1270 <phrase role="keyword">bool</phrase> <phrase role="keyword">operator</phrase><phrase role="special">!=(</phrase> <phrase role="identifier">id</phrase> <phrase role="keyword">const</phrase><phrase role="special">&)</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 1271 1272 <phrase role="keyword">bool</phrase> <phrase role="keyword">operator</phrase><phrase role="special"><(</phrase> <phrase role="identifier">id</phrase> <phrase role="keyword">const</phrase><phrase role="special">&)</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 1273 1274 <phrase role="keyword">bool</phrase> <phrase role="keyword">operator</phrase><phrase role="special">>(</phrase> <phrase role="identifier">id</phrase> <phrase role="keyword">const</phrase><phrase role="special">&)</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 1275 1276 <phrase role="keyword">bool</phrase> <phrase role="keyword">operator</phrase><phrase role="special"><=(</phrase> <phrase role="identifier">id</phrase> <phrase role="keyword">const</phrase><phrase role="special">&)</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 1277 1278 <phrase role="keyword">bool</phrase> <phrase role="keyword">operator</phrase><phrase role="special">>=(</phrase> <phrase role="identifier">id</phrase> <phrase role="keyword">const</phrase><phrase role="special">&)</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 1279 1280 <phrase role="keyword">template</phrase><phrase role="special"><</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">></phrase> 1281 <phrase role="keyword">friend</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">basic_ostream</phrase><phrase role="special"><</phrase> <phrase role="identifier">charT</phrase><phrase role="special">,</phrase> <phrase role="identifier">traitsT</phrase> <phrase role="special">></phrase> <phrase role="special">&</phrase> 1282 <phrase role="keyword">operator</phrase><phrase role="special"><<(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">basic_ostream</phrase><phrase role="special"><</phrase> <phrase role="identifier">charT</phrase><phrase role="special">,</phrase> <phrase role="identifier">traitsT</phrase> <phrase role="special">></phrase> <phrase role="special">&,</phrase> <phrase role="identifier">id</phrase> <phrase role="keyword">const</phrase><phrase role="special">&);</phrase> 1283<phrase role="special">};</phrase> 1284 1285<phrase role="special">}}</phrase> 1286</programlisting> 1287 <bridgehead renderas="sect4" id="fiber.fiber_mgmt.id.h0"> 1288 <phrase id="fiber.fiber_mgmt.id.constructor"/><link linkend="fiber.fiber_mgmt.id.constructor">Constructor</link> 1289 </bridgehead> 1290<programlisting><phrase role="keyword">constexpr</phrase> <phrase role="identifier">id</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 1291</programlisting> 1292 <variablelist> 1293 <title></title> 1294 <varlistentry> 1295 <term>Effects:</term> 1296 <listitem> 1297 <para> 1298 Represents an instance of <emphasis>not-a-fiber</emphasis>. 1299 </para> 1300 </listitem> 1301 </varlistentry> 1302 <varlistentry> 1303 <term>Throws:</term> 1304 <listitem> 1305 <para> 1306 Nothing. 1307 </para> 1308 </listitem> 1309 </varlistentry> 1310 </variablelist> 1311 <para> 1312 <bridgehead renderas="sect4" id="id_operator_equal_bridgehead"> 1313 <phrase id="id_operator_equal"/> 1314 <link linkend="id_operator_equal">Member function 1315 <code>operator==</code>()</link> 1316</bridgehead> 1317 </para> 1318<programlisting><phrase role="keyword">bool</phrase> <phrase role="keyword">operator</phrase><phrase role="special">==(</phrase> <phrase role="identifier">id</phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 1319</programlisting> 1320 <variablelist> 1321 <title></title> 1322 <varlistentry> 1323 <term>Returns:</term> 1324 <listitem> 1325 <para> 1326 <code><phrase role="keyword">true</phrase></code> if <code><phrase 1327 role="special">*</phrase><phrase role="keyword">this</phrase></code> 1328 and <code><phrase role="identifier">other</phrase></code> represent 1329 the same fiber, or both represent <emphasis>not-a-fiber</emphasis>, 1330 <code><phrase role="keyword">false</phrase></code> otherwise. 1331 </para> 1332 </listitem> 1333 </varlistentry> 1334 <varlistentry> 1335 <term>Throws:</term> 1336 <listitem> 1337 <para> 1338 Nothing. 1339 </para> 1340 </listitem> 1341 </varlistentry> 1342 </variablelist> 1343 <para> 1344 <bridgehead renderas="sect4" id="id_operator_not_equal_bridgehead"> 1345 <phrase id="id_operator_not_equal"/> 1346 <link linkend="id_operator_not_equal">Member 1347 function <code>operator!=</code>()</link> 1348</bridgehead> 1349 </para> 1350<programlisting><phrase role="keyword">bool</phrase> <phrase role="keyword">operator</phrase><phrase role="special">!=(</phrase> <phrase role="identifier">id</phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 1351</programlisting> 1352 <variablelist> 1353 <title></title> 1354 <varlistentry> 1355 <term>Returns:</term> 1356 <listitem> 1357 <para> 1358 <code>! (other == * this)</code> 1359 </para> 1360 </listitem> 1361 </varlistentry> 1362 <varlistentry> 1363 <term>Throws:</term> 1364 <listitem> 1365 <para> 1366 Nothing. 1367 </para> 1368 </listitem> 1369 </varlistentry> 1370 </variablelist> 1371 <para> 1372 <bridgehead renderas="sect4" id="id_operator_less_bridgehead"> 1373 <phrase id="id_operator_less"/> 1374 <link linkend="id_operator_less">Member function 1375 <code>operator<</code>()</link> 1376</bridgehead> 1377 </para> 1378<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">&</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 1379</programlisting> 1380 <variablelist> 1381 <title></title> 1382 <varlistentry> 1383 <term>Returns:</term> 1384 <listitem> 1385 <para> 1386 <code><phrase role="keyword">true</phrase></code> if <code><phrase 1387 role="special">*</phrase><phrase role="keyword">this</phrase> <phrase 1388 role="special">!=</phrase> <phrase role="identifier">other</phrase></code> 1389 is true and the implementation-defined total order of <code><phrase 1390 role="identifier">fiber</phrase><phrase role="special">::</phrase><phrase 1391 role="identifier">id</phrase></code> values places <code><phrase role="special">*</phrase><phrase 1392 role="keyword">this</phrase></code> before <code><phrase role="identifier">other</phrase></code>, 1393 false otherwise. 1394 </para> 1395 </listitem> 1396 </varlistentry> 1397 <varlistentry> 1398 <term>Throws:</term> 1399 <listitem> 1400 <para> 1401 Nothing. 1402 </para> 1403 </listitem> 1404 </varlistentry> 1405 </variablelist> 1406 <para> 1407 <bridgehead renderas="sect4" id="id_operator_greater_bridgehead"> 1408 <phrase id="id_operator_greater"/> 1409 <link linkend="id_operator_greater">Member 1410 function <code>operator></code>()</link> 1411</bridgehead> 1412 </para> 1413<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">&</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 1414</programlisting> 1415 <variablelist> 1416 <title></title> 1417 <varlistentry> 1418 <term>Returns:</term> 1419 <listitem> 1420 <para> 1421 <code><phrase role="identifier">other</phrase> <phrase role="special"><</phrase> 1422 <phrase role="special">*</phrase> <phrase role="keyword">this</phrase></code> 1423 </para> 1424 </listitem> 1425 </varlistentry> 1426 <varlistentry> 1427 <term>Throws:</term> 1428 <listitem> 1429 <para> 1430 Nothing. 1431 </para> 1432 </listitem> 1433 </varlistentry> 1434 </variablelist> 1435 <para> 1436 <bridgehead renderas="sect4" id="id_operator_less_equal_bridgehead"> 1437 <phrase id="id_operator_less_equal"/> 1438 <link linkend="id_operator_less_equal">Member 1439 function <code>operator<=</code>()</link> 1440</bridgehead> 1441 </para> 1442<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">&</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 1443</programlisting> 1444 <variablelist> 1445 <title></title> 1446 <varlistentry> 1447 <term>Returns:</term> 1448 <listitem> 1449 <para> 1450 <code><phrase role="special">!</phrase> <phrase role="special">(</phrase><phrase 1451 role="identifier">other</phrase> <phrase role="special"><</phrase> 1452 <phrase role="special">*</phrase> <phrase role="keyword">this</phrase><phrase 1453 role="special">)</phrase></code> 1454 </para> 1455 </listitem> 1456 </varlistentry> 1457 <varlistentry> 1458 <term>Throws:</term> 1459 <listitem> 1460 <para> 1461 Nothing. 1462 </para> 1463 </listitem> 1464 </varlistentry> 1465 </variablelist> 1466 <para> 1467 <bridgehead renderas="sect4" id="id_operator_greater_equal_bridgehead"> 1468 <phrase id="id_operator_greater_equal"/> 1469 <link linkend="id_operator_greater_equal">Member 1470 function <code>operator>=</code>()</link> 1471</bridgehead> 1472 </para> 1473<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">&</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 1474</programlisting> 1475 <variablelist> 1476 <title></title> 1477 <varlistentry> 1478 <term>Returns:</term> 1479 <listitem> 1480 <para> 1481 <code><phrase role="special">!</phrase> <phrase role="special">(*</phrase> 1482 <phrase role="keyword">this</phrase> <phrase role="special"><</phrase> 1483 <phrase role="identifier">other</phrase><phrase role="special">)</phrase></code> 1484 </para> 1485 </listitem> 1486 </varlistentry> 1487 <varlistentry> 1488 <term>Throws:</term> 1489 <listitem> 1490 <para> 1491 Nothing. 1492 </para> 1493 </listitem> 1494 </varlistentry> 1495 </variablelist> 1496 <bridgehead renderas="sect4" id="fiber.fiber_mgmt.id.h1"> 1497 <phrase id="fiber.fiber_mgmt.id.operator_lt__lt_"/><link linkend="fiber.fiber_mgmt.id.operator_lt__lt_">operator<<</link> 1498 </bridgehead> 1499<programlisting><phrase role="keyword">template</phrase><phrase role="special"><</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">></phrase> 1500<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">basic_ostream</phrase><phrase role="special"><</phrase> <phrase role="identifier">charT</phrase><phrase role="special">,</phrase> <phrase role="identifier">traitsT</phrase> <phrase role="special">></phrase> <phrase role="special">&</phrase> 1501<phrase role="keyword">operator</phrase><phrase role="special"><<(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">basic_ostream</phrase><phrase role="special"><</phrase> <phrase role="identifier">charT</phrase><phrase role="special">,</phrase> <phrase role="identifier">traitsT</phrase> <phrase role="special">></phrase> <phrase role="special">&</phrase> <phrase role="identifier">os</phrase><phrase role="special">,</phrase> <phrase role="identifier">id</phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">other</phrase><phrase role="special">);</phrase> 1502</programlisting> 1503 <variablelist> 1504 <title></title> 1505 <varlistentry> 1506 <term>Efects:</term> 1507 <listitem> 1508 <para> 1509 Writes the representation of <code><phrase role="identifier">other</phrase></code> 1510 to stream <code><phrase role="identifier">os</phrase></code>. The representation 1511 is unspecified. 1512 </para> 1513 </listitem> 1514 </varlistentry> 1515 <varlistentry> 1516 <term>Returns:</term> 1517 <listitem> 1518 <para> 1519 <code><phrase role="identifier">os</phrase></code> 1520 </para> 1521 </listitem> 1522 </varlistentry> 1523 </variablelist> 1524 </section> 1525 <section id="fiber.fiber_mgmt.this_fiber"> 1526 <title><link linkend="fiber.fiber_mgmt.this_fiber">Namespace this_fiber</link></title> 1527 <para> 1528 In general, <code><phrase role="identifier">this_fiber</phrase></code> operations 1529 may be called from the <quote>main</quote> fiber — the fiber on which function 1530 <code><phrase role="identifier">main</phrase><phrase role="special">()</phrase></code> 1531 is entered — as well as from an explicitly-launched thread’s thread-function. 1532 That is, in many respects the main fiber on each thread can be treated like 1533 an explicitly-launched fiber. 1534 </para> 1535<programlisting><phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase> 1536<phrase role="keyword">namespace</phrase> <phrase role="identifier">this_fiber</phrase> <phrase role="special">{</phrase> 1537 1538<phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">fiber</phrase><phrase role="special">::</phrase><phrase role="identifier">id</phrase> <phrase role="identifier">get_id</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 1539<phrase role="keyword">void</phrase> <phrase role="identifier">yield</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 1540<phrase role="keyword">template</phrase><phrase role="special"><</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Clock</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Duration</phrase> <phrase role="special">></phrase> 1541<phrase role="keyword">void</phrase> <phrase role="identifier">sleep_until</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">time_point</phrase><phrase role="special"><</phrase> <phrase role="identifier">Clock</phrase><phrase role="special">,</phrase> <phrase role="identifier">Duration</phrase> <phrase role="special">></phrase> <phrase role="keyword">const</phrase><phrase role="special">&);</phrase> 1542<phrase role="keyword">template</phrase><phrase role="special"><</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Rep</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Period</phrase> <phrase role="special">></phrase> 1543<phrase role="keyword">void</phrase> <phrase role="identifier">sleep_for</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">duration</phrase><phrase role="special"><</phrase> <phrase role="identifier">Rep</phrase><phrase role="special">,</phrase> <phrase role="identifier">Period</phrase> <phrase role="special">></phrase> <phrase role="keyword">const</phrase><phrase role="special">&);</phrase> 1544<phrase role="keyword">template</phrase><phrase role="special"><</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">PROPS</phrase> <phrase role="special">></phrase> 1545<phrase role="identifier">PROPS</phrase> <phrase role="special">&</phrase> <phrase role="identifier">properties</phrase><phrase role="special">();</phrase> 1546 1547<phrase role="special">}}</phrase> 1548</programlisting> 1549 <para> 1550 <bridgehead renderas="sect4" id="this_fiber_get_id_bridgehead"> 1551 <phrase id="this_fiber_get_id"/> 1552 <link linkend="this_fiber_get_id">Non-member 1553 function <code>this_fiber::get_id()</code></link> 1554</bridgehead> 1555 </para> 1556<programlisting><phrase role="preprocessor">#include</phrase> <phrase role="special"><</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">></phrase> 1557 1558<phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase> 1559<phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase> 1560 1561<phrase role="identifier">fiber</phrase><phrase role="special">::</phrase><phrase role="identifier">id</phrase> <phrase role="identifier">get_id</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 1562 1563<phrase role="special">}}</phrase> 1564</programlisting> 1565 <variablelist> 1566 <title></title> 1567 <varlistentry> 1568 <term>Returns:</term> 1569 <listitem> 1570 <para> 1571 An instance of <link linkend="class_fiber_id"><code><phrase role="identifier">fiber</phrase><phrase 1572 role="special">::</phrase><phrase role="identifier">id</phrase></code></link> that 1573 represents the currently executing fiber. 1574 </para> 1575 </listitem> 1576 </varlistentry> 1577 <varlistentry> 1578 <term>Throws:</term> 1579 <listitem> 1580 <para> 1581 Nothing. 1582 </para> 1583 </listitem> 1584 </varlistentry> 1585 </variablelist> 1586 <para> 1587 <bridgehead renderas="sect4" id="this_fiber_sleep_until_bridgehead"> 1588 <phrase id="this_fiber_sleep_until"/> 1589 <link linkend="this_fiber_sleep_until">Non-member 1590 function <code>this_fiber::sleep_until()</code></link> 1591</bridgehead> 1592 </para> 1593<programlisting><phrase role="preprocessor">#include</phrase> <phrase role="special"><</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">></phrase> 1594 1595<phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase> 1596<phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase> 1597 1598<phrase role="keyword">template</phrase><phrase role="special"><</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Clock</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Duration</phrase> <phrase role="special">></phrase> 1599<phrase role="keyword">void</phrase> <phrase role="identifier">sleep_until</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">time_point</phrase><phrase role="special"><</phrase> <phrase role="identifier">Clock</phrase><phrase role="special">,</phrase> <phrase role="identifier">Duration</phrase> <phrase role="special">></phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">abs_time</phrase><phrase role="special">);</phrase> 1600 1601<phrase role="special">}}</phrase> 1602</programlisting> 1603 <variablelist> 1604 <title></title> 1605 <varlistentry> 1606 <term>Effects:</term> 1607 <listitem> 1608 <para> 1609 Suspends the current fiber until the time point specified by <code><phrase 1610 role="identifier">abs_time</phrase></code> has been reached. 1611 </para> 1612 </listitem> 1613 </varlistentry> 1614 <varlistentry> 1615 <term>Throws:</term> 1616 <listitem> 1617 <para> 1618 timeout-related exceptions. 1619 </para> 1620 </listitem> 1621 </varlistentry> 1622 <varlistentry> 1623 <term>Note:</term> 1624 <listitem> 1625 <para> 1626 The current fiber will not resume before <code><phrase role="identifier">abs_time</phrase></code>, 1627 but there are no guarantees about how soon after <code><phrase role="identifier">abs_time</phrase></code> 1628 it might resume. 1629 </para> 1630 </listitem> 1631 </varlistentry> 1632 <varlistentry> 1633 <term>Note:</term> 1634 <listitem> 1635 <para> 1636 <quote>timeout-related exceptions</quote> are as defined in the C++ 1637 Standard, section <emphasis role="bold">30.2.4 Timing specifications 1638 [thread.req.timing]</emphasis>: <quote>A function that takes an argument 1639 which specifies a timeout will throw if, during its execution, a clock, 1640 time point, or time duration throws an exception. Such exceptions are 1641 referred to as <emphasis>timeout-related exceptions.</emphasis></quote> 1642 </para> 1643 </listitem> 1644 </varlistentry> 1645 </variablelist> 1646 <para> 1647 <bridgehead renderas="sect4" id="this_fiber_sleep_for_bridgehead"> 1648 <phrase id="this_fiber_sleep_for"/> 1649 <link linkend="this_fiber_sleep_for">Non-member 1650 function <code>this_fiber::sleep_for()</code></link> 1651</bridgehead> 1652 </para> 1653<programlisting><phrase role="preprocessor">#include</phrase> <phrase role="special"><</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">></phrase> 1654 1655<phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase> 1656<phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase> 1657 1658<phrase role="keyword">template</phrase><phrase role="special"><</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">></phrase> 1659<phrase role="keyword">void</phrase> <phrase role="identifier">sleep_for</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">duration</phrase><phrase role="special"><</phrase> <phrase role="identifier">Rep</phrase><phrase role="special">,</phrase> <phrase role="identifier">Period</phrase> <phrase role="special">></phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">rel_time</phrase><phrase role="special">);</phrase> 1660 1661<phrase role="special">}}</phrase> 1662</programlisting> 1663 <variablelist> 1664 <title></title> 1665 <varlistentry> 1666 <term>Effects:</term> 1667 <listitem> 1668 <para> 1669 Suspends the current fiber until the time duration specified by <code><phrase 1670 role="identifier">rel_time</phrase></code> has elapsed. 1671 </para> 1672 </listitem> 1673 </varlistentry> 1674 <varlistentry> 1675 <term>Throws:</term> 1676 <listitem> 1677 <para> 1678 timeout-related exceptions. 1679 </para> 1680 </listitem> 1681 </varlistentry> 1682 <varlistentry> 1683 <term>Note:</term> 1684 <listitem> 1685 <para> 1686 The current fiber will not resume before <code><phrase role="identifier">rel_time</phrase></code> 1687 has elapsed, but there are no guarantees about how soon after that 1688 it might resume. 1689 </para> 1690 </listitem> 1691 </varlistentry> 1692 </variablelist> 1693 <para> 1694 <bridgehead renderas="sect4" id="this_fiber_yield_bridgehead"> 1695 <phrase id="this_fiber_yield"/> 1696 <link linkend="this_fiber_yield">Non-member function 1697 <code>this_fiber::yield()</code></link> 1698</bridgehead> 1699 </para> 1700<programlisting><phrase role="preprocessor">#include</phrase> <phrase role="special"><</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">></phrase> 1701 1702<phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase> 1703<phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase> 1704 1705<phrase role="keyword">void</phrase> <phrase role="identifier">yield</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 1706 1707<phrase role="special">}}</phrase> 1708</programlisting> 1709 <variablelist> 1710 <title></title> 1711 <varlistentry> 1712 <term>Effects:</term> 1713 <listitem> 1714 <para> 1715 Relinquishes execution control, allowing other fibers to run. 1716 </para> 1717 </listitem> 1718 </varlistentry> 1719 <varlistentry> 1720 <term>Throws:</term> 1721 <listitem> 1722 <para> 1723 Nothing. 1724 </para> 1725 </listitem> 1726 </varlistentry> 1727 <varlistentry> 1728 <term>Note:</term> 1729 <listitem> 1730 <para> 1731 A fiber that calls <code><phrase role="identifier">yield</phrase><phrase 1732 role="special">()</phrase></code> is not suspended: it is immediately 1733 passed to the scheduler as ready to run. 1734 </para> 1735 </listitem> 1736 </varlistentry> 1737 </variablelist> 1738 <para> 1739 <bridgehead renderas="sect4" id="this_fiber_properties_bridgehead"> 1740 <phrase id="this_fiber_properties"/> 1741 <link linkend="this_fiber_properties">Non-member 1742 function <code>this_fiber::properties()</code></link> 1743</bridgehead> 1744 </para> 1745<programlisting><phrase role="preprocessor">#include</phrase> <phrase role="special"><</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">></phrase> 1746 1747<phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase> 1748<phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase> 1749 1750<phrase role="keyword">template</phrase><phrase role="special"><</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">PROPS</phrase> <phrase role="special">></phrase> 1751<phrase role="identifier">PROPS</phrase> <phrase role="special">&</phrase> <phrase role="identifier">properties</phrase><phrase role="special">();</phrase> 1752 1753<phrase role="special">}}</phrase> 1754</programlisting> 1755 <variablelist> 1756 <title></title> 1757 <varlistentry> 1758 <term>Preconditions:</term> 1759 <listitem> 1760 <para> 1761 <link linkend="use_scheduling_algorithm"><code>use_scheduling_algorithm()</code></link> has been called from 1762 this thread with a subclass of <link linkend="class_algorithm_with_properties"><code>algorithm_with_properties<></code></link> with 1763 the same template argument <code><phrase role="identifier">PROPS</phrase></code>. 1764 </para> 1765 </listitem> 1766 </varlistentry> 1767 <varlistentry> 1768 <term>Returns:</term> 1769 <listitem> 1770 <para> 1771 a reference to the scheduler properties instance for the currently 1772 running fiber. 1773 </para> 1774 </listitem> 1775 </varlistentry> 1776 <varlistentry> 1777 <term>Throws:</term> 1778 <listitem> 1779 <para> 1780 <code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase 1781 role="identifier">bad_cast</phrase></code> if <code><phrase role="identifier">use_scheduling_algorithm</phrase><phrase 1782 role="special">()</phrase></code> was called with an <code><phrase 1783 role="identifier">algorithm_with_properties</phrase></code> subclass 1784 with some other template parameter than <code><phrase role="identifier">PROPS</phrase></code>. 1785 </para> 1786 </listitem> 1787 </varlistentry> 1788 <varlistentry> 1789 <term>Note:</term> 1790 <listitem> 1791 <para> 1792 <link linkend="class_algorithm_with_properties"><code>algorithm_with_properties<></code></link> provides 1793 a way for a user-coded scheduler to associate extended properties, 1794 such as priority, with a fiber instance. This function allows access 1795 to those user-provided properties. 1796 </para> 1797 </listitem> 1798 </varlistentry> 1799 <varlistentry> 1800 <term>Note:</term> 1801 <listitem> 1802 <para> 1803 The first time this function is called from the main fiber of a thread, 1804 it may internally yield, permitting other fibers to run. 1805 </para> 1806 </listitem> 1807 </varlistentry> 1808 <varlistentry> 1809 <term>See also:</term> 1810 <listitem> 1811 <para> 1812 <link linkend="custom">Customization</link> 1813 </para> 1814 </listitem> 1815 </varlistentry> 1816 </variablelist> 1817 </section> 1818 </section> 1819 <section id="fiber.scheduling"> 1820 <title><anchor id="scheduling"/><link linkend="fiber.scheduling">Scheduling</link></title> 1821 <para> 1822 The fibers in a thread are coordinated by a fiber manager. Fibers trade control 1823 cooperatively, rather than preemptively: the currently-running fiber retains 1824 control until it invokes some operation that passes control to the manager. 1825 Each time a fiber suspends (or yields), the fiber manager consults a scheduler 1826 to determine which fiber will run next. 1827 </para> 1828 <para> 1829 <emphasis role="bold">Boost.Fiber</emphasis> provides the fiber manager, but 1830 the scheduler is a customization point. (See <link linkend="custom">Customization</link>.) 1831 </para> 1832 <para> 1833 Each thread has its own scheduler. Different threads in a process may use different 1834 schedulers. By default, <emphasis role="bold">Boost.Fiber</emphasis> implicitly 1835 instantiates <link linkend="class_round_robin"><code>round_robin</code></link> as the scheduler for each thread. 1836 </para> 1837 <para> 1838 You are explicitly permitted to code your own <link linkend="class_algorithm"><code>algorithm</code></link> subclass. 1839 For the most part, your <code><phrase role="identifier">algorithm</phrase></code> 1840 subclass need not defend against cross-thread calls: the fiber manager intercepts 1841 and defers such calls. Most <code><phrase role="identifier">algorithm</phrase></code> 1842 methods are only ever directly called from the thread whose fibers it is managing 1843 — with exceptions as documented below. 1844 </para> 1845 <para> 1846 Your <code><phrase role="identifier">algorithm</phrase></code> subclass is 1847 engaged on a particular thread by calling <link linkend="use_scheduling_algorithm"><code>use_scheduling_algorithm()</code></link>: 1848 </para> 1849<programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">thread_fn</phrase><phrase role="special">()</phrase> <phrase role="special">{</phrase> 1850 <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">use_scheduling_algorithm</phrase><phrase role="special"><</phrase> <phrase role="identifier">my_fiber_scheduler</phrase> <phrase role="special">>();</phrase> 1851 <phrase role="special">...</phrase> 1852<phrase role="special">}</phrase> 1853</programlisting> 1854 <para> 1855 A scheduler class must implement interface <link linkend="class_algorithm"><code>algorithm</code></link>. <emphasis 1856 role="bold">Boost.Fiber</emphasis> provides schedulers: <link linkend="class_round_robin"><code>round_robin</code></link>, 1857 <link linkend="class_work_stealing"><code>work_stealing</code></link>, <link linkend="class_numa_work_stealing"><code>numa::work_stealing</code></link> and 1858 <link linkend="class_shared_work"><code>shared_work</code></link>. 1859 </para> 1860<programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">thread</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">uint32_t</phrase> <phrase role="identifier">thread_count</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase> 1861 <phrase role="comment">// thread registers itself at work-stealing scheduler</phrase> 1862 <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">use_scheduling_algorithm</phrase><phrase role="special"><</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">algo</phrase><phrase role="special">::</phrase><phrase role="identifier">work_stealing</phrase> <phrase role="special">>(</phrase> <phrase role="identifier">thread_count</phrase><phrase role="special">);</phrase> 1863 <phrase role="special">...</phrase> 1864<phrase role="special">}</phrase> 1865 1866<phrase role="comment">// count of logical cpus</phrase> 1867<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">uint32_t</phrase> <phrase role="identifier">thread_count</phrase> <phrase role="special">=</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">thread</phrase><phrase role="special">::</phrase><phrase role="identifier">hardware_concurrency</phrase><phrase role="special">();</phrase> 1868<phrase role="comment">// start worker-threads first</phrase> 1869<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">vector</phrase><phrase role="special"><</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">thread</phrase> <phrase role="special">></phrase> <phrase role="identifier">threads</phrase><phrase role="special">;</phrase> 1870<phrase role="keyword">for</phrase> <phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">uint32_t</phrase> <phrase role="identifier">i</phrase> <phrase role="special">=</phrase> <phrase role="number">1</phrase> <phrase role="comment">/* count start-thread */</phrase><phrase role="special">;</phrase> <phrase role="identifier">i</phrase> <phrase role="special"><</phrase> <phrase role="identifier">thread_count</phrase><phrase role="special">;</phrase> <phrase role="special">++</phrase><phrase role="identifier">i</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase> 1871 <phrase role="comment">// spawn thread</phrase> 1872 <phrase role="identifier">threads</phrase><phrase role="special">.</phrase><phrase role="identifier">emplace_back</phrase><phrase role="special">(</phrase> <phrase role="identifier">thread</phrase><phrase role="special">,</phrase> <phrase role="identifier">thread_count</phrase><phrase role="special">);</phrase> 1873<phrase role="special">}</phrase> 1874<phrase role="comment">// start-thread registers itself at work-stealing scheduler</phrase> 1875<phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">use_scheduling_algorithm</phrase><phrase role="special"><</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">algo</phrase><phrase role="special">::</phrase><phrase role="identifier">work_stealing</phrase> <phrase role="special">>(</phrase> <phrase role="identifier">thread_count</phrase><phrase role="special">);</phrase> 1876<phrase role="special">...</phrase> 1877</programlisting> 1878 <para> 1879 The example spawns as many threads as <code><phrase role="identifier">std</phrase><phrase 1880 role="special">::</phrase><phrase role="identifier">thread</phrase><phrase 1881 role="special">::</phrase><phrase role="identifier">hardware_concurrency</phrase><phrase 1882 role="special">()</phrase></code> returns. Each thread runs a <link linkend="class_work_stealing"><code>work_stealing</code></link> scheduler. 1883 Each instance of this scheduler needs to know how many threads run the work-stealing 1884 scheduler in the program. If the local queue of one thread runs out of ready 1885 fibers, the thread tries to steal a ready fiber from another thread running 1886 this scheduler. 1887 </para> 1888 <para> 1889 <bridgehead renderas="sect4" id="class_algorithm_bridgehead"> 1890 <phrase id="class_algorithm"/> 1891 <link linkend="class_algorithm">Class <code>algorithm</code></link> 1892</bridgehead> 1893 </para> 1894 <para> 1895 <code><phrase role="identifier">algorithm</phrase></code> is the abstract base 1896 class defining the interface that a fiber scheduler must implement. 1897 </para> 1898<programlisting><phrase role="preprocessor">#include</phrase> <phrase role="special"><</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">></phrase> 1899 1900<phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase> 1901<phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase> 1902<phrase role="keyword">namespace</phrase> <phrase role="identifier">algo</phrase> <phrase role="special">{</phrase> 1903 1904<phrase role="keyword">struct</phrase> <phrase role="identifier">algorithm</phrase> <phrase role="special">{</phrase> 1905 <phrase role="keyword">virtual</phrase> <phrase role="special">~</phrase><phrase role="identifier">algorithm</phrase><phrase role="special">();</phrase> 1906 1907 <phrase role="keyword">virtual</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">awakened</phrase><phrase role="special">(</phrase> <phrase role="identifier">context</phrase> <phrase role="special">*)</phrase> <phrase role="keyword">noexcept</phrase> <phrase role="special">=</phrase> <phrase role="number">0</phrase><phrase role="special">;</phrase> 1908 1909 <phrase role="keyword">virtual</phrase> <phrase role="identifier">context</phrase> <phrase role="special">*</phrase> <phrase role="identifier">pick_next</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase> <phrase role="special">=</phrase> <phrase role="number">0</phrase><phrase role="special">;</phrase> 1910 1911 <phrase role="keyword">virtual</phrase> <phrase role="keyword">bool</phrase> <phrase role="identifier">has_ready_fibers</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase> <phrase role="special">=</phrase> <phrase role="number">0</phrase><phrase role="special">;</phrase> 1912 1913 <phrase role="keyword">virtual</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">suspend_until</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">steady_clock</phrase><phrase role="special">::</phrase><phrase role="identifier">time_point</phrase> <phrase role="keyword">const</phrase><phrase role="special">&)</phrase> <phrase role="keyword">noexcept</phrase> <phrase role="special">=</phrase> <phrase role="number">0</phrase><phrase role="special">;</phrase> 1914 1915 <phrase role="keyword">virtual</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">notify</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase> <phrase role="special">=</phrase> <phrase role="number">0</phrase><phrase role="special">;</phrase> 1916<phrase role="special">};</phrase> 1917 1918<phrase role="special">}}}</phrase> 1919</programlisting> 1920 <para> 1921 <bridgehead renderas="sect4" id="algorithm_awakened_bridgehead"> 1922 <phrase id="algorithm_awakened"/> 1923 <link linkend="algorithm_awakened">Member function 1924 <code>awakened</code>()</link> 1925</bridgehead> 1926 </para> 1927<programlisting><phrase role="keyword">virtual</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">awakened</phrase><phrase role="special">(</phrase> <phrase role="identifier">context</phrase> <phrase role="special">*</phrase> <phrase role="identifier">f</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase> <phrase role="special">=</phrase> <phrase role="number">0</phrase><phrase role="special">;</phrase> 1928</programlisting> 1929 <variablelist> 1930 <title></title> 1931 <varlistentry> 1932 <term>Effects:</term> 1933 <listitem> 1934 <para> 1935 Informs the scheduler that fiber <code><phrase role="identifier">f</phrase></code> 1936 is ready to run. Fiber <code><phrase role="identifier">f</phrase></code> 1937 might be newly launched, or it might have been blocked but has just been 1938 awakened, or it might have called <link linkend="this_fiber_yield"><code>this_fiber::yield()</code></link>. 1939 </para> 1940 </listitem> 1941 </varlistentry> 1942 <varlistentry> 1943 <term>Note:</term> 1944 <listitem> 1945 <para> 1946 This method advises the scheduler to add fiber <code><phrase role="identifier">f</phrase></code> 1947 to its collection of fibers ready to run. A typical scheduler implementation 1948 places <code><phrase role="identifier">f</phrase></code> into a queue. 1949 </para> 1950 </listitem> 1951 </varlistentry> 1952 <varlistentry> 1953 <term>See also:</term> 1954 <listitem> 1955 <para> 1956 <link linkend="class_round_robin"><code>round_robin</code></link> 1957 </para> 1958 </listitem> 1959 </varlistentry> 1960 </variablelist> 1961 <para> 1962 <bridgehead renderas="sect4" id="algorithm_pick_next_bridgehead"> 1963 <phrase id="algorithm_pick_next"/> 1964 <link linkend="algorithm_pick_next">Member 1965 function <code>pick_next</code>()</link> 1966</bridgehead> 1967 </para> 1968<programlisting><phrase role="keyword">virtual</phrase> <phrase role="identifier">context</phrase> <phrase role="special">*</phrase> <phrase role="identifier">pick_next</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase> <phrase role="special">=</phrase> <phrase role="number">0</phrase><phrase role="special">;</phrase> 1969</programlisting> 1970 <variablelist> 1971 <title></title> 1972 <varlistentry> 1973 <term>Returns:</term> 1974 <listitem> 1975 <para> 1976 the fiber which is to be resumed next, or <code><phrase role="keyword">nullptr</phrase></code> 1977 if there is no ready fiber. 1978 </para> 1979 </listitem> 1980 </varlistentry> 1981 <varlistentry> 1982 <term>Note:</term> 1983 <listitem> 1984 <para> 1985 This is where the scheduler actually specifies the fiber which is to 1986 run next. A typical scheduler implementation chooses the head of the 1987 ready queue. 1988 </para> 1989 </listitem> 1990 </varlistentry> 1991 <varlistentry> 1992 <term>See also:</term> 1993 <listitem> 1994 <para> 1995 <link linkend="class_round_robin"><code>round_robin</code></link> 1996 </para> 1997 </listitem> 1998 </varlistentry> 1999 </variablelist> 2000 <para> 2001 <bridgehead renderas="sect4" id="algorithm_has_ready_fibers_bridgehead"> 2002 <phrase id="algorithm_has_ready_fibers"/> 2003 <link linkend="algorithm_has_ready_fibers">Member 2004 function <code>has_ready_fibers</code>()</link> 2005</bridgehead> 2006 </para> 2007<programlisting><phrase role="keyword">virtual</phrase> <phrase role="keyword">bool</phrase> <phrase role="identifier">has_ready_fibers</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase> <phrase role="special">=</phrase> <phrase role="number">0</phrase><phrase role="special">;</phrase> 2008</programlisting> 2009 <variablelist> 2010 <title></title> 2011 <varlistentry> 2012 <term>Returns:</term> 2013 <listitem> 2014 <para> 2015 <code><phrase role="keyword">true</phrase></code> if scheduler has fibers 2016 ready to run. 2017 </para> 2018 </listitem> 2019 </varlistentry> 2020 </variablelist> 2021 <para> 2022 <bridgehead renderas="sect4" id="algorithm_suspend_until_bridgehead"> 2023 <phrase id="algorithm_suspend_until"/> 2024 <link linkend="algorithm_suspend_until">Member 2025 function <code>suspend_until</code>()</link> 2026</bridgehead> 2027 </para> 2028<programlisting><phrase role="keyword">virtual</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">suspend_until</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">steady_clock</phrase><phrase role="special">::</phrase><phrase role="identifier">time_point</phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">abs_time</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase> <phrase role="special">=</phrase> <phrase role="number">0</phrase><phrase role="special">;</phrase> 2029</programlisting> 2030 <variablelist> 2031 <title></title> 2032 <varlistentry> 2033 <term>Effects:</term> 2034 <listitem> 2035 <para> 2036 Informs the scheduler that no fiber will be ready until time-point <code><phrase 2037 role="identifier">abs_time</phrase></code>. 2038 </para> 2039 </listitem> 2040 </varlistentry> 2041 <varlistentry> 2042 <term>Note:</term> 2043 <listitem> 2044 <para> 2045 This method allows a custom scheduler to yield control to the containing 2046 environment in whatever way makes sense. The fiber manager is stating 2047 that <code><phrase role="identifier">suspend_until</phrase><phrase role="special">()</phrase></code> 2048 need not return until <code><phrase role="identifier">abs_time</phrase></code> 2049 — or <link linkend="algorithm_notify"><code>algorithm::notify()</code></link> is called — whichever comes first. 2050 The interaction with <code><phrase role="identifier">notify</phrase><phrase 2051 role="special">()</phrase></code> means that, for instance, calling 2052 <ulink url="http://en.cppreference.com/w/cpp/thread/sleep_until"><code><phrase 2053 role="identifier">std</phrase><phrase role="special">::</phrase><phrase 2054 role="identifier">this_thread</phrase><phrase role="special">::</phrase><phrase 2055 role="identifier">sleep_until</phrase><phrase role="special">(</phrase><phrase 2056 role="identifier">abs_time</phrase><phrase role="special">)</phrase></code></ulink> 2057 would be too simplistic. <link linkend="round_robin_suspend_until"><code>round_robin::suspend_until()</code></link> uses 2058 a <ulink url="http://en.cppreference.com/w/cpp/thread/condition_variable"><code><phrase 2059 role="identifier">std</phrase><phrase role="special">::</phrase><phrase 2060 role="identifier">condition_variable</phrase></code></ulink> to coordinate 2061 with <link linkend="round_robin_notify"><code>round_robin::notify()</code></link>. 2062 </para> 2063 </listitem> 2064 </varlistentry> 2065 <varlistentry> 2066 <term>Note:</term> 2067 <listitem> 2068 <para> 2069 Given that <code><phrase role="identifier">notify</phrase><phrase role="special">()</phrase></code> 2070 might be called from another thread, your <code><phrase role="identifier">suspend_until</phrase><phrase 2071 role="special">()</phrase></code> implementation — like the rest of your 2072 <code><phrase role="identifier">algorithm</phrase></code> implementation 2073 — must guard any data it shares with your <code><phrase role="identifier">notify</phrase><phrase 2074 role="special">()</phrase></code> implementation. 2075 </para> 2076 </listitem> 2077 </varlistentry> 2078 </variablelist> 2079 <para> 2080 <bridgehead renderas="sect4" id="algorithm_notify_bridgehead"> 2081 <phrase id="algorithm_notify"/> 2082 <link linkend="algorithm_notify">Member function 2083 <code>notify</code>()</link> 2084</bridgehead> 2085 </para> 2086<programlisting><phrase role="keyword">virtual</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">notify</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase> <phrase role="special">=</phrase> <phrase role="number">0</phrase><phrase role="special">;</phrase> 2087</programlisting> 2088 <variablelist> 2089 <title></title> 2090 <varlistentry> 2091 <term>Effects:</term> 2092 <listitem> 2093 <para> 2094 Requests the scheduler to return from a pending call to <link linkend="algorithm_suspend_until"><code>algorithm::suspend_until()</code></link>. 2095 </para> 2096 </listitem> 2097 </varlistentry> 2098 <varlistentry> 2099 <term>Note:</term> 2100 <listitem> 2101 <para> 2102 Alone among the <code><phrase role="identifier">algorithm</phrase></code> 2103 methods, <code><phrase role="identifier">notify</phrase><phrase role="special">()</phrase></code> 2104 may be called from another thread. Your <code><phrase role="identifier">notify</phrase><phrase 2105 role="special">()</phrase></code> implementation must guard any data 2106 it shares with the rest of your <code><phrase role="identifier">algorithm</phrase></code> 2107 implementation. 2108 </para> 2109 </listitem> 2110 </varlistentry> 2111 </variablelist> 2112 <para> 2113 <bridgehead renderas="sect4" id="class_round_robin_bridgehead"> 2114 <phrase id="class_round_robin"/> 2115 <link linkend="class_round_robin">Class <code>round_robin</code></link> 2116</bridgehead> 2117 </para> 2118 <para> 2119 This class implements <link linkend="class_algorithm"><code>algorithm</code></link>, scheduling fibers in round-robin 2120 fashion. 2121 </para> 2122<programlisting><phrase role="preprocessor">#include</phrase> <phrase role="special"><</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">></phrase> 2123 2124<phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase> 2125<phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase> 2126<phrase role="keyword">namespace</phrase> <phrase role="identifier">algo</phrase> <phrase role="special">{</phrase> 2127 2128<phrase role="keyword">class</phrase> <phrase role="identifier">round_robin</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <phrase role="identifier">algorithm</phrase> <phrase role="special">{</phrase> 2129 <phrase role="keyword">virtual</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">awakened</phrase><phrase role="special">(</phrase> <phrase role="identifier">context</phrase> <phrase role="special">*)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 2130 2131 <phrase role="keyword">virtual</phrase> <phrase role="identifier">context</phrase> <phrase role="special">*</phrase> <phrase role="identifier">pick_next</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 2132 2133 <phrase role="keyword">virtual</phrase> <phrase role="keyword">bool</phrase> <phrase role="identifier">has_ready_fibers</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 2134 2135 <phrase role="keyword">virtual</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">suspend_until</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">steady_clock</phrase><phrase role="special">::</phrase><phrase role="identifier">time_point</phrase> <phrase role="keyword">const</phrase><phrase role="special">&)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 2136 2137 <phrase role="keyword">virtual</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">notify</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 2138<phrase role="special">};</phrase> 2139 2140<phrase role="special">}}}</phrase> 2141</programlisting> 2142 <para> 2143 <bridgehead renderas="sect4" id="round_robin_awakened_bridgehead"> 2144 <phrase id="round_robin_awakened"/> 2145 <link linkend="round_robin_awakened">Member 2146 function <code>awakened</code>()</link> 2147</bridgehead> 2148 </para> 2149<programlisting><phrase role="keyword">virtual</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">awakened</phrase><phrase role="special">(</phrase> <phrase role="identifier">context</phrase> <phrase role="special">*</phrase> <phrase role="identifier">f</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 2150</programlisting> 2151 <variablelist> 2152 <title></title> 2153 <varlistentry> 2154 <term>Effects:</term> 2155 <listitem> 2156 <para> 2157 Enqueues fiber <code><phrase role="identifier">f</phrase></code> onto 2158 a ready queue. 2159 </para> 2160 </listitem> 2161 </varlistentry> 2162 <varlistentry> 2163 <term>Throws:</term> 2164 <listitem> 2165 <para> 2166 Nothing. 2167 </para> 2168 </listitem> 2169 </varlistentry> 2170 </variablelist> 2171 <para> 2172 <bridgehead renderas="sect4" id="round_robin_pick_next_bridgehead"> 2173 <phrase id="round_robin_pick_next"/> 2174 <link linkend="round_robin_pick_next">Member 2175 function <code>pick_next</code>()</link> 2176</bridgehead> 2177 </para> 2178<programlisting><phrase role="keyword">virtual</phrase> <phrase role="identifier">context</phrase> <phrase role="special">*</phrase> <phrase role="identifier">pick_next</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 2179</programlisting> 2180 <variablelist> 2181 <title></title> 2182 <varlistentry> 2183 <term>Returns:</term> 2184 <listitem> 2185 <para> 2186 the fiber at the head of the ready queue, or <code><phrase role="keyword">nullptr</phrase></code> 2187 if the queue is empty. 2188 </para> 2189 </listitem> 2190 </varlistentry> 2191 <varlistentry> 2192 <term>Throws:</term> 2193 <listitem> 2194 <para> 2195 Nothing. 2196 </para> 2197 </listitem> 2198 </varlistentry> 2199 <varlistentry> 2200 <term>Note:</term> 2201 <listitem> 2202 <para> 2203 Placing ready fibers onto the tail of a queue, and returning them from 2204 the head of that queue, shares the thread between ready fibers in round-robin 2205 fashion. 2206 </para> 2207 </listitem> 2208 </varlistentry> 2209 </variablelist> 2210 <para> 2211 <bridgehead renderas="sect4" id="round_robin_has_ready_fibers_bridgehead"> 2212 <phrase id="round_robin_has_ready_fibers"/> 2213 <link linkend="round_robin_has_ready_fibers">Member 2214 function <code>has_ready_fibers</code>()</link> 2215</bridgehead> 2216 </para> 2217<programlisting><phrase role="keyword">virtual</phrase> <phrase role="keyword">bool</phrase> <phrase role="identifier">has_ready_fibers</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 2218</programlisting> 2219 <variablelist> 2220 <title></title> 2221 <varlistentry> 2222 <term>Returns:</term> 2223 <listitem> 2224 <para> 2225 <code><phrase role="keyword">true</phrase></code> if scheduler has fibers 2226 ready to run. 2227 </para> 2228 </listitem> 2229 </varlistentry> 2230 <varlistentry> 2231 <term>Throws:</term> 2232 <listitem> 2233 <para> 2234 Nothing. 2235 </para> 2236 </listitem> 2237 </varlistentry> 2238 </variablelist> 2239 <para> 2240 <bridgehead renderas="sect4" id="round_robin_suspend_until_bridgehead"> 2241 <phrase id="round_robin_suspend_until"/> 2242 <link linkend="round_robin_suspend_until">Member 2243 function <code>suspend_until</code>()</link> 2244</bridgehead> 2245 </para> 2246<programlisting><phrase role="keyword">virtual</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">suspend_until</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">steady_clock</phrase><phrase role="special">::</phrase><phrase role="identifier">time_point</phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">abs_time</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 2247</programlisting> 2248 <variablelist> 2249 <title></title> 2250 <varlistentry> 2251 <term>Effects:</term> 2252 <listitem> 2253 <para> 2254 Informs <code><phrase role="identifier">round_robin</phrase></code> that 2255 no ready fiber will be available until time-point <code><phrase role="identifier">abs_time</phrase></code>. 2256 This implementation blocks in <ulink url="http://en.cppreference.com/w/cpp/thread/condition_variable/wait_until"><code><phrase 2257 role="identifier">std</phrase><phrase role="special">::</phrase><phrase 2258 role="identifier">condition_variable</phrase><phrase role="special">::</phrase><phrase 2259 role="identifier">wait_until</phrase><phrase role="special">()</phrase></code></ulink>. 2260 </para> 2261 </listitem> 2262 </varlistentry> 2263 <varlistentry> 2264 <term>Throws:</term> 2265 <listitem> 2266 <para> 2267 Nothing. 2268 </para> 2269 </listitem> 2270 </varlistentry> 2271 </variablelist> 2272 <para> 2273 <bridgehead renderas="sect4" id="round_robin_notify_bridgehead"> 2274 <phrase id="round_robin_notify"/> 2275 <link linkend="round_robin_notify">Member function 2276 <code>notify</code>()</link> 2277</bridgehead> 2278 </para> 2279<programlisting><phrase role="keyword">virtual</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">notify</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase> <phrase role="special">=</phrase> <phrase role="number">0</phrase><phrase role="special">;</phrase> 2280</programlisting> 2281 <variablelist> 2282 <title></title> 2283 <varlistentry> 2284 <term>Effects:</term> 2285 <listitem> 2286 <para> 2287 Wake up a pending call to <link linkend="round_robin_suspend_until"><code>round_robin::suspend_until()</code></link>, 2288 some fibers might be ready. This implementation wakes <code><phrase role="identifier">suspend_until</phrase><phrase 2289 role="special">()</phrase></code> via <ulink url="http://en.cppreference.com/w/cpp/thread/condition_variable/notify_all"><code><phrase 2290 role="identifier">std</phrase><phrase role="special">::</phrase><phrase 2291 role="identifier">condition_variable</phrase><phrase role="special">::</phrase><phrase 2292 role="identifier">notify_all</phrase><phrase role="special">()</phrase></code></ulink>. 2293 </para> 2294 </listitem> 2295 </varlistentry> 2296 <varlistentry> 2297 <term>Throws:</term> 2298 <listitem> 2299 <para> 2300 Nothing. 2301 </para> 2302 </listitem> 2303 </varlistentry> 2304 </variablelist> 2305 <para> 2306 <bridgehead renderas="sect4" id="class_work_stealing_bridgehead"> 2307 <phrase id="class_work_stealing"/> 2308 <link linkend="class_work_stealing">Class <code>work_stealing</code></link> 2309</bridgehead> 2310 </para> 2311 <para> 2312 This class implements <link linkend="class_algorithm"><code>algorithm</code></link>; if the local ready-queue runs 2313 out of ready fibers, ready fibers are stolen from other schedulers.<sbr/> The 2314 victim scheduler (from which a ready fiber is stolen) is selected at random. 2315 </para> 2316 <note> 2317 <para> 2318 Worker-threads are stored in a static variable, dynamically adding/removing 2319 worker threads is not supported. 2320 </para> 2321 </note> 2322<programlisting><phrase role="preprocessor">#include</phrase> <phrase role="special"><</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">fiber</phrase><phrase role="special">/</phrase><phrase role="identifier">algo</phrase><phrase role="special">/</phrase><phrase role="identifier">work_stealing</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">></phrase> 2323 2324<phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase> 2325<phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase> 2326<phrase role="keyword">namespace</phrase> <phrase role="identifier">algo</phrase> <phrase role="special">{</phrase> 2327 2328<phrase role="keyword">class</phrase> <phrase role="identifier">work_stealing</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <phrase role="identifier">algorithm</phrase> <phrase role="special">{</phrase> 2329<phrase role="keyword">public</phrase><phrase role="special">:</phrase> 2330 <phrase role="identifier">work_stealing</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">uint32_t</phrase> <phrase role="identifier">thread_count</phrase><phrase role="special">,</phrase> <phrase role="keyword">bool</phrase> <phrase role="identifier">suspend</phrase> <phrase role="special">=</phrase> <phrase role="keyword">false</phrase><phrase role="special">);</phrase> 2331 2332 <phrase role="identifier">work_stealing</phrase><phrase role="special">(</phrase> <phrase role="identifier">work_stealing</phrase> <phrase role="keyword">const</phrase><phrase role="special">&)</phrase> <phrase role="special">=</phrase> <phrase role="keyword">delete</phrase><phrase role="special">;</phrase> 2333 <phrase role="identifier">work_stealing</phrase><phrase role="special">(</phrase> <phrase role="identifier">work_stealing</phrase> <phrase role="special">&&)</phrase> <phrase role="special">=</phrase> <phrase role="keyword">delete</phrase><phrase role="special">;</phrase> 2334 2335 <phrase role="identifier">work_stealing</phrase> <phrase role="special">&</phrase> <phrase role="keyword">operator</phrase><phrase role="special">=(</phrase> <phrase role="identifier">work_stealing</phrase> <phrase role="keyword">const</phrase><phrase role="special">&)</phrase> <phrase role="special">=</phrase> <phrase role="keyword">delete</phrase><phrase role="special">;</phrase> 2336 <phrase role="identifier">work_stealing</phrase> <phrase role="special">&</phrase> <phrase role="keyword">operator</phrase><phrase role="special">=(</phrase> <phrase role="identifier">work_stealing</phrase> <phrase role="special">&&)</phrase> <phrase role="special">=</phrase> <phrase role="keyword">delete</phrase><phrase role="special">;</phrase> 2337 2338 <phrase role="keyword">virtual</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">awakened</phrase><phrase role="special">(</phrase> <phrase role="identifier">context</phrase> <phrase role="special">*)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 2339 2340 <phrase role="keyword">virtual</phrase> <phrase role="identifier">context</phrase> <phrase role="special">*</phrase> <phrase role="identifier">pick_next</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 2341 2342 <phrase role="keyword">virtual</phrase> <phrase role="keyword">bool</phrase> <phrase role="identifier">has_ready_fibers</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 2343 2344 <phrase role="keyword">virtual</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">suspend_until</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">steady_clock</phrase><phrase role="special">::</phrase><phrase role="identifier">time_point</phrase> <phrase role="keyword">const</phrase><phrase role="special">&)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 2345 2346 <phrase role="keyword">virtual</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">notify</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 2347<phrase role="special">};</phrase> 2348 2349<phrase role="special">}}}</phrase> 2350</programlisting> 2351 <bridgehead renderas="sect3" id="fiber.scheduling.h0"> 2352 <phrase id="fiber.scheduling.constructor"/><link linkend="fiber.scheduling.constructor">Constructor</link> 2353 </bridgehead> 2354<programlisting><phrase role="identifier">work_stealing</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">uint32_t</phrase> <phrase role="identifier">thread_count</phrase><phrase role="special">,</phrase> <phrase role="keyword">bool</phrase> <phrase role="identifier">suspend</phrase> <phrase role="special">=</phrase> <phrase role="keyword">false</phrase><phrase role="special">);</phrase> 2355</programlisting> 2356 <variablelist> 2357 <title></title> 2358 <varlistentry> 2359 <term>Effects:</term> 2360 <listitem> 2361 <para> 2362 Constructs work-stealing scheduling algorithm. <code><phrase role="identifier">thread_count</phrase></code> 2363 represents the number of threads running this algorithm. 2364 </para> 2365 </listitem> 2366 </varlistentry> 2367 <varlistentry> 2368 <term>Throws:</term> 2369 <listitem> 2370 <para> 2371 <code><phrase role="identifier">system_error</phrase></code> 2372 </para> 2373 </listitem> 2374 </varlistentry> 2375 <varlistentry> 2376 <term>Note:</term> 2377 <listitem> 2378 <para> 2379 If <code><phrase role="identifier">suspend</phrase></code> is set to 2380 <code><phrase role="keyword">true</phrase></code>, then the scheduler 2381 suspends if no ready fiber could be stolen. The scheduler will by woken 2382 up if a sleeping fiber times out or it was notified from remote (other 2383 thread or fiber scheduler). 2384 </para> 2385 </listitem> 2386 </varlistentry> 2387 </variablelist> 2388 <para> 2389 <bridgehead renderas="sect4" id="work_stealing_awakened_bridgehead"> 2390 <phrase id="work_stealing_awakened"/> 2391 <link linkend="work_stealing_awakened">Member 2392 function <code>awakened</code>()</link> 2393</bridgehead> 2394 </para> 2395<programlisting><phrase role="keyword">virtual</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">awakened</phrase><phrase role="special">(</phrase> <phrase role="identifier">context</phrase> <phrase role="special">*</phrase> <phrase role="identifier">f</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 2396</programlisting> 2397 <variablelist> 2398 <title></title> 2399 <varlistentry> 2400 <term>Effects:</term> 2401 <listitem> 2402 <para> 2403 Enqueues fiber <code><phrase role="identifier">f</phrase></code> onto 2404 the shared ready queue. 2405 </para> 2406 </listitem> 2407 </varlistentry> 2408 <varlistentry> 2409 <term>Throws:</term> 2410 <listitem> 2411 <para> 2412 Nothing. 2413 </para> 2414 </listitem> 2415 </varlistentry> 2416 </variablelist> 2417 <para> 2418 <bridgehead renderas="sect4" id="work_stealing_pick_next_bridgehead"> 2419 <phrase id="work_stealing_pick_next"/> 2420 <link linkend="work_stealing_pick_next">Member 2421 function <code>pick_next</code>()</link> 2422</bridgehead> 2423 </para> 2424<programlisting><phrase role="keyword">virtual</phrase> <phrase role="identifier">context</phrase> <phrase role="special">*</phrase> <phrase role="identifier">pick_next</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 2425</programlisting> 2426 <variablelist> 2427 <title></title> 2428 <varlistentry> 2429 <term>Returns:</term> 2430 <listitem> 2431 <para> 2432 the fiber at the head of the ready queue, or <code><phrase role="keyword">nullptr</phrase></code> 2433 if the queue is empty. 2434 </para> 2435 </listitem> 2436 </varlistentry> 2437 <varlistentry> 2438 <term>Throws:</term> 2439 <listitem> 2440 <para> 2441 Nothing. 2442 </para> 2443 </listitem> 2444 </varlistentry> 2445 <varlistentry> 2446 <term>Note:</term> 2447 <listitem> 2448 <para> 2449 Placing ready fibers onto the tail of the sahred queue, and returning 2450 them from the head of that queue, shares the thread between ready fibers 2451 in round-robin fashion. 2452 </para> 2453 </listitem> 2454 </varlistentry> 2455 </variablelist> 2456 <para> 2457 <bridgehead renderas="sect4" id="work_stealing_has_ready_fibers_bridgehead"> 2458 <phrase id="work_stealing_has_ready_fibers"/> 2459 <link linkend="work_stealing_has_ready_fibers">Member 2460 function <code>has_ready_fibers</code>()</link> 2461</bridgehead> 2462 </para> 2463<programlisting><phrase role="keyword">virtual</phrase> <phrase role="keyword">bool</phrase> <phrase role="identifier">has_ready_fibers</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 2464</programlisting> 2465 <variablelist> 2466 <title></title> 2467 <varlistentry> 2468 <term>Returns:</term> 2469 <listitem> 2470 <para> 2471 <code><phrase role="keyword">true</phrase></code> if scheduler has fibers 2472 ready to run. 2473 </para> 2474 </listitem> 2475 </varlistentry> 2476 <varlistentry> 2477 <term>Throws:</term> 2478 <listitem> 2479 <para> 2480 Nothing. 2481 </para> 2482 </listitem> 2483 </varlistentry> 2484 </variablelist> 2485 <para> 2486 <bridgehead renderas="sect4" id="work_stealing_suspend_until_bridgehead"> 2487 <phrase id="work_stealing_suspend_until"/> 2488 <link linkend="work_stealing_suspend_until">Member 2489 function <code>suspend_until</code>()</link> 2490</bridgehead> 2491 </para> 2492<programlisting><phrase role="keyword">virtual</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">suspend_until</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">steady_clock</phrase><phrase role="special">::</phrase><phrase role="identifier">time_point</phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">abs_time</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 2493</programlisting> 2494 <variablelist> 2495 <title></title> 2496 <varlistentry> 2497 <term>Effects:</term> 2498 <listitem> 2499 <para> 2500 Informs <code><phrase role="identifier">work_stealing</phrase></code> 2501 that no ready fiber will be available until time-point <code><phrase 2502 role="identifier">abs_time</phrase></code>. This implementation blocks 2503 in <ulink url="http://en.cppreference.com/w/cpp/thread/condition_variable/wait_until"><code><phrase 2504 role="identifier">std</phrase><phrase role="special">::</phrase><phrase 2505 role="identifier">condition_variable</phrase><phrase role="special">::</phrase><phrase 2506 role="identifier">wait_until</phrase><phrase role="special">()</phrase></code></ulink>. 2507 </para> 2508 </listitem> 2509 </varlistentry> 2510 <varlistentry> 2511 <term>Throws:</term> 2512 <listitem> 2513 <para> 2514 Nothing. 2515 </para> 2516 </listitem> 2517 </varlistentry> 2518 </variablelist> 2519 <para> 2520 <bridgehead renderas="sect4" id="work_stealing_notify_bridgehead"> 2521 <phrase id="work_stealing_notify"/> 2522 <link linkend="work_stealing_notify">Member 2523 function <code>notify</code>()</link> 2524</bridgehead> 2525 </para> 2526<programlisting><phrase role="keyword">virtual</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">notify</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase> <phrase role="special">=</phrase> <phrase role="number">0</phrase><phrase role="special">;</phrase> 2527</programlisting> 2528 <variablelist> 2529 <title></title> 2530 <varlistentry> 2531 <term>Effects:</term> 2532 <listitem> 2533 <para> 2534 Wake up a pending call to <link linkend="work_stealing_suspend_until"><code>work_stealing::suspend_until()</code></link>, 2535 some fibers might be ready. This implementation wakes <code><phrase role="identifier">suspend_until</phrase><phrase 2536 role="special">()</phrase></code> via <ulink url="http://en.cppreference.com/w/cpp/thread/condition_variable/notify_all"><code><phrase 2537 role="identifier">std</phrase><phrase role="special">::</phrase><phrase 2538 role="identifier">condition_variable</phrase><phrase role="special">::</phrase><phrase 2539 role="identifier">notify_all</phrase><phrase role="special">()</phrase></code></ulink>. 2540 </para> 2541 </listitem> 2542 </varlistentry> 2543 <varlistentry> 2544 <term>Throws:</term> 2545 <listitem> 2546 <para> 2547 Nothing. 2548 </para> 2549 </listitem> 2550 </varlistentry> 2551 </variablelist> 2552 <para> 2553 <bridgehead renderas="sect4" id="class_shared_work_bridgehead"> 2554 <phrase id="class_shared_work"/> 2555 <link linkend="class_shared_work">Class <code>shared_work</code></link> 2556</bridgehead> 2557 </para> 2558 <note> 2559 <para> 2560 Because of the non-locality of data, <emphasis>shared_work</emphasis> is 2561 less performant than <link linkend="class_work_stealing"><code>work_stealing</code></link>. 2562 </para> 2563 </note> 2564 <para> 2565 This class implements <link linkend="class_algorithm"><code>algorithm</code></link>, scheduling fibers in round-robin 2566 fashion. Ready fibers are shared between all instances (running on different 2567 threads) of shared_work, thus the work is distributed equally over all threads. 2568 </para> 2569 <note> 2570 <para> 2571 Worker-threads are stored in a static variable, dynamically adding/removing 2572 worker threads is not supported. 2573 </para> 2574 </note> 2575<programlisting><phrase role="preprocessor">#include</phrase> <phrase role="special"><</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">></phrase> 2576 2577<phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase> 2578<phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase> 2579<phrase role="keyword">namespace</phrase> <phrase role="identifier">algo</phrase> <phrase role="special">{</phrase> 2580 2581<phrase role="keyword">class</phrase> <phrase role="identifier">shared_work</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <phrase role="identifier">algorithm</phrase> <phrase role="special">{</phrase> 2582 <phrase role="keyword">virtual</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">awakened</phrase><phrase role="special">(</phrase> <phrase role="identifier">context</phrase> <phrase role="special">*)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 2583 2584 <phrase role="keyword">virtual</phrase> <phrase role="identifier">context</phrase> <phrase role="special">*</phrase> <phrase role="identifier">pick_next</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 2585 2586 <phrase role="keyword">virtual</phrase> <phrase role="keyword">bool</phrase> <phrase role="identifier">has_ready_fibers</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 2587 2588 <phrase role="keyword">virtual</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">suspend_until</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">steady_clock</phrase><phrase role="special">::</phrase><phrase role="identifier">time_point</phrase> <phrase role="keyword">const</phrase><phrase role="special">&)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 2589 2590 <phrase role="keyword">virtual</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">notify</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 2591<phrase role="special">};</phrase> 2592 2593<phrase role="special">}}}</phrase> 2594</programlisting> 2595 <para> 2596 <bridgehead renderas="sect4" id="shared_work_awakened_bridgehead"> 2597 <phrase id="shared_work_awakened"/> 2598 <link linkend="shared_work_awakened">Member 2599 function <code>awakened</code>()</link> 2600</bridgehead> 2601 </para> 2602<programlisting><phrase role="keyword">virtual</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">awakened</phrase><phrase role="special">(</phrase> <phrase role="identifier">context</phrase> <phrase role="special">*</phrase> <phrase role="identifier">f</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 2603</programlisting> 2604 <variablelist> 2605 <title></title> 2606 <varlistentry> 2607 <term>Effects:</term> 2608 <listitem> 2609 <para> 2610 Enqueues fiber <code><phrase role="identifier">f</phrase></code> onto 2611 the shared ready queue. 2612 </para> 2613 </listitem> 2614 </varlistentry> 2615 <varlistentry> 2616 <term>Throws:</term> 2617 <listitem> 2618 <para> 2619 Nothing. 2620 </para> 2621 </listitem> 2622 </varlistentry> 2623 </variablelist> 2624 <para> 2625 <bridgehead renderas="sect4" id="shared_work_pick_next_bridgehead"> 2626 <phrase id="shared_work_pick_next"/> 2627 <link linkend="shared_work_pick_next">Member 2628 function <code>pick_next</code>()</link> 2629</bridgehead> 2630 </para> 2631<programlisting><phrase role="keyword">virtual</phrase> <phrase role="identifier">context</phrase> <phrase role="special">*</phrase> <phrase role="identifier">pick_next</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 2632</programlisting> 2633 <variablelist> 2634 <title></title> 2635 <varlistentry> 2636 <term>Returns:</term> 2637 <listitem> 2638 <para> 2639 the fiber at the head of the ready queue, or <code><phrase role="keyword">nullptr</phrase></code> 2640 if the queue is empty. 2641 </para> 2642 </listitem> 2643 </varlistentry> 2644 <varlistentry> 2645 <term>Throws:</term> 2646 <listitem> 2647 <para> 2648 Nothing. 2649 </para> 2650 </listitem> 2651 </varlistentry> 2652 <varlistentry> 2653 <term>Note:</term> 2654 <listitem> 2655 <para> 2656 Placing ready fibers onto the tail of the shared queue, and returning 2657 them from the head of that queue, shares the thread between ready fibers 2658 in round-robin fashion. 2659 </para> 2660 </listitem> 2661 </varlistentry> 2662 </variablelist> 2663 <para> 2664 <bridgehead renderas="sect4" id="shared_work_has_ready_fibers_bridgehead"> 2665 <phrase id="shared_work_has_ready_fibers"/> 2666 <link linkend="shared_work_has_ready_fibers">Member 2667 function <code>has_ready_fibers</code>()</link> 2668</bridgehead> 2669 </para> 2670<programlisting><phrase role="keyword">virtual</phrase> <phrase role="keyword">bool</phrase> <phrase role="identifier">has_ready_fibers</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 2671</programlisting> 2672 <variablelist> 2673 <title></title> 2674 <varlistentry> 2675 <term>Returns:</term> 2676 <listitem> 2677 <para> 2678 <code><phrase role="keyword">true</phrase></code> if scheduler has fibers 2679 ready to run. 2680 </para> 2681 </listitem> 2682 </varlistentry> 2683 <varlistentry> 2684 <term>Throws:</term> 2685 <listitem> 2686 <para> 2687 Nothing. 2688 </para> 2689 </listitem> 2690 </varlistentry> 2691 </variablelist> 2692 <para> 2693 <bridgehead renderas="sect4" id="shared_work_suspend_until_bridgehead"> 2694 <phrase id="shared_work_suspend_until"/> 2695 <link linkend="shared_work_suspend_until">Member 2696 function <code>suspend_until</code>()</link> 2697</bridgehead> 2698 </para> 2699<programlisting><phrase role="keyword">virtual</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">suspend_until</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">steady_clock</phrase><phrase role="special">::</phrase><phrase role="identifier">time_point</phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">abs_time</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 2700</programlisting> 2701 <variablelist> 2702 <title></title> 2703 <varlistentry> 2704 <term>Effects:</term> 2705 <listitem> 2706 <para> 2707 Informs <code><phrase role="identifier">shared_work</phrase></code> that 2708 no ready fiber will be available until time-point <code><phrase role="identifier">abs_time</phrase></code>. 2709 This implementation blocks in <ulink url="http://en.cppreference.com/w/cpp/thread/condition_variable/wait_until"><code><phrase 2710 role="identifier">std</phrase><phrase role="special">::</phrase><phrase 2711 role="identifier">condition_variable</phrase><phrase role="special">::</phrase><phrase 2712 role="identifier">wait_until</phrase><phrase role="special">()</phrase></code></ulink>. 2713 </para> 2714 </listitem> 2715 </varlistentry> 2716 <varlistentry> 2717 <term>Throws:</term> 2718 <listitem> 2719 <para> 2720 Nothing. 2721 </para> 2722 </listitem> 2723 </varlistentry> 2724 </variablelist> 2725 <para> 2726 <bridgehead renderas="sect4" id="shared_work_notify_bridgehead"> 2727 <phrase id="shared_work_notify"/> 2728 <link linkend="shared_work_notify">Member function 2729 <code>notify</code>()</link> 2730</bridgehead> 2731 </para> 2732<programlisting><phrase role="keyword">virtual</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">notify</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase> <phrase role="special">=</phrase> <phrase role="number">0</phrase><phrase role="special">;</phrase> 2733</programlisting> 2734 <variablelist> 2735 <title></title> 2736 <varlistentry> 2737 <term>Effects:</term> 2738 <listitem> 2739 <para> 2740 Wake up a pending call to <link linkend="shared_work_suspend_until"><code>shared_work::suspend_until()</code></link>, 2741 some fibers might be ready. This implementation wakes <code><phrase role="identifier">suspend_until</phrase><phrase 2742 role="special">()</phrase></code> via <ulink url="http://en.cppreference.com/w/cpp/thread/condition_variable/notify_all"><code><phrase 2743 role="identifier">std</phrase><phrase role="special">::</phrase><phrase 2744 role="identifier">condition_variable</phrase><phrase role="special">::</phrase><phrase 2745 role="identifier">notify_all</phrase><phrase role="special">()</phrase></code></ulink>. 2746 </para> 2747 </listitem> 2748 </varlistentry> 2749 <varlistentry> 2750 <term>Throws:</term> 2751 <listitem> 2752 <para> 2753 Nothing. 2754 </para> 2755 </listitem> 2756 </varlistentry> 2757 </variablelist> 2758 <bridgehead renderas="sect3" id="fiber.scheduling.h1"> 2759 <phrase id="fiber.scheduling.custom_scheduler_fiber_properties"/><link linkend="fiber.scheduling.custom_scheduler_fiber_properties">Custom 2760 Scheduler Fiber Properties</link> 2761 </bridgehead> 2762 <para> 2763 A scheduler class directly derived from <link linkend="class_algorithm"><code>algorithm</code></link> can use any 2764 information available from <link linkend="class_context"><code>context</code></link> to implement the <code><phrase 2765 role="identifier">algorithm</phrase></code> interface. But a custom scheduler 2766 might need to track additional properties for a fiber. For instance, a priority-based 2767 scheduler would need to track a fiber’s priority. 2768 </para> 2769 <para> 2770 <emphasis role="bold">Boost.Fiber</emphasis> provides a mechanism by which 2771 your custom scheduler can associate custom properties with each fiber. 2772 </para> 2773 <para> 2774 <bridgehead renderas="sect4" id="class_fiber_properties_bridgehead"> 2775 <phrase id="class_fiber_properties"/> 2776 <link linkend="class_fiber_properties">Class 2777 <code>fiber_properties</code></link> 2778</bridgehead> 2779 </para> 2780 <para> 2781 A custom fiber properties class must be derived from <code><phrase role="identifier">fiber_properties</phrase></code>. 2782 </para> 2783<programlisting><phrase role="preprocessor">#include</phrase> <phrase role="special"><</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">></phrase> 2784 2785<phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase> 2786<phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase> 2787 2788<phrase role="keyword">class</phrase> <phrase role="identifier">fiber_properties</phrase> <phrase role="special">{</phrase> 2789<phrase role="keyword">public</phrase><phrase role="special">:</phrase> 2790 <phrase role="identifier">fiber_properties</phrase><phrase role="special">(</phrase> <phrase role="identifier">context</phrase> <phrase role="special">*)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 2791 2792 <phrase role="keyword">virtual</phrase> <phrase role="special">~</phrase><phrase role="identifier">fiber_properties</phrase><phrase role="special">();</phrase> 2793 2794<phrase role="keyword">protected</phrase><phrase role="special">:</phrase> 2795 <phrase role="keyword">void</phrase> <phrase role="identifier">notify</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 2796<phrase role="special">};</phrase> 2797 2798<phrase role="special">}}</phrase> 2799</programlisting> 2800 <bridgehead renderas="sect3" id="fiber.scheduling.h2"> 2801 <phrase id="fiber.scheduling.constructor0"/><link linkend="fiber.scheduling.constructor0">Constructor</link> 2802 </bridgehead> 2803<programlisting><phrase role="identifier">fiber_properties</phrase><phrase role="special">(</phrase> <phrase role="identifier">context</phrase> <phrase role="special">*</phrase> <phrase role="identifier">f</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 2804</programlisting> 2805 <variablelist> 2806 <title></title> 2807 <varlistentry> 2808 <term>Effects:</term> 2809 <listitem> 2810 <para> 2811 Constructs base-class component of custom subclass. 2812 </para> 2813 </listitem> 2814 </varlistentry> 2815 <varlistentry> 2816 <term>Throws:</term> 2817 <listitem> 2818 <para> 2819 Nothing. 2820 </para> 2821 </listitem> 2822 </varlistentry> 2823 <varlistentry> 2824 <term>Note:</term> 2825 <listitem> 2826 <para> 2827 Your subclass constructor must accept a <code><phrase role="identifier">context</phrase><phrase 2828 role="special">*</phrase></code> and pass it to the base-class <code><phrase 2829 role="identifier">fiber_properties</phrase></code> constructor. 2830 </para> 2831 </listitem> 2832 </varlistentry> 2833 </variablelist> 2834 <para> 2835 <bridgehead renderas="sect4" id="fiber_properties_notify_bridgehead"> 2836 <phrase id="fiber_properties_notify"/> 2837 <link linkend="fiber_properties_notify">Member 2838 function <code>notify</code>()</link> 2839</bridgehead> 2840 </para> 2841<programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">notify</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 2842</programlisting> 2843 <variablelist> 2844 <title></title> 2845 <varlistentry> 2846 <term>Effects:</term> 2847 <listitem> 2848 <para> 2849 Pass control to the custom <link linkend="class_algorithm_with_properties"><code>algorithm_with_properties<></code></link> subclass’s 2850 <link linkend="algorithm_with_properties_property_change"><code>algorithm_with_properties::property_change()</code></link> method. 2851 </para> 2852 </listitem> 2853 </varlistentry> 2854 <varlistentry> 2855 <term>Throws:</term> 2856 <listitem> 2857 <para> 2858 Nothing. 2859 </para> 2860 </listitem> 2861 </varlistentry> 2862 <varlistentry> 2863 <term>Note:</term> 2864 <listitem> 2865 <para> 2866 A custom scheduler’s <link linkend="algorithm_with_properties_pick_next"><code>algorithm_with_properties::pick_next()</code></link> method 2867 might dynamically select from the ready fibers, or <link linkend="algorithm_with_properties_awakened"><code>algorithm_with_properties::awakened()</code></link> might 2868 instead insert each ready fiber into some form of ready queue for <code><phrase 2869 role="identifier">pick_next</phrase><phrase role="special">()</phrase></code>. 2870 In the latter case, if application code modifies a fiber property (e.g. 2871 priority) that should affect that fiber’s relationship to other ready 2872 fibers, the custom scheduler must be given the opportunity to reorder 2873 its ready queue. The custom property subclass should implement an access 2874 method to modify such a property; that access method should call <code><phrase 2875 role="identifier">notify</phrase><phrase role="special">()</phrase></code> 2876 once the new property value has been stored. This passes control to the 2877 custom scheduler’s <code><phrase role="identifier">property_change</phrase><phrase 2878 role="special">()</phrase></code> method, allowing the custom scheduler 2879 to reorder its ready queue appropriately. Use at your discretion. Of 2880 course, if you define a property which does not affect the behavior of 2881 the <code><phrase role="identifier">pick_next</phrase><phrase role="special">()</phrase></code> 2882 method, you need not call <code><phrase role="identifier">notify</phrase><phrase 2883 role="special">()</phrase></code> when that property is modified. 2884 </para> 2885 </listitem> 2886 </varlistentry> 2887 </variablelist> 2888 <para> 2889 <bridgehead renderas="sect4" id="class_algorithm_with_properties_bridgehead"> 2890 <phrase id="class_algorithm_with_properties"/> 2891 <link linkend="class_algorithm_with_properties">Template 2892 <code>algorithm_with_properties<></code></link> 2893</bridgehead> 2894 </para> 2895 <para> 2896 A custom scheduler that depends on a custom properties class <code><phrase 2897 role="identifier">PROPS</phrase></code> should be derived from <code><phrase 2898 role="identifier">algorithm_with_properties</phrase><phrase role="special"><</phrase><phrase 2899 role="identifier">PROPS</phrase><phrase role="special">></phrase></code>. 2900 <code><phrase role="identifier">PROPS</phrase></code> should be derived from 2901 <link linkend="class_fiber_properties"><code>fiber_properties</code></link>. 2902 </para> 2903<programlisting><phrase role="preprocessor">#include</phrase> <phrase role="special"><</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">></phrase> 2904 2905<phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase> 2906<phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase> 2907<phrase role="keyword">namespace</phrase> <phrase role="identifier">algo</phrase> <phrase role="special">{</phrase> 2908 2909<phrase role="keyword">template</phrase><phrase role="special"><</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">PROPS</phrase> <phrase role="special">></phrase> 2910<phrase role="keyword">struct</phrase> <phrase role="identifier">algorithm_with_properties</phrase> <phrase role="special">{</phrase> 2911 <phrase role="keyword">virtual</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">awakened</phrase><phrase role="special">(</phrase> <phrase role="identifier">context</phrase> <phrase role="special">*,</phrase> <phrase role="identifier">PROPS</phrase> <phrase role="special">&)</phrase> <phrase role="keyword">noexcept</phrase> <phrase role="special">=</phrase> <phrase role="number">0</phrase><phrase role="special">;</phrase> 2912 2913 <phrase role="keyword">virtual</phrase> <phrase role="identifier">context</phrase> <phrase role="special">*</phrase> <phrase role="identifier">pick_next</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 2914 2915 <phrase role="keyword">virtual</phrase> <phrase role="keyword">bool</phrase> <phrase role="identifier">has_ready_fibers</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 2916 2917 <phrase role="keyword">virtual</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">suspend_until</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">steady_clock</phrase><phrase role="special">::</phrase><phrase role="identifier">time_point</phrase> <phrase role="keyword">const</phrase><phrase role="special">&)</phrase> <phrase role="keyword">noexcept</phrase> <phrase role="special">=</phrase> <phrase role="number">0</phrase><phrase role="special">;</phrase> 2918 2919 <phrase role="keyword">virtual</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">notify</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase> <phrase role="special">=</phrase> <phrase role="number">0</phrase><phrase role="special">;</phrase> 2920 2921 <phrase role="identifier">PROPS</phrase> <phrase role="special">&</phrase> <phrase role="identifier">properties</phrase><phrase role="special">(</phrase> <phrase role="identifier">context</phrase> <phrase role="special">*)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 2922 2923 <phrase role="keyword">virtual</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">property_change</phrase><phrase role="special">(</phrase> <phrase role="identifier">context</phrase> <phrase role="special">*,</phrase> <phrase role="identifier">PROPS</phrase> <phrase role="special">&)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 2924 2925 <phrase role="keyword">virtual</phrase> <phrase role="identifier">fiber_properties</phrase> <phrase role="special">*</phrase> <phrase role="identifier">new_properties</phrase><phrase role="special">(</phrase> <phrase role="identifier">context</phrase> <phrase role="special">*);</phrase> 2926<phrase role="special">};</phrase> 2927 2928<phrase role="special">}}}</phrase> 2929</programlisting> 2930 <para> 2931 <bridgehead renderas="sect4" id="algorithm_with_properties_awakened_bridgehead"> 2932 <phrase id="algorithm_with_properties_awakened"/> 2933 <link linkend="algorithm_with_properties_awakened">Member 2934 function <code>awakened</code>()</link> 2935</bridgehead> 2936 </para> 2937<programlisting><phrase role="keyword">virtual</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">awakened</phrase><phrase role="special">(</phrase> <phrase role="identifier">context</phrase> <phrase role="special">*</phrase> <phrase role="identifier">f</phrase><phrase role="special">,</phrase> <phrase role="identifier">PROPS</phrase> <phrase role="special">&</phrase> <phrase role="identifier">properties</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 2938</programlisting> 2939 <variablelist> 2940 <title></title> 2941 <varlistentry> 2942 <term>Effects:</term> 2943 <listitem> 2944 <para> 2945 Informs the scheduler that fiber <code><phrase role="identifier">f</phrase></code> 2946 is ready to run, like <link linkend="algorithm_awakened"><code>algorithm::awakened()</code></link>. Passes 2947 the fiber’s associated <code><phrase role="identifier">PROPS</phrase></code> 2948 instance. 2949 </para> 2950 </listitem> 2951 </varlistentry> 2952 <varlistentry> 2953 <term>Throws:</term> 2954 <listitem> 2955 <para> 2956 Nothing. 2957 </para> 2958 </listitem> 2959 </varlistentry> 2960 <varlistentry> 2961 <term>Note:</term> 2962 <listitem> 2963 <para> 2964 An <code><phrase role="identifier">algorithm_with_properties</phrase><phrase 2965 role="special"><></phrase></code> subclass must override this method 2966 instead of <code><phrase role="identifier">algorithm</phrase><phrase 2967 role="special">::</phrase><phrase role="identifier">awakened</phrase><phrase 2968 role="special">()</phrase></code>. 2969 </para> 2970 </listitem> 2971 </varlistentry> 2972 </variablelist> 2973 <para> 2974 <bridgehead renderas="sect4" id="algorithm_with_properties_pick_next_bridgehead"> 2975 <phrase id="algorithm_with_properties_pick_next"/> 2976 <link linkend="algorithm_with_properties_pick_next">Member 2977 function <code>pick_next</code>()</link> 2978</bridgehead> 2979 </para> 2980<programlisting><phrase role="keyword">virtual</phrase> <phrase role="identifier">context</phrase> <phrase role="special">*</phrase> <phrase role="identifier">pick_next</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 2981</programlisting> 2982 <variablelist> 2983 <title></title> 2984 <varlistentry> 2985 <term>Returns:</term> 2986 <listitem> 2987 <para> 2988 the fiber which is to be resumed next, or <code><phrase role="keyword">nullptr</phrase></code> 2989 if there is no ready fiber. 2990 </para> 2991 </listitem> 2992 </varlistentry> 2993 <varlistentry> 2994 <term>Throws:</term> 2995 <listitem> 2996 <para> 2997 Nothing. 2998 </para> 2999 </listitem> 3000 </varlistentry> 3001 <varlistentry> 3002 <term>Note:</term> 3003 <listitem> 3004 <para> 3005 same as <link linkend="algorithm_pick_next"><code>algorithm::pick_next()</code></link> 3006 </para> 3007 </listitem> 3008 </varlistentry> 3009 </variablelist> 3010 <para> 3011 <bridgehead renderas="sect4" id="algorithm_with_properties_has_ready_fibers_bridgehead"> 3012 <phrase id="algorithm_with_properties_has_ready_fibers"/> 3013 <link linkend="algorithm_with_properties_has_ready_fibers">Member 3014 function <code>has_ready_fibers</code>()</link> 3015</bridgehead> 3016 </para> 3017<programlisting><phrase role="keyword">virtual</phrase> <phrase role="keyword">bool</phrase> <phrase role="identifier">has_ready_fibers</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 3018</programlisting> 3019 <variablelist> 3020 <title></title> 3021 <varlistentry> 3022 <term>Returns:</term> 3023 <listitem> 3024 <para> 3025 <code><phrase role="keyword">true</phrase></code> if scheduler has fibers 3026 ready to run. 3027 </para> 3028 </listitem> 3029 </varlistentry> 3030 <varlistentry> 3031 <term>Throws:</term> 3032 <listitem> 3033 <para> 3034 Nothing. 3035 </para> 3036 </listitem> 3037 </varlistentry> 3038 <varlistentry> 3039 <term>Note:</term> 3040 <listitem> 3041 <para> 3042 same as <link linkend="algorithm_has_ready_fibers"><code>algorithm::has_ready_fibers()</code></link> 3043 </para> 3044 </listitem> 3045 </varlistentry> 3046 </variablelist> 3047 <para> 3048 <bridgehead renderas="sect4" id="algorithm_with_properties_suspend_until_bridgehead"> 3049 <phrase id="algorithm_with_properties_suspend_until"/> 3050 <link linkend="algorithm_with_properties_suspend_until">Member 3051 function <code>suspend_until</code>()</link> 3052</bridgehead> 3053 </para> 3054<programlisting><phrase role="keyword">virtual</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">suspend_until</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">steady_clock</phrase><phrase role="special">::</phrase><phrase role="identifier">time_point</phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">abs_time</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase> <phrase role="special">=</phrase> <phrase role="number">0</phrase><phrase role="special">;</phrase> 3055</programlisting> 3056 <variablelist> 3057 <title></title> 3058 <varlistentry> 3059 <term>Effects:</term> 3060 <listitem> 3061 <para> 3062 Informs the scheduler that no fiber will be ready until time-point <code><phrase 3063 role="identifier">abs_time</phrase></code>. 3064 </para> 3065 </listitem> 3066 </varlistentry> 3067 <varlistentry> 3068 <term>Note:</term> 3069 <listitem> 3070 <para> 3071 same as <link linkend="algorithm_suspend_until"><code>algorithm::suspend_until()</code></link> 3072 </para> 3073 </listitem> 3074 </varlistentry> 3075 </variablelist> 3076 <para> 3077 <bridgehead renderas="sect4" id="algorithm_with_properties_notify_bridgehead"> 3078 <phrase id="algorithm_with_properties_notify"/> 3079 <link linkend="algorithm_with_properties_notify">Member 3080 function <code>notify</code>()</link> 3081</bridgehead> 3082 </para> 3083<programlisting><phrase role="keyword">virtual</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">notify</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase> <phrase role="special">=</phrase> <phrase role="number">0</phrase><phrase role="special">;</phrase> 3084</programlisting> 3085 <variablelist> 3086 <title></title> 3087 <varlistentry> 3088 <term>Effects:</term> 3089 <listitem> 3090 <para> 3091 Requests the scheduler to return from a pending call to <link linkend="algorithm_with_properties_suspend_until"><code>algorithm_with_properties::suspend_until()</code></link>. 3092 </para> 3093 </listitem> 3094 </varlistentry> 3095 <varlistentry> 3096 <term>Note:</term> 3097 <listitem> 3098 <para> 3099 same as <link linkend="algorithm_notify"><code>algorithm::notify()</code></link> 3100 </para> 3101 </listitem> 3102 </varlistentry> 3103 </variablelist> 3104 <para> 3105 <bridgehead renderas="sect4" id="algorithm_with_properties_properties_bridgehead"> 3106 <phrase id="algorithm_with_properties_properties"/> 3107 <link linkend="algorithm_with_properties_properties">Member 3108 function <code>properties</code>()</link> 3109</bridgehead> 3110 </para> 3111<programlisting><phrase role="identifier">PROPS</phrase><phrase role="special">&</phrase> <phrase role="identifier">properties</phrase><phrase role="special">(</phrase> <phrase role="identifier">context</phrase> <phrase role="special">*</phrase> <phrase role="identifier">f</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 3112</programlisting> 3113 <variablelist> 3114 <title></title> 3115 <varlistentry> 3116 <term>Returns:</term> 3117 <listitem> 3118 <para> 3119 the <code><phrase role="identifier">PROPS</phrase></code> instance associated 3120 with fiber <code><phrase role="identifier">f</phrase></code>. 3121 </para> 3122 </listitem> 3123 </varlistentry> 3124 <varlistentry> 3125 <term>Throws:</term> 3126 <listitem> 3127 <para> 3128 Nothing. 3129 </para> 3130 </listitem> 3131 </varlistentry> 3132 <varlistentry> 3133 <term>Note:</term> 3134 <listitem> 3135 <para> 3136 The fiber’s associated <code><phrase role="identifier">PROPS</phrase></code> 3137 instance is already passed to <link linkend="algorithm_with_properties_awakened"><code>algorithm_with_properties::awakened()</code></link> and 3138 <link linkend="algorithm_with_properties_property_change"><code>algorithm_with_properties::property_change()</code></link>. 3139 However, every <link linkend="class_algorithm"><code>algorithm</code></link> subclass is expected to track 3140 a collection of ready <link linkend="class_context"><code>context</code></link> instances. This method allows 3141 your custom scheduler to retrieve the <link linkend="class_fiber_properties"><code>fiber_properties</code></link> subclass 3142 instance for any <code><phrase role="identifier">context</phrase></code> 3143 in its collection. 3144 </para> 3145 </listitem> 3146 </varlistentry> 3147 </variablelist> 3148 <para> 3149 <bridgehead renderas="sect4" id="algorithm_with_properties_property_change_bridgehead"> 3150 <phrase id="algorithm_with_properties_property_change"/> 3151 <link linkend="algorithm_with_properties_property_change">Member 3152 function <code>property_change</code>()</link> 3153</bridgehead> 3154 </para> 3155<programlisting><phrase role="keyword">virtual</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">property_change</phrase><phrase role="special">(</phrase> <phrase role="identifier">context</phrase> <phrase role="special">*</phrase> <phrase role="identifier">f</phrase><phrase role="special">,</phrase> <phrase role="identifier">PROPS</phrase> <phrase role="special">&</phrase> <phrase role="identifier">properties</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 3156</programlisting> 3157 <variablelist> 3158 <title></title> 3159 <varlistentry> 3160 <term>Effects:</term> 3161 <listitem> 3162 <para> 3163 Notify the custom scheduler of a possibly-relevant change to a property 3164 belonging to fiber <code><phrase role="identifier">f</phrase></code>. 3165 <code><phrase role="identifier">properties</phrase></code> contains the 3166 new values of all relevant properties. 3167 </para> 3168 </listitem> 3169 </varlistentry> 3170 <varlistentry> 3171 <term>Throws:</term> 3172 <listitem> 3173 <para> 3174 Nothing. 3175 </para> 3176 </listitem> 3177 </varlistentry> 3178 <varlistentry> 3179 <term>Note:</term> 3180 <listitem> 3181 <para> 3182 This method is only called when a custom <link linkend="class_fiber_properties"><code>fiber_properties</code></link> subclass 3183 explicitly calls <link linkend="fiber_properties_notify"><code>fiber_properties::notify()</code></link>. 3184 </para> 3185 </listitem> 3186 </varlistentry> 3187 </variablelist> 3188 <para> 3189 <bridgehead renderas="sect4" id="algorithm_with_properties_new_properties_bridgehead"> 3190 <phrase id="algorithm_with_properties_new_properties"/> 3191 <link linkend="algorithm_with_properties_new_properties">Member 3192 function <code>new_properties</code>()</link> 3193</bridgehead> 3194 </para> 3195<programlisting><phrase role="keyword">virtual</phrase> <phrase role="identifier">fiber_properties</phrase> <phrase role="special">*</phrase> <phrase role="identifier">new_properties</phrase><phrase role="special">(</phrase> <phrase role="identifier">context</phrase> <phrase role="special">*</phrase> <phrase role="identifier">f</phrase><phrase role="special">);</phrase> 3196</programlisting> 3197 <variablelist> 3198 <title></title> 3199 <varlistentry> 3200 <term>Returns:</term> 3201 <listitem> 3202 <para> 3203 A new instance of <link linkend="class_fiber_properties"><code>fiber_properties</code></link> subclass <code><phrase 3204 role="identifier">PROPS</phrase></code>. 3205 </para> 3206 </listitem> 3207 </varlistentry> 3208 <varlistentry> 3209 <term>Note:</term> 3210 <listitem> 3211 <para> 3212 By default, <code><phrase role="identifier">algorithm_with_properties</phrase><phrase 3213 role="special"><>::</phrase><phrase role="identifier">new_properties</phrase><phrase 3214 role="special">()</phrase></code> simply returns <code><phrase role="keyword">new</phrase> 3215 <phrase role="identifier">PROPS</phrase><phrase role="special">(</phrase><phrase 3216 role="identifier">f</phrase><phrase role="special">)</phrase></code>, 3217 placing the <code><phrase role="identifier">PROPS</phrase></code> instance 3218 on the heap. Override this method to allocate <code><phrase role="identifier">PROPS</phrase></code> 3219 some other way. The returned <code><phrase role="identifier">fiber_properties</phrase></code> 3220 pointer must point to the <code><phrase role="identifier">PROPS</phrase></code> 3221 instance to be associated with fiber <code><phrase role="identifier">f</phrase></code>. 3222 </para> 3223 </listitem> 3224 </varlistentry> 3225 </variablelist> 3226 <para> 3227 <anchor id="context"/><bridgehead renderas="sect4" id="class_context_bridgehead"> 3228 <phrase id="class_context"/> 3229 <link linkend="class_context">Class 3230 <code>context</code></link> 3231</bridgehead> 3232 </para> 3233 <para> 3234 While you are free to treat <code><phrase role="identifier">context</phrase><phrase 3235 role="special">*</phrase></code> as an opaque token, certain <code><phrase 3236 role="identifier">context</phrase></code> members may be useful to a custom 3237 scheduler implementation. 3238 </para> 3239 <para> 3240 <anchor id="ready_queue_t"/>Of particular note is the fact that <code><phrase 3241 role="identifier">context</phrase></code> contains a hook to participate in 3242 a <ulink url="http://www.boost.org/doc/libs/release/doc/html/intrusive/list.html"><code><phrase 3243 role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">intrusive</phrase><phrase 3244 role="special">::</phrase><phrase role="identifier">list</phrase></code></ulink> 3245 <literal>typedef</literal>’ed as <code><phrase role="identifier">boost</phrase><phrase 3246 role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase 3247 role="special">::</phrase><phrase role="identifier">scheduler</phrase><phrase 3248 role="special">::</phrase><phrase role="identifier">ready_queue_t</phrase></code>. 3249 This hook is reserved for use by <link linkend="class_algorithm"><code>algorithm</code></link> implementations. (For 3250 instance, <link linkend="class_round_robin"><code>round_robin</code></link> contains a <code><phrase role="identifier">ready_queue_t</phrase></code> 3251 instance to manage its ready fibers.) See <link linkend="context_ready_is_linked"><code>context::ready_is_linked()</code></link>, 3252 <link linkend="context_ready_link"><code>context::ready_link()</code></link>, <link linkend="context_ready_unlink"><code>context::ready_unlink()</code></link>. 3253 </para> 3254 <para> 3255 Your <code><phrase role="identifier">algorithm</phrase></code> implementation 3256 may use any container you desire to manage passed <code><phrase role="identifier">context</phrase></code> 3257 instances. <code><phrase role="identifier">ready_queue_t</phrase></code> avoids 3258 some of the overhead of typical STL containers. 3259 </para> 3260<programlisting><phrase role="preprocessor">#include</phrase> <phrase role="special"><</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">></phrase> 3261 3262<phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase> 3263<phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase> 3264 3265<phrase role="keyword">enum</phrase> <phrase role="keyword">class</phrase> <phrase role="identifier">type</phrase> <phrase role="special">{</phrase> 3266 <phrase role="identifier">none</phrase> <phrase role="special">=</phrase> <emphasis>unspecified</emphasis><phrase role="special">,</phrase> 3267 <phrase role="identifier">main_context</phrase> <phrase role="special">=</phrase> <emphasis>unspecified</emphasis><phrase role="special">,</phrase> <phrase role="comment">// fiber associated with thread's stack</phrase> 3268 <phrase role="identifier">dispatcher_context</phrase> <phrase role="special">=</phrase> <emphasis>unspecified</emphasis><phrase role="special">,</phrase> <phrase role="comment">// special fiber for maintenance operations</phrase> 3269 <phrase role="identifier">worker_context</phrase> <phrase role="special">=</phrase> <emphasis>unspecified</emphasis><phrase role="special">,</phrase> <phrase role="comment">// fiber not special to the library</phrase> 3270 <phrase role="identifier">pinned_context</phrase> <phrase role="special">=</phrase> <emphasis>unspecified</emphasis> <phrase role="comment">// fiber must not be migrated to another thread</phrase> 3271<phrase role="special">};</phrase> 3272 3273<phrase role="keyword">class</phrase> <phrase role="identifier">context</phrase> <phrase role="special">{</phrase> 3274<phrase role="keyword">public</phrase><phrase role="special">:</phrase> 3275 <phrase role="keyword">class</phrase> <phrase role="identifier">id</phrase><phrase role="special">;</phrase> 3276 3277 <phrase role="keyword">static</phrase> <phrase role="identifier">context</phrase> <phrase role="special">*</phrase> <phrase role="identifier">active</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 3278 3279 <phrase role="identifier">context</phrase><phrase role="special">(</phrase> <phrase role="identifier">context</phrase> <phrase role="keyword">const</phrase><phrase role="special">&)</phrase> <phrase role="special">=</phrase> <phrase role="keyword">delete</phrase><phrase role="special">;</phrase> 3280 <phrase role="identifier">context</phrase> <phrase role="special">&</phrase> <phrase role="keyword">operator</phrase><phrase role="special">=(</phrase> <phrase role="identifier">context</phrase> <phrase role="keyword">const</phrase><phrase role="special">&)</phrase> <phrase role="special">=</phrase> <phrase role="keyword">delete</phrase><phrase role="special">;</phrase> 3281 3282 <phrase role="identifier">id</phrase> <phrase role="identifier">get_id</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 3283 3284 <phrase role="keyword">void</phrase> <phrase role="identifier">detach</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 3285 <phrase role="keyword">void</phrase> <phrase role="identifier">attach</phrase><phrase role="special">(</phrase> <phrase role="identifier">context</phrase> <phrase role="special">*)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 3286 3287 <phrase role="keyword">bool</phrase> <phrase role="identifier">is_context</phrase><phrase role="special">(</phrase> <phrase role="identifier">type</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 3288 3289 <phrase role="keyword">bool</phrase> <phrase role="identifier">is_terminated</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 3290 3291 <phrase role="keyword">bool</phrase> <phrase role="identifier">ready_is_linked</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 3292 <phrase role="keyword">bool</phrase> <phrase role="identifier">remote_ready_is_linked</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 3293 <phrase role="keyword">bool</phrase> <phrase role="identifier">wait_is_linked</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 3294 3295 <phrase role="keyword">template</phrase><phrase role="special"><</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">List</phrase> <phrase role="special">></phrase> 3296 <phrase role="keyword">void</phrase> <phrase role="identifier">ready_link</phrase><phrase role="special">(</phrase> <phrase role="identifier">List</phrase> <phrase role="special">&)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 3297 <phrase role="keyword">template</phrase><phrase role="special"><</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">List</phrase> <phrase role="special">></phrase> 3298 <phrase role="keyword">void</phrase> <phrase role="identifier">remote_ready_link</phrase><phrase role="special">(</phrase> <phrase role="identifier">List</phrase> <phrase role="special">&)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 3299 <phrase role="keyword">template</phrase><phrase role="special"><</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">List</phrase> <phrase role="special">></phrase> 3300 <phrase role="keyword">void</phrase> <phrase role="identifier">wait_link</phrase><phrase role="special">(</phrase> <phrase role="identifier">List</phrase> <phrase role="special">&)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 3301 3302 <phrase role="keyword">void</phrase> <phrase role="identifier">ready_unlink</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 3303 <phrase role="keyword">void</phrase> <phrase role="identifier">remote_ready_unlink</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 3304 <phrase role="keyword">void</phrase> <phrase role="identifier">wait_unlink</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 3305 3306 <phrase role="keyword">void</phrase> <phrase role="identifier">suspend</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 3307 <phrase role="keyword">void</phrase> <phrase role="identifier">schedule</phrase><phrase role="special">(</phrase> <phrase role="identifier">context</phrase> <phrase role="special">*)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 3308<phrase role="special">};</phrase> 3309 3310<phrase role="keyword">bool</phrase> <phrase role="keyword">operator</phrase><phrase role="special"><(</phrase> <phrase role="identifier">context</phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">l</phrase><phrase role="special">,</phrase> <phrase role="identifier">context</phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">r</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 3311 3312<phrase role="special">}}</phrase> 3313</programlisting> 3314 <para> 3315 <bridgehead renderas="sect4" id="context_active_bridgehead"> 3316 <phrase id="context_active"/> 3317 <link linkend="context_active">Static member function 3318 <code>active</code>()</link> 3319</bridgehead> 3320 </para> 3321<programlisting><phrase role="keyword">static</phrase> <phrase role="identifier">context</phrase> <phrase role="special">*</phrase> <phrase role="identifier">active</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 3322</programlisting> 3323 <variablelist> 3324 <title></title> 3325 <varlistentry> 3326 <term>Returns:</term> 3327 <listitem> 3328 <para> 3329 Pointer to instance of current fiber. 3330 </para> 3331 </listitem> 3332 </varlistentry> 3333 <varlistentry> 3334 <term>Throws:</term> 3335 <listitem> 3336 <para> 3337 Nothing 3338 </para> 3339 </listitem> 3340 </varlistentry> 3341 </variablelist> 3342 <para> 3343 <bridgehead renderas="sect4" id="context_get_id_bridgehead"> 3344 <phrase id="context_get_id"/> 3345 <link linkend="context_get_id">Member function <code>get_id</code>()</link> 3346</bridgehead> 3347 </para> 3348<programlisting><phrase role="identifier">context</phrase><phrase role="special">::</phrase><phrase role="identifier">id</phrase> <phrase role="identifier">get_id</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 3349</programlisting> 3350 <variablelist> 3351 <title></title> 3352 <varlistentry> 3353 <term>Returns:</term> 3354 <listitem> 3355 <para> 3356 If <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code> 3357 refers to a fiber of execution, an instance of <link linkend="class_fiber_id"><code><phrase 3358 role="identifier">fiber</phrase><phrase role="special">::</phrase><phrase 3359 role="identifier">id</phrase></code></link> that represents that fiber. Otherwise 3360 returns a default-constructed <link linkend="class_fiber_id"><code><phrase role="identifier">fiber</phrase><phrase 3361 role="special">::</phrase><phrase role="identifier">id</phrase></code></link>. 3362 </para> 3363 </listitem> 3364 </varlistentry> 3365 <varlistentry> 3366 <term>Throws:</term> 3367 <listitem> 3368 <para> 3369 Nothing 3370 </para> 3371 </listitem> 3372 </varlistentry> 3373 <varlistentry> 3374 <term>See also:</term> 3375 <listitem> 3376 <para> 3377 <link linkend="fiber_get_id"><code>fiber::get_id()</code></link> 3378 </para> 3379 </listitem> 3380 </varlistentry> 3381 </variablelist> 3382 <para> 3383 <bridgehead renderas="sect4" id="context_attach_bridgehead"> 3384 <phrase id="context_attach"/> 3385 <link linkend="context_attach">Member function <code>attach</code>()</link> 3386</bridgehead> 3387 </para> 3388<programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">attach</phrase><phrase role="special">(</phrase> <phrase role="identifier">context</phrase> <phrase role="special">*</phrase> <phrase role="identifier">f</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 3389</programlisting> 3390 <variablelist> 3391 <title></title> 3392 <varlistentry> 3393 <term>Precondition:</term> 3394 <listitem> 3395 <para> 3396 <code><phrase role="keyword">this</phrase><phrase role="special">-></phrase><phrase 3397 role="identifier">get_scheduler</phrase><phrase role="special">()</phrase> 3398 <phrase role="special">==</phrase> <phrase role="keyword">nullptr</phrase></code> 3399 </para> 3400 </listitem> 3401 </varlistentry> 3402 <varlistentry> 3403 <term>Effects:</term> 3404 <listitem> 3405 <para> 3406 Attach fiber <code><phrase role="identifier">f</phrase></code> to scheduler 3407 running <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>. 3408 </para> 3409 </listitem> 3410 </varlistentry> 3411 <varlistentry> 3412 <term>Postcondition:</term> 3413 <listitem> 3414 <para> 3415 <code><phrase role="keyword">this</phrase><phrase role="special">-></phrase><phrase 3416 role="identifier">get_scheduler</phrase><phrase role="special">()</phrase> 3417 <phrase role="special">!=</phrase> <phrase role="keyword">nullptr</phrase></code> 3418 </para> 3419 </listitem> 3420 </varlistentry> 3421 <varlistentry> 3422 <term>Throws:</term> 3423 <listitem> 3424 <para> 3425 Nothing 3426 </para> 3427 </listitem> 3428 </varlistentry> 3429 <varlistentry> 3430 <term>Note:</term> 3431 <listitem> 3432 <para> 3433 A typical call: <code><phrase role="identifier">boost</phrase><phrase 3434 role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase 3435 role="special">::</phrase><phrase role="identifier">context</phrase><phrase 3436 role="special">::</phrase><phrase role="identifier">active</phrase><phrase 3437 role="special">()-></phrase><phrase role="identifier">attach</phrase><phrase 3438 role="special">(</phrase><phrase role="identifier">f</phrase><phrase 3439 role="special">);</phrase></code> 3440 </para> 3441 </listitem> 3442 </varlistentry> 3443 <varlistentry> 3444 <term>Note:</term> 3445 <listitem> 3446 <para> 3447 <code><phrase role="identifier">f</phrase></code> must not be the running 3448 fiber’s context. It must not be <link linkend="blocking"><emphasis>blocked</emphasis></link> 3449 or terminated. It must not be a <code><phrase role="identifier">pinned_context</phrase></code>. 3450 It must be currently detached. It must not currently be linked into an 3451 <link linkend="class_algorithm"><code>algorithm</code></link> implementation’s ready queue. Most of these conditions 3452 are implied by <code><phrase role="identifier">f</phrase></code> being 3453 owned by an <code><phrase role="identifier">algorithm</phrase></code> 3454 implementation: that is, it has been passed to <link linkend="algorithm_awakened"><code>algorithm::awakened()</code></link> but 3455 has not yet been returned by <link linkend="algorithm_pick_next"><code>algorithm::pick_next()</code></link>. 3456 Typically a <code><phrase role="identifier">pick_next</phrase><phrase 3457 role="special">()</phrase></code> implementation would call <code><phrase 3458 role="identifier">attach</phrase><phrase role="special">()</phrase></code> 3459 with the <code><phrase role="identifier">context</phrase><phrase role="special">*</phrase></code> 3460 it is about to return. It must first remove <code><phrase role="identifier">f</phrase></code> 3461 from its ready queue. You should never pass a <code><phrase role="identifier">pinned_context</phrase></code> 3462 to <code><phrase role="identifier">attach</phrase><phrase role="special">()</phrase></code> 3463 because you should never have called its <code><phrase role="identifier">detach</phrase><phrase 3464 role="special">()</phrase></code> method in the first place. 3465 </para> 3466 </listitem> 3467 </varlistentry> 3468 </variablelist> 3469 <para> 3470 <bridgehead renderas="sect4" id="context_detach_bridgehead"> 3471 <phrase id="context_detach"/> 3472 <link linkend="context_detach">Member function <code>detach</code>()</link> 3473</bridgehead> 3474 </para> 3475<programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">detach</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 3476</programlisting> 3477 <variablelist> 3478 <title></title> 3479 <varlistentry> 3480 <term>Precondition:</term> 3481 <listitem> 3482 <para> 3483 <code><phrase role="special">(</phrase><phrase role="keyword">this</phrase><phrase 3484 role="special">-></phrase><phrase role="identifier">get_scheduler</phrase><phrase 3485 role="special">()</phrase> <phrase role="special">!=</phrase> <phrase 3486 role="keyword">nullptr</phrase><phrase role="special">)</phrase> <phrase 3487 role="special">&&</phrase> <phrase role="special">!</phrase> 3488 <phrase role="keyword">this</phrase><phrase role="special">-></phrase><phrase 3489 role="identifier">is_context</phrase><phrase role="special">(</phrase><phrase 3490 role="identifier">pinned_context</phrase><phrase role="special">)</phrase></code> 3491 </para> 3492 </listitem> 3493 </varlistentry> 3494 <varlistentry> 3495 <term>Effects:</term> 3496 <listitem> 3497 <para> 3498 Detach fiber <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code> 3499 from its scheduler running <code><phrase role="special">*</phrase><phrase 3500 role="keyword">this</phrase></code>. 3501 </para> 3502 </listitem> 3503 </varlistentry> 3504 <varlistentry> 3505 <term>Throws:</term> 3506 <listitem> 3507 <para> 3508 Nothing 3509 </para> 3510 </listitem> 3511 </varlistentry> 3512 <varlistentry> 3513 <term>Postcondition:</term> 3514 <listitem> 3515 <para> 3516 <code><phrase role="keyword">this</phrase><phrase role="special">-></phrase><phrase 3517 role="identifier">get_scheduler</phrase><phrase role="special">()</phrase> 3518 <phrase role="special">==</phrase> <phrase role="keyword">nullptr</phrase></code> 3519 </para> 3520 </listitem> 3521 </varlistentry> 3522 <varlistentry> 3523 <term>Note:</term> 3524 <listitem> 3525 <para> 3526 This method must be called on the thread with which the fiber is currently 3527 associated. <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code> 3528 must not be the running fiber’s context. It must not be <link linkend="blocking"><emphasis>blocked</emphasis></link> 3529 or terminated. It must not be a <code><phrase role="identifier">pinned_context</phrase></code>. 3530 It must not be detached already. It must not already be linked into an 3531 <link linkend="class_algorithm"><code>algorithm</code></link> implementation’s ready queue. Most of these conditions 3532 are implied by <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code> 3533 being passed to <link linkend="algorithm_awakened"><code>algorithm::awakened()</code></link>; an <code><phrase 3534 role="identifier">awakened</phrase><phrase role="special">()</phrase></code> 3535 implementation must, however, test for <code><phrase role="identifier">pinned_context</phrase></code>. 3536 It must call <code><phrase role="identifier">detach</phrase><phrase role="special">()</phrase></code> 3537 <emphasis>before</emphasis> linking <code><phrase role="special">*</phrase><phrase 3538 role="keyword">this</phrase></code> into its ready queue. 3539 </para> 3540 </listitem> 3541 </varlistentry> 3542 <varlistentry> 3543 <term>Note:</term> 3544 <listitem> 3545 <para> 3546 In particular, it is erroneous to attempt to migrate a fiber from one 3547 thread to another by calling both <code><phrase role="identifier">detach</phrase><phrase 3548 role="special">()</phrase></code> and <code><phrase role="identifier">attach</phrase><phrase 3549 role="special">()</phrase></code> in the <link linkend="algorithm_pick_next"><code>algorithm::pick_next()</code></link> method. 3550 <code><phrase role="identifier">pick_next</phrase><phrase role="special">()</phrase></code> 3551 is called on the intended destination thread. <code><phrase role="identifier">detach</phrase><phrase 3552 role="special">()</phrase></code> must be called on the fiber’s original 3553 thread. You must call <code><phrase role="identifier">detach</phrase><phrase 3554 role="special">()</phrase></code> in the corresponding <code><phrase 3555 role="identifier">awakened</phrase><phrase role="special">()</phrase></code> 3556 method. 3557 </para> 3558 </listitem> 3559 </varlistentry> 3560 <varlistentry> 3561 <term>Note:</term> 3562 <listitem> 3563 <para> 3564 Unless you intend make a fiber available for potential migration to a 3565 different thread, you should call neither <code><phrase role="identifier">detach</phrase><phrase 3566 role="special">()</phrase></code> nor <code><phrase role="identifier">attach</phrase><phrase 3567 role="special">()</phrase></code> with its <code><phrase role="identifier">context</phrase></code>. 3568 </para> 3569 </listitem> 3570 </varlistentry> 3571 </variablelist> 3572 <para> 3573 <bridgehead renderas="sect4" id="context_is_context_bridgehead"> 3574 <phrase id="context_is_context"/> 3575 <link linkend="context_is_context">Member function 3576 <code>is_context</code>()</link> 3577</bridgehead> 3578 </para> 3579<programlisting><phrase role="keyword">bool</phrase> <phrase role="identifier">is_context</phrase><phrase role="special">(</phrase> <phrase role="identifier">type</phrase> <phrase role="identifier">t</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 3580</programlisting> 3581 <variablelist> 3582 <title></title> 3583 <varlistentry> 3584 <term>Returns:</term> 3585 <listitem> 3586 <para> 3587 <code><phrase role="keyword">true</phrase></code> if <code><phrase role="special">*</phrase><phrase 3588 role="keyword">this</phrase></code> is of the specified type. 3589 </para> 3590 </listitem> 3591 </varlistentry> 3592 <varlistentry> 3593 <term>Throws:</term> 3594 <listitem> 3595 <para> 3596 Nothing 3597 </para> 3598 </listitem> 3599 </varlistentry> 3600 <varlistentry> 3601 <term>Note:</term> 3602 <listitem> 3603 <para> 3604 <code><phrase role="identifier">type</phrase><phrase role="special">::</phrase><phrase 3605 role="identifier">worker_context</phrase></code> here means any fiber 3606 not special to the library. For <code><phrase role="identifier">type</phrase><phrase 3607 role="special">::</phrase><phrase role="identifier">main_context</phrase></code> 3608 the <code><phrase role="identifier">context</phrase></code> is associated 3609 with the <quote>main</quote> fiber of the thread: the one implicitly 3610 created by the thread itself, rather than one explicitly created by 3611 <emphasis role="bold">Boost.Fiber</emphasis>. For <code><phrase role="identifier">type</phrase><phrase 3612 role="special">::</phrase><phrase role="identifier">dispatcher_context</phrase></code> 3613 the <code><phrase role="identifier">context</phrase></code> is associated 3614 with a <quote>dispatching</quote> fiber, responsible for dispatching 3615 awakened fibers to a scheduler’s ready-queue. The <quote>dispatching</quote> 3616 fiber is an implementation detail of the fiber manager. The context of 3617 the <quote>main</quote> or <quote>dispatching</quote> fiber — any fiber 3618 for which <code><phrase role="identifier">is_context</phrase><phrase 3619 role="special">(</phrase><phrase role="identifier">pinned_context</phrase><phrase 3620 role="special">)</phrase></code> is <code><phrase role="keyword">true</phrase></code> 3621 — must never be passed to <link linkend="context_detach"><code>context::detach()</code></link>. 3622 </para> 3623 </listitem> 3624 </varlistentry> 3625 </variablelist> 3626 <para> 3627 <bridgehead renderas="sect4" id="context_is_terminated_bridgehead"> 3628 <phrase id="context_is_terminated"/> 3629 <link linkend="context_is_terminated">Member 3630 function <code>is_terminated</code>()</link> 3631</bridgehead> 3632 </para> 3633<programlisting><phrase role="keyword">bool</phrase> <phrase role="identifier">is_terminated</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 3634</programlisting> 3635 <variablelist> 3636 <title></title> 3637 <varlistentry> 3638 <term>Returns:</term> 3639 <listitem> 3640 <para> 3641 <code><phrase role="keyword">true</phrase></code> if <code><phrase role="special">*</phrase><phrase 3642 role="keyword">this</phrase></code> is no longer a valid context. 3643 </para> 3644 </listitem> 3645 </varlistentry> 3646 <varlistentry> 3647 <term>Throws:</term> 3648 <listitem> 3649 <para> 3650 Nothing 3651 </para> 3652 </listitem> 3653 </varlistentry> 3654 <varlistentry> 3655 <term>Note:</term> 3656 <listitem> 3657 <para> 3658 The <code><phrase role="identifier">context</phrase></code> has returned 3659 from its fiber-function and is no longer considered a valid context. 3660 </para> 3661 </listitem> 3662 </varlistentry> 3663 </variablelist> 3664 <para> 3665 <bridgehead renderas="sect4" id="context_ready_is_linked_bridgehead"> 3666 <phrase id="context_ready_is_linked"/> 3667 <link linkend="context_ready_is_linked">Member 3668 function <code>ready_is_linked</code>()</link> 3669</bridgehead> 3670 </para> 3671<programlisting><phrase role="keyword">bool</phrase> <phrase role="identifier">ready_is_linked</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 3672</programlisting> 3673 <variablelist> 3674 <title></title> 3675 <varlistentry> 3676 <term>Returns:</term> 3677 <listitem> 3678 <para> 3679 <code><phrase role="keyword">true</phrase></code> if <code><phrase role="special">*</phrase><phrase 3680 role="keyword">this</phrase></code> is stored in an <link linkend="class_algorithm"><code>algorithm</code></link> 3681implementation’s 3682 ready-queue. 3683 </para> 3684 </listitem> 3685 </varlistentry> 3686 <varlistentry> 3687 <term>Throws:</term> 3688 <listitem> 3689 <para> 3690 Nothing 3691 </para> 3692 </listitem> 3693 </varlistentry> 3694 <varlistentry> 3695 <term>Note:</term> 3696 <listitem> 3697 <para> 3698 Specifically, this method indicates whether <link linkend="context_ready_link"><code>context::ready_link()</code></link> has 3699 been called on <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>. 3700 <code><phrase role="identifier">ready_is_linked</phrase><phrase role="special">()</phrase></code> 3701 has no information about participation in any other containers. 3702 </para> 3703 </listitem> 3704 </varlistentry> 3705 </variablelist> 3706 <para> 3707 <bridgehead renderas="sect4" id="context_remote_ready_is_linked_bridgehead"> 3708 <phrase id="context_remote_ready_is_linked"/> 3709 <link linkend="context_remote_ready_is_linked">Member 3710 function <code>remote_ready_is_linked</code>()</link> 3711</bridgehead> 3712 </para> 3713<programlisting><phrase role="keyword">bool</phrase> <phrase role="identifier">remote_ready_is_linked</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 3714</programlisting> 3715 <variablelist> 3716 <title></title> 3717 <varlistentry> 3718 <term>Returns:</term> 3719 <listitem> 3720 <para> 3721 <code><phrase role="keyword">true</phrase></code> if <code><phrase role="special">*</phrase><phrase 3722 role="keyword">this</phrase></code> is stored in the fiber manager’s remote-ready-queue. 3723 </para> 3724 </listitem> 3725 </varlistentry> 3726 <varlistentry> 3727 <term>Throws:</term> 3728 <listitem> 3729 <para> 3730 Nothing 3731 </para> 3732 </listitem> 3733 </varlistentry> 3734 <varlistentry> 3735 <term>Note:</term> 3736 <listitem> 3737 <para> 3738 A <code><phrase role="identifier">context</phrase></code> signaled as 3739 ready by another thread is first stored in the fiber manager’s remote-ready-queue. 3740 This is the mechanism by which the fiber manager protects an <link linkend="class_algorithm"><code>algorithm</code></link> implementation 3741 from cross-thread <link linkend="algorithm_awakened"><code>algorithm::awakened()</code></link> calls. 3742 </para> 3743 </listitem> 3744 </varlistentry> 3745 </variablelist> 3746 <para> 3747 <bridgehead renderas="sect4" id="context_wait_is_linked_bridgehead"> 3748 <phrase id="context_wait_is_linked"/> 3749 <link linkend="context_wait_is_linked">Member 3750 function <code>wait_is_linked</code>()</link> 3751</bridgehead> 3752 </para> 3753<programlisting><phrase role="keyword">bool</phrase> <phrase role="identifier">wait_is_linked</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 3754</programlisting> 3755 <variablelist> 3756 <title></title> 3757 <varlistentry> 3758 <term>Returns:</term> 3759 <listitem> 3760 <para> 3761 <code><phrase role="keyword">true</phrase></code> if <code><phrase role="special">*</phrase><phrase 3762 role="keyword">this</phrase></code> is stored in the wait-queue of some 3763 synchronization object. 3764 </para> 3765 </listitem> 3766 </varlistentry> 3767 <varlistentry> 3768 <term>Throws:</term> 3769 <listitem> 3770 <para> 3771 Nothing 3772 </para> 3773 </listitem> 3774 </varlistentry> 3775 <varlistentry> 3776 <term>Note:</term> 3777 <listitem> 3778 <para> 3779 The <code><phrase role="identifier">context</phrase></code> of a fiber 3780 waiting on a synchronization object (e.g. <code><phrase role="identifier">mutex</phrase></code>, 3781 <code><phrase role="identifier">condition_variable</phrase></code> etc.) 3782 is stored in the wait-queue of that synchronization object. 3783 </para> 3784 </listitem> 3785 </varlistentry> 3786 </variablelist> 3787 <para> 3788 <bridgehead renderas="sect4" id="context_ready_link_bridgehead"> 3789 <phrase id="context_ready_link"/> 3790 <link linkend="context_ready_link">Member function 3791 <code>ready_link</code>()</link> 3792</bridgehead> 3793 </para> 3794<programlisting><phrase role="keyword">template</phrase><phrase role="special"><</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">List</phrase> <phrase role="special">></phrase> 3795<phrase role="keyword">void</phrase> <phrase role="identifier">ready_link</phrase><phrase role="special">(</phrase> <phrase role="identifier">List</phrase> <phrase role="special">&</phrase> <phrase role="identifier">lst</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 3796</programlisting> 3797 <variablelist> 3798 <title></title> 3799 <varlistentry> 3800 <term>Effects:</term> 3801 <listitem> 3802 <para> 3803 Stores <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code> 3804 in ready-queue <code><phrase role="identifier">lst</phrase></code>. 3805 </para> 3806 </listitem> 3807 </varlistentry> 3808 <varlistentry> 3809 <term>Throws:</term> 3810 <listitem> 3811 <para> 3812 Nothing 3813 </para> 3814 </listitem> 3815 </varlistentry> 3816 <varlistentry> 3817 <term>Note:</term> 3818 <listitem> 3819 <para> 3820 Argument <code><phrase role="identifier">lst</phrase></code> must be 3821 a doubly-linked list from <ulink url="http://www.boost.org/doc/libs/release/libs/intrusive/index.html">Boost.Intrusive</ulink>, 3822 e.g. an instance of <code><phrase role="identifier">boost</phrase><phrase 3823 role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase 3824 role="special">::</phrase><phrase role="identifier">scheduler</phrase><phrase 3825 role="special">::</phrase><phrase role="identifier">ready_queue_t</phrase></code>. 3826 Specifically, it must be a <ulink url="http://www.boost.org/doc/libs/release/doc/html/intrusive/list.html"><code><phrase 3827 role="identifier">boost</phrase><phrase role="special">::</phrase><phrase 3828 role="identifier">intrusive</phrase><phrase role="special">::</phrase><phrase 3829 role="identifier">list</phrase></code></ulink> compatible with the <code><phrase 3830 role="identifier">list_member_hook</phrase></code> stored in the <code><phrase 3831 role="identifier">context</phrase></code> object. 3832 </para> 3833 </listitem> 3834 </varlistentry> 3835 </variablelist> 3836 <para> 3837 <bridgehead renderas="sect4" id="context_remote_ready_link_bridgehead"> 3838 <phrase id="context_remote_ready_link"/> 3839 <link linkend="context_remote_ready_link">Member 3840 function <code>remote_ready_link</code>()</link> 3841</bridgehead> 3842 </para> 3843<programlisting><phrase role="keyword">template</phrase><phrase role="special"><</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">List</phrase> <phrase role="special">></phrase> 3844<phrase role="keyword">void</phrase> <phrase role="identifier">remote_ready_link</phrase><phrase role="special">(</phrase> <phrase role="identifier">List</phrase> <phrase role="special">&</phrase> <phrase role="identifier">lst</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 3845</programlisting> 3846 <variablelist> 3847 <title></title> 3848 <varlistentry> 3849 <term>Effects:</term> 3850 <listitem> 3851 <para> 3852 Stores <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code> 3853 in remote-ready-queue <code><phrase role="identifier">lst</phrase></code>. 3854 </para> 3855 </listitem> 3856 </varlistentry> 3857 <varlistentry> 3858 <term>Throws:</term> 3859 <listitem> 3860 <para> 3861 Nothing 3862 </para> 3863 </listitem> 3864 </varlistentry> 3865 <varlistentry> 3866 <term>Note:</term> 3867 <listitem> 3868 <para> 3869 Argument <code><phrase role="identifier">lst</phrase></code> must be 3870 a doubly-linked list from <ulink url="http://www.boost.org/doc/libs/release/libs/intrusive/index.html">Boost.Intrusive</ulink>. 3871 </para> 3872 </listitem> 3873 </varlistentry> 3874 </variablelist> 3875 <para> 3876 <bridgehead renderas="sect4" id="context_wait_link_bridgehead"> 3877 <phrase id="context_wait_link"/> 3878 <link linkend="context_wait_link">Member function 3879 <code>wait_link</code>()</link> 3880</bridgehead> 3881 </para> 3882<programlisting><phrase role="keyword">template</phrase><phrase role="special"><</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">List</phrase> <phrase role="special">></phrase> 3883<phrase role="keyword">void</phrase> <phrase role="identifier">wait_link</phrase><phrase role="special">(</phrase> <phrase role="identifier">List</phrase> <phrase role="special">&</phrase> <phrase role="identifier">lst</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 3884</programlisting> 3885 <variablelist> 3886 <title></title> 3887 <varlistentry> 3888 <term>Effects:</term> 3889 <listitem> 3890 <para> 3891 Stores <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code> 3892 in wait-queue <code><phrase role="identifier">lst</phrase></code>. 3893 </para> 3894 </listitem> 3895 </varlistentry> 3896 <varlistentry> 3897 <term>Throws:</term> 3898 <listitem> 3899 <para> 3900 Nothing 3901 </para> 3902 </listitem> 3903 </varlistentry> 3904 <varlistentry> 3905 <term>Note:</term> 3906 <listitem> 3907 <para> 3908 Argument <code><phrase role="identifier">lst</phrase></code> must be 3909 a doubly-linked list from <ulink url="http://www.boost.org/doc/libs/release/libs/intrusive/index.html">Boost.Intrusive</ulink>. 3910 </para> 3911 </listitem> 3912 </varlistentry> 3913 </variablelist> 3914 <para> 3915 <bridgehead renderas="sect4" id="context_ready_unlink_bridgehead"> 3916 <phrase id="context_ready_unlink"/> 3917 <link linkend="context_ready_unlink">Member 3918 function <code>ready_unlink</code>()</link> 3919</bridgehead> 3920 </para> 3921<programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">ready_unlink</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 3922</programlisting> 3923 <variablelist> 3924 <title></title> 3925 <varlistentry> 3926 <term>Effects:</term> 3927 <listitem> 3928 <para> 3929 Removes <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code> 3930 from ready-queue: undoes the effect of <link linkend="context_ready_link"><code>context::ready_link()</code></link>. 3931 </para> 3932 </listitem> 3933 </varlistentry> 3934 <varlistentry> 3935 <term>Throws:</term> 3936 <listitem> 3937 <para> 3938 Nothing 3939 </para> 3940 </listitem> 3941 </varlistentry> 3942 </variablelist> 3943 <para> 3944 <bridgehead renderas="sect4" id="context_remote_ready_unlink_bridgehead"> 3945 <phrase id="context_remote_ready_unlink"/> 3946 <link linkend="context_remote_ready_unlink">Member 3947 function <code>remote_ready_unlink</code>()</link> 3948</bridgehead> 3949 </para> 3950<programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">remote_ready_unlink</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 3951</programlisting> 3952 <variablelist> 3953 <title></title> 3954 <varlistentry> 3955 <term>Effects:</term> 3956 <listitem> 3957 <para> 3958 Removes <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code> 3959 from remote-ready-queue. 3960 </para> 3961 </listitem> 3962 </varlistentry> 3963 <varlistentry> 3964 <term>Throws:</term> 3965 <listitem> 3966 <para> 3967 Nothing 3968 </para> 3969 </listitem> 3970 </varlistentry> 3971 </variablelist> 3972 <para> 3973 <bridgehead renderas="sect4" id="context_wait_unlink_bridgehead"> 3974 <phrase id="context_wait_unlink"/> 3975 <link linkend="context_wait_unlink">Member 3976 function <code>wait_unlink</code>()</link> 3977</bridgehead> 3978 </para> 3979<programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">wait_unlink</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 3980</programlisting> 3981 <variablelist> 3982 <title></title> 3983 <varlistentry> 3984 <term>Effects:</term> 3985 <listitem> 3986 <para> 3987 Removes <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code> 3988 from wait-queue. 3989 </para> 3990 </listitem> 3991 </varlistentry> 3992 <varlistentry> 3993 <term>Throws:</term> 3994 <listitem> 3995 <para> 3996 Nothing 3997 </para> 3998 </listitem> 3999 </varlistentry> 4000 </variablelist> 4001 <para> 4002 <bridgehead renderas="sect4" id="context_suspend_bridgehead"> 4003 <phrase id="context_suspend"/> 4004 <link linkend="context_suspend">Member function <code>suspend</code>()</link> 4005</bridgehead> 4006 </para> 4007<programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">suspend</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 4008</programlisting> 4009 <variablelist> 4010 <title></title> 4011 <varlistentry> 4012 <term>Effects:</term> 4013 <listitem> 4014 <para> 4015 Suspends the running fiber (the fiber associated with <code><phrase role="special">*</phrase><phrase 4016 role="keyword">this</phrase></code>) until some other fiber passes <code><phrase 4017 role="keyword">this</phrase></code> to <link linkend="context_schedule"><code>context::schedule()</code></link>. 4018 <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code> 4019 is marked as not-ready, and control passes to the scheduler to select 4020 another fiber to run. 4021 </para> 4022 </listitem> 4023 </varlistentry> 4024 <varlistentry> 4025 <term>Throws:</term> 4026 <listitem> 4027 <para> 4028 Nothing 4029 </para> 4030 </listitem> 4031 </varlistentry> 4032 <varlistentry> 4033 <term>Note:</term> 4034 <listitem> 4035 <para> 4036 This is a low-level API potentially useful for integration with other 4037 frameworks. It is not intended to be directly invoked by a typical application 4038 program. 4039 </para> 4040 </listitem> 4041 </varlistentry> 4042 <varlistentry> 4043 <term>Note:</term> 4044 <listitem> 4045 <para> 4046 The burden is on the caller to arrange for a call to <code><phrase role="identifier">schedule</phrase><phrase 4047 role="special">()</phrase></code> with a pointer to <code><phrase role="keyword">this</phrase></code> 4048 at some future time. 4049 </para> 4050 </listitem> 4051 </varlistentry> 4052 </variablelist> 4053 <para> 4054 <bridgehead renderas="sect4" id="context_schedule_bridgehead"> 4055 <phrase id="context_schedule"/> 4056 <link linkend="context_schedule">Member function 4057 <code>schedule</code>()</link> 4058</bridgehead> 4059 </para> 4060<programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">schedule</phrase><phrase role="special">(</phrase> <phrase role="identifier">context</phrase> <phrase role="special">*</phrase> <phrase role="identifier">ctx</phrase> <phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 4061</programlisting> 4062 <variablelist> 4063 <title></title> 4064 <varlistentry> 4065 <term>Effects:</term> 4066 <listitem> 4067 <para> 4068 Mark the fiber associated with context <code><phrase role="special">*</phrase><phrase 4069 role="identifier">ctx</phrase></code> as being ready to run. This does 4070 not immediately resume that fiber; rather it passes the fiber to the 4071 scheduler for subsequent resumption. If the scheduler is idle (has not 4072 returned from a call to <link linkend="algorithm_suspend_until"><code>algorithm::suspend_until()</code></link>), 4073 <link linkend="algorithm_notify"><code>algorithm::notify()</code></link> is called to wake it up. 4074 </para> 4075 </listitem> 4076 </varlistentry> 4077 <varlistentry> 4078 <term>Throws:</term> 4079 <listitem> 4080 <para> 4081 Nothing 4082 </para> 4083 </listitem> 4084 </varlistentry> 4085 <varlistentry> 4086 <term>Note:</term> 4087 <listitem> 4088 <para> 4089 This is a low-level API potentially useful for integration with other 4090 frameworks. It is not intended to be directly invoked by a typical application 4091 program. 4092 </para> 4093 </listitem> 4094 </varlistentry> 4095 <varlistentry> 4096 <term>Note:</term> 4097 <listitem> 4098 <para> 4099 It is explicitly supported to call <code><phrase role="identifier">schedule</phrase><phrase 4100 role="special">(</phrase><phrase role="identifier">ctx</phrase><phrase 4101 role="special">)</phrase></code> from a thread other than the one on 4102 which <code><phrase role="special">*</phrase><phrase role="identifier">ctx</phrase></code> 4103 is currently suspended. The corresponding fiber will be resumed on its 4104 original thread in due course. 4105 </para> 4106 </listitem> 4107 </varlistentry> 4108 </variablelist> 4109 <para> 4110 <bridgehead renderas="sect4" id="context_less_bridgehead"> 4111 <phrase id="context_less"/> 4112 <link linkend="context_less">Non-member function <code>operator<()</code></link> 4113</bridgehead> 4114 </para> 4115<programlisting><phrase role="keyword">bool</phrase> <phrase role="keyword">operator</phrase><phrase role="special"><(</phrase> <phrase role="identifier">context</phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">l</phrase><phrase role="special">,</phrase> <phrase role="identifier">context</phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">r</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 4116</programlisting> 4117 <variablelist> 4118 <title></title> 4119 <varlistentry> 4120 <term>Returns:</term> 4121 <listitem> 4122 <para> 4123 <code><phrase role="keyword">true</phrase></code> if <code><phrase role="identifier">l</phrase><phrase 4124 role="special">.</phrase><phrase role="identifier">get_id</phrase><phrase 4125 role="special">()</phrase> <phrase role="special"><</phrase> <phrase 4126 role="identifier">r</phrase><phrase role="special">.</phrase><phrase 4127 role="identifier">get_id</phrase><phrase role="special">()</phrase></code> 4128 is <code><phrase role="keyword">true</phrase></code>, <code><phrase role="keyword">false</phrase></code> 4129 otherwise. 4130 </para> 4131 </listitem> 4132 </varlistentry> 4133 <varlistentry> 4134 <term>Throws:</term> 4135 <listitem> 4136 <para> 4137 Nothing. 4138 </para> 4139 </listitem> 4140 </varlistentry> 4141 </variablelist> 4142 </section> 4143 <section id="fiber.stack"> 4144 <title><anchor id="stack"/><link linkend="fiber.stack">Stack allocation</link></title> 4145 <para> 4146 A <link linkend="class_fiber"><code>fiber</code></link> uses internally an __econtext__ which manages a set of registers 4147 and a stack. The memory used by the stack is allocated/deallocated via a <emphasis>stack_allocator</emphasis> 4148 which is required to model a <link linkend="stack_allocator_concept"><emphasis>stack-allocator 4149 concept</emphasis></link>. 4150 </para> 4151 <para> 4152 A <emphasis>stack_allocator</emphasis> can be passed to <link linkend="fiber_fiber"><code><phrase 4153 role="identifier">fiber</phrase><phrase role="special">::</phrase><phrase role="identifier">fiber</phrase><phrase 4154 role="special">()</phrase></code></link> or to <link linkend="fibers_async"><code>fibers::async()</code></link>. 4155 </para> 4156 <anchor id="stack_allocator_concept"/> 4157 <bridgehead renderas="sect3" id="fiber.stack.h0"> 4158 <phrase id="fiber.stack.stack_allocator_concept"/><link linkend="fiber.stack.stack_allocator_concept">stack-allocator 4159 concept</link> 4160 </bridgehead> 4161 <para> 4162 A <emphasis>stack_allocator</emphasis> must satisfy the <emphasis>stack-allocator 4163 concept</emphasis> requirements shown in the following table, in which <code><phrase 4164 role="identifier">a</phrase></code> is an object of a <emphasis>stack_allocator</emphasis> 4165 type, <code><phrase role="identifier">sctx</phrase></code> is a <ulink url="http://www.boost.org/doc/libs/release/libs/context/doc/html/context/stack/stack_context.html"><code><phrase 4166 role="identifier">stack_context</phrase></code></ulink>, and <code><phrase 4167 role="identifier">size</phrase></code> is a <code><phrase role="identifier">std</phrase><phrase 4168 role="special">::</phrase><phrase role="identifier">size_t</phrase></code>: 4169 </para> 4170 <informaltable frame="all"> 4171 <tgroup cols="3"> 4172 <thead> 4173 <row> 4174 <entry> 4175 <para> 4176 expression 4177 </para> 4178 </entry> 4179 <entry> 4180 <para> 4181 return type 4182 </para> 4183 </entry> 4184 <entry> 4185 <para> 4186 notes 4187 </para> 4188 </entry> 4189 </row> 4190 </thead> 4191 <tbody> 4192 <row> 4193 <entry> 4194 <para> 4195 <code><phrase role="identifier">a</phrase><phrase role="special">(</phrase><phrase 4196 role="identifier">size</phrase><phrase role="special">)</phrase></code> 4197 </para> 4198 </entry> 4199 <entry> 4200 </entry> 4201 <entry> 4202 <para> 4203 creates a stack allocator 4204 </para> 4205 </entry> 4206 </row> 4207 <row> 4208 <entry> 4209 <para> 4210 <code><phrase role="identifier">a</phrase><phrase role="special">.</phrase><phrase 4211 role="identifier">allocate</phrase><phrase role="special">()</phrase></code> 4212 </para> 4213 </entry> 4214 <entry> 4215 <para> 4216 <ulink url="http://www.boost.org/doc/libs/release/libs/context/doc/html/context/stack/stack_context.html"><code><phrase 4217 role="identifier">stack_context</phrase></code></ulink> 4218 </para> 4219 </entry> 4220 <entry> 4221 <para> 4222 creates a stack 4223 </para> 4224 </entry> 4225 </row> 4226 <row> 4227 <entry> 4228 <para> 4229 <code><phrase role="identifier">a</phrase><phrase role="special">.</phrase><phrase 4230 role="identifier">deallocate</phrase><phrase role="special">(</phrase> 4231 <phrase role="identifier">sctx</phrase><phrase role="special">)</phrase></code> 4232 </para> 4233 </entry> 4234 <entry> 4235 <para> 4236 <code><phrase role="keyword">void</phrase></code> 4237 </para> 4238 </entry> 4239 <entry> 4240 <para> 4241 deallocates the stack created by <code><phrase role="identifier">a</phrase><phrase 4242 role="special">.</phrase><phrase role="identifier">allocate</phrase><phrase 4243 role="special">()</phrase></code> 4244 </para> 4245 </entry> 4246 </row> 4247 </tbody> 4248 </tgroup> 4249 </informaltable> 4250 <important> 4251 <para> 4252 The implementation of <code><phrase role="identifier">allocate</phrase><phrase 4253 role="special">()</phrase></code> might include logic to protect against 4254 exceeding the context's available stack size rather than leaving it as undefined 4255 behaviour. 4256 </para> 4257 </important> 4258 <important> 4259 <para> 4260 Calling <code><phrase role="identifier">deallocate</phrase><phrase role="special">()</phrase></code> 4261 with a <ulink url="http://www.boost.org/doc/libs/release/libs/context/doc/html/context/stack/stack_context.html"><code><phrase 4262 role="identifier">stack_context</phrase></code></ulink> not obtained from 4263 <code><phrase role="identifier">allocate</phrase><phrase role="special">()</phrase></code> 4264 results in undefined behaviour. 4265 </para> 4266 </important> 4267 <note> 4268 <para> 4269 The memory for the stack is not required to be aligned; alignment takes place 4270 inside __econtext__. 4271 </para> 4272 </note> 4273 <para> 4274 See also <ulink url="http://www.boost.org/doc/libs/release/libs/context/doc/html/context/stack.html">Boost.Context 4275 stack allocation</ulink>. In particular, <code><phrase role="identifier">traits_type</phrase></code> 4276 methods are as described for <ulink url="http://www.boost.org/doc/libs/release/libs/context/doc/html/context/stack/stack_traits.html"><code><phrase 4277 role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">context</phrase><phrase 4278 role="special">::</phrase><phrase role="identifier">stack_traits</phrase></code></ulink>. 4279 </para> 4280 <para> 4281 <bridgehead renderas="sect4" id="class_protected_fixedsize_stack_bridgehead"> 4282 <phrase id="class_protected_fixedsize_stack"/> 4283 <link linkend="class_protected_fixedsize_stack">Class 4284 <code>protected_fixedsize_stack</code></link> 4285</bridgehead> 4286 </para> 4287 <para> 4288 <emphasis role="bold">Boost.Fiber</emphasis> provides the class <link linkend="class_protected_fixedsize_stack"><code>protected_fixedsize_stack</code></link> which 4289 models the <link linkend="stack_allocator_concept"><emphasis>stack-allocator 4290 concept</emphasis></link>. It appends a guard page at the end of each stack 4291 to protect against exceeding the stack. If the guard page is accessed (read 4292 or write operation) a segmentation fault/access violation is generated by the 4293 operating system. 4294 </para> 4295 <important> 4296 <para> 4297 Using <link linkend="class_protected_fixedsize_stack"><code>protected_fixedsize_stack</code></link> is expensive. 4298 Launching a new fiber with a stack of this type incurs the overhead of setting 4299 the memory protection; once allocated, this stack is just as efficient to 4300 use as <link linkend="class_fixedsize_stack"><code>fixedsize_stack</code></link>. 4301 </para> 4302 </important> 4303 <note> 4304 <para> 4305 The appended <code><phrase role="identifier">guard</phrase> <phrase role="identifier">page</phrase></code> 4306 is <emphasis role="bold">not</emphasis> mapped to physical memory, only virtual 4307 addresses are used. 4308 </para> 4309 </note> 4310<programlisting><phrase role="preprocessor">#include</phrase> <phrase role="special"><</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">></phrase> 4311 4312<phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase> 4313<phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase> 4314 4315<phrase role="keyword">struct</phrase> <phrase role="identifier">protected_fixedsize</phrase> <phrase role="special">{</phrase> 4316 <phrase role="identifier">protected_fixesize</phrase><phrase role="special">(</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">size</phrase> <phrase role="special">=</phrase> <phrase role="identifier">traits_type</phrase><phrase role="special">::</phrase><phrase role="identifier">default_size</phrase><phrase role="special">());</phrase> 4317 4318 <phrase role="identifier">stack_context</phrase> <phrase role="identifier">allocate</phrase><phrase role="special">();</phrase> 4319 4320 <phrase role="keyword">void</phrase> <phrase role="identifier">deallocate</phrase><phrase role="special">(</phrase> <phrase role="identifier">stack_context</phrase> <phrase role="special">&);</phrase> 4321<phrase role="special">}</phrase> 4322 4323<phrase role="special">}}</phrase> 4324</programlisting> 4325 <para> 4326 <bridgehead renderas="sect4" id="protected_fixedsize_allocate_bridgehead"> 4327 <phrase id="protected_fixedsize_allocate"/> 4328 <link linkend="protected_fixedsize_allocate">Member 4329 function <code>allocate</code>()</link> 4330</bridgehead> 4331 </para> 4332<programlisting><phrase role="identifier">stack_context</phrase> <phrase role="identifier">allocate</phrase><phrase role="special">();</phrase> 4333</programlisting> 4334 <variablelist> 4335 <title></title> 4336 <varlistentry> 4337 <term>Preconditions:</term> 4338 <listitem> 4339 <para> 4340 <code><phrase role="identifier">traits_type</phrase><phrase role="special">::</phrase><phrase 4341 role="identifier">minimum_size</phrase><phrase role="special">()</phrase> 4342 <phrase role="special"><=</phrase> <phrase role="identifier">size</phrase></code> 4343 and <code><phrase role="identifier">traits_type</phrase><phrase role="special">::</phrase><phrase 4344 role="identifier">is_unbounded</phrase><phrase role="special">()</phrase> 4345 <phrase role="special">||</phrase> <phrase role="special">(</phrase> 4346 <phrase role="identifier">size</phrase> <phrase role="special"><=</phrase> 4347 <phrase role="identifier">traits_type</phrase><phrase role="special">::</phrase><phrase 4348 role="identifier">maximum_size</phrase><phrase role="special">()</phrase> 4349 <phrase role="special">)</phrase></code>. 4350 </para> 4351 </listitem> 4352 </varlistentry> 4353 <varlistentry> 4354 <term>Effects:</term> 4355 <listitem> 4356 <para> 4357 Allocates memory of at least <code><phrase role="identifier">size</phrase></code> 4358 bytes and stores a pointer to the stack and its actual size in <code><phrase 4359 role="identifier">sctx</phrase></code>. Depending on the architecture 4360 (the stack grows downwards/upwards) the stored address is the highest/lowest 4361 address of the stack. 4362 </para> 4363 </listitem> 4364 </varlistentry> 4365 </variablelist> 4366 <para> 4367 <bridgehead renderas="sect4" id="protected_fixesize_deallocate_bridgehead"> 4368 <phrase id="protected_fixesize_deallocate"/> 4369 <link linkend="protected_fixesize_deallocate">Member 4370 function <code>deallocate</code>()</link> 4371</bridgehead> 4372 </para> 4373<programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">deallocate</phrase><phrase role="special">(</phrase> <phrase role="identifier">stack_context</phrase> <phrase role="special">&</phrase> <phrase role="identifier">sctx</phrase><phrase role="special">);</phrase> 4374</programlisting> 4375 <variablelist> 4376 <title></title> 4377 <varlistentry> 4378 <term>Preconditions:</term> 4379 <listitem> 4380 <para> 4381 <code><phrase role="identifier">sctx</phrase><phrase role="special">.</phrase><phrase 4382 role="identifier">sp</phrase></code> is valid, <code><phrase role="identifier">traits_type</phrase><phrase 4383 role="special">::</phrase><phrase role="identifier">minimum_size</phrase><phrase 4384 role="special">()</phrase> <phrase role="special"><=</phrase> <phrase 4385 role="identifier">sctx</phrase><phrase role="special">.</phrase><phrase 4386 role="identifier">size</phrase></code> and <code><phrase role="identifier">traits_type</phrase><phrase 4387 role="special">::</phrase><phrase role="identifier">is_unbounded</phrase><phrase 4388 role="special">()</phrase> <phrase role="special">||</phrase> <phrase 4389 role="special">(</phrase> <phrase role="identifier">sctx</phrase><phrase 4390 role="special">.</phrase><phrase role="identifier">size</phrase> <phrase 4391 role="special"><=</phrase> <phrase role="identifier">traits_type</phrase><phrase 4392 role="special">::</phrase><phrase role="identifier">maximum_size</phrase><phrase 4393 role="special">()</phrase> <phrase role="special">)</phrase></code>. 4394 </para> 4395 </listitem> 4396 </varlistentry> 4397 <varlistentry> 4398 <term>Effects:</term> 4399 <listitem> 4400 <para> 4401 Deallocates the stack space. 4402 </para> 4403 </listitem> 4404 </varlistentry> 4405 </variablelist> 4406 <para> 4407 <bridgehead renderas="sect4" id="class_pooled_fixedsize_stack_bridgehead"> 4408 <phrase id="class_pooled_fixedsize_stack"/> 4409 <link linkend="class_pooled_fixedsize_stack">Class 4410 <code>pooled_fixedsize_stack</code></link> 4411</bridgehead> 4412 </para> 4413 <para> 4414 <emphasis role="bold">Boost.Fiber</emphasis> provides the class <link linkend="class_pooled_fixedsize_stack"><code>pooled_fixedsize_stack</code></link> which 4415 models the <link linkend="stack_allocator_concept"><emphasis>stack-allocator 4416 concept</emphasis></link>. In contrast to <link linkend="class_protected_fixedsize_stack"><code>protected_fixedsize_stack</code></link> it 4417 does not append a guard page at the end of each stack. The memory is managed 4418 internally by <ulink url="http://www.boost.org/doc/libs/release/libs/pool/doc/html/boost/pool.html"><code><phrase 4419 role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">pool</phrase><phrase 4420 role="special"><></phrase></code></ulink>. 4421 </para> 4422<programlisting><phrase role="preprocessor">#include</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">pooled_fixedsize_stack</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">></phrase> 4423 4424<phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase> 4425<phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase> 4426 4427<phrase role="keyword">struct</phrase> <phrase role="identifier">pooled_fixedsize_stack</phrase> <phrase role="special">{</phrase> 4428 <phrase role="identifier">pooled_fixedsize_stack</phrase><phrase role="special">(</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">stack_size</phrase> <phrase role="special">=</phrase> <phrase role="identifier">traits_type</phrase><phrase role="special">::</phrase><phrase role="identifier">default_size</phrase><phrase role="special">(),</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">next_size</phrase> <phrase role="special">=</phrase> <phrase role="number">32</phrase><phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">max_size</phrase> <phrase role="special">=</phrase> <phrase role="number">0</phrase><phrase role="special">);</phrase> 4429 4430 <phrase role="identifier">stack_context</phrase> <phrase role="identifier">allocate</phrase><phrase role="special">();</phrase> 4431 4432 <phrase role="keyword">void</phrase> <phrase role="identifier">deallocate</phrase><phrase role="special">(</phrase> <phrase role="identifier">stack_context</phrase> <phrase role="special">&);</phrase> 4433<phrase role="special">}</phrase> 4434 4435<phrase role="special">}}</phrase> 4436</programlisting> 4437 <para> 4438 <bridgehead renderas="sect4" id="pooled_fixedsize_bridgehead"> 4439 <phrase id="pooled_fixedsize"/> 4440 <link linkend="pooled_fixedsize">Constructor</link> 4441</bridgehead> 4442 </para> 4443<programlisting><phrase role="identifier">pooled_fixedsize_stack</phrase><phrase role="special">(</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">stack_size</phrase><phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">next_size</phrase><phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">max_size</phrase><phrase role="special">);</phrase> 4444</programlisting> 4445 <variablelist> 4446 <title></title> 4447 <varlistentry> 4448 <term>Preconditions:</term> 4449 <listitem> 4450 <para> 4451 <code><phrase role="identifier">traits_type</phrase><phrase role="special">::</phrase><phrase 4452 role="identifier">is_unbounded</phrase><phrase role="special">()</phrase> 4453 <phrase role="special">||</phrase> <phrase role="special">(</phrase> 4454 <phrase role="identifier">traits_type</phrase><phrase role="special">::</phrase><phrase 4455 role="identifier">maximum_size</phrase><phrase role="special">()</phrase> 4456 <phrase role="special">>=</phrase> <phrase role="identifier">stack_size</phrase><phrase 4457 role="special">)</phrase></code> and <code><phrase role="number">0</phrase> 4458 <phrase role="special"><</phrase> <phrase role="identifier">next_size</phrase></code>. 4459 </para> 4460 </listitem> 4461 </varlistentry> 4462 <varlistentry> 4463 <term>Effects:</term> 4464 <listitem> 4465 <para> 4466 Allocates memory of at least <code><phrase role="identifier">stack_size</phrase></code> 4467 bytes and stores a pointer to the stack and its actual size in <code><phrase 4468 role="identifier">sctx</phrase></code>. Depending on the architecture 4469 (the stack grows downwards/upwards) the stored address is the highest/lowest 4470 address of the stack. Argument <code><phrase role="identifier">next_size</phrase></code> 4471 determines the number of stacks to request from the system the first 4472 time that <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code> 4473 needs to allocate system memory. The third argument <code><phrase role="identifier">max_size</phrase></code> 4474 controls how much memory might be allocated for stacks — a value of zero 4475 means no upper limit. 4476 </para> 4477 </listitem> 4478 </varlistentry> 4479 </variablelist> 4480 <para> 4481 <bridgehead renderas="sect4" id="pooled_fixedsize_allocate_bridgehead"> 4482 <phrase id="pooled_fixedsize_allocate"/> 4483 <link linkend="pooled_fixedsize_allocate">Member 4484 function <code>allocate</code>()</link> 4485</bridgehead> 4486 </para> 4487<programlisting><phrase role="identifier">stack_context</phrase> <phrase role="identifier">allocate</phrase><phrase role="special">();</phrase> 4488</programlisting> 4489 <variablelist> 4490 <title></title> 4491 <varlistentry> 4492 <term>Preconditions:</term> 4493 <listitem> 4494 <para> 4495 <code><phrase role="identifier">traits_type</phrase><phrase role="special">::</phrase><phrase 4496 role="identifier">is_unbounded</phrase><phrase role="special">()</phrase> 4497 <phrase role="special">||</phrase> <phrase role="special">(</phrase> 4498 <phrase role="identifier">traits_type</phrase><phrase role="special">::</phrase><phrase 4499 role="identifier">maximum_size</phrase><phrase role="special">()</phrase> 4500 <phrase role="special">>=</phrase> <phrase role="identifier">stack_size</phrase><phrase 4501 role="special">)</phrase></code>. 4502 </para> 4503 </listitem> 4504 </varlistentry> 4505 <varlistentry> 4506 <term>Effects:</term> 4507 <listitem> 4508 <para> 4509 Allocates memory of at least <code><phrase role="identifier">stack_size</phrase></code> 4510 bytes and stores a pointer to the stack and its actual size in <code><phrase 4511 role="identifier">sctx</phrase></code>. Depending on the architecture 4512 (the stack grows downwards/upwards) the stored address is the highest/lowest 4513 address of the stack. 4514 </para> 4515 </listitem> 4516 </varlistentry> 4517 </variablelist> 4518 <para> 4519 <bridgehead renderas="sect4" id="pooled_fixesize_deallocate_bridgehead"> 4520 <phrase id="pooled_fixesize_deallocate"/> 4521 <link linkend="pooled_fixesize_deallocate">Member 4522 function <code>deallocate</code>()</link> 4523</bridgehead> 4524 </para> 4525<programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">deallocate</phrase><phrase role="special">(</phrase> <phrase role="identifier">stack_context</phrase> <phrase role="special">&</phrase> <phrase role="identifier">sctx</phrase><phrase role="special">);</phrase> 4526</programlisting> 4527 <variablelist> 4528 <title></title> 4529 <varlistentry> 4530 <term>Preconditions:</term> 4531 <listitem> 4532 <para> 4533 <code><phrase role="identifier">sctx</phrase><phrase role="special">.</phrase><phrase 4534 role="identifier">sp</phrase></code> is valid, <code><phrase role="identifier">traits_type</phrase><phrase 4535 role="special">::</phrase><phrase role="identifier">is_unbounded</phrase><phrase 4536 role="special">()</phrase> <phrase role="special">||</phrase> <phrase 4537 role="special">(</phrase> <phrase role="identifier">traits_type</phrase><phrase 4538 role="special">::</phrase><phrase role="identifier">maximum_size</phrase><phrase 4539 role="special">()</phrase> <phrase role="special">>=</phrase> <phrase 4540 role="identifier">sctx</phrase><phrase role="special">.</phrase><phrase 4541 role="identifier">size</phrase><phrase role="special">)</phrase></code>. 4542 </para> 4543 </listitem> 4544 </varlistentry> 4545 <varlistentry> 4546 <term>Effects:</term> 4547 <listitem> 4548 <para> 4549 Deallocates the stack space. 4550 </para> 4551 </listitem> 4552 </varlistentry> 4553 </variablelist> 4554 <note> 4555 <para> 4556 This stack allocator is not thread safe. 4557 </para> 4558 </note> 4559 <para> 4560 <bridgehead renderas="sect4" id="class_fixedsize_stack_bridgehead"> 4561 <phrase id="class_fixedsize_stack"/> 4562 <link linkend="class_fixedsize_stack">Class 4563 <code>fixedsize_stack</code></link> 4564</bridgehead> 4565 </para> 4566 <para> 4567 <emphasis role="bold">Boost.Fiber</emphasis> provides the class <link linkend="class_fixedsize_stack"><code>fixedsize_stack</code></link> which 4568 models the <link linkend="stack_allocator_concept"><emphasis>stack-allocator 4569 concept</emphasis></link>. In contrast to <link linkend="class_protected_fixedsize_stack"><code>protected_fixedsize_stack</code></link> it 4570 does not append a guard page at the end of each stack. The memory is simply 4571 managed by <code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase 4572 role="identifier">malloc</phrase><phrase role="special">()</phrase></code> 4573 and <code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase 4574 role="identifier">free</phrase><phrase role="special">()</phrase></code>. 4575 </para> 4576<programlisting><phrase role="preprocessor">#include</phrase> <phrase role="special"><</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">></phrase> 4577 4578<phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase> 4579<phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase> 4580 4581<phrase role="keyword">struct</phrase> <phrase role="identifier">fixedsize_stack</phrase> <phrase role="special">{</phrase> 4582 <phrase role="identifier">fixedsize_stack</phrase><phrase role="special">(</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">size</phrase> <phrase role="special">=</phrase> <phrase role="identifier">traits_type</phrase><phrase role="special">::</phrase><phrase role="identifier">default_size</phrase><phrase role="special">());</phrase> 4583 4584 <phrase role="identifier">stack_context</phrase> <phrase role="identifier">allocate</phrase><phrase role="special">();</phrase> 4585 4586 <phrase role="keyword">void</phrase> <phrase role="identifier">deallocate</phrase><phrase role="special">(</phrase> <phrase role="identifier">stack_context</phrase> <phrase role="special">&);</phrase> 4587<phrase role="special">}</phrase> 4588 4589<phrase role="special">}}</phrase> 4590</programlisting> 4591 <para> 4592 <bridgehead renderas="sect4" id="fixedsize_allocate_bridgehead"> 4593 <phrase id="fixedsize_allocate"/> 4594 <link linkend="fixedsize_allocate">Member function 4595 <code>allocate</code>()</link> 4596</bridgehead> 4597 </para> 4598<programlisting><phrase role="identifier">stack_context</phrase> <phrase role="identifier">allocate</phrase><phrase role="special">();</phrase> 4599</programlisting> 4600 <variablelist> 4601 <title></title> 4602 <varlistentry> 4603 <term>Preconditions:</term> 4604 <listitem> 4605 <para> 4606 <code><phrase role="identifier">traits_type</phrase><phrase role="special">::</phrase><phrase 4607 role="identifier">minimum_size</phrase><phrase role="special">()</phrase> 4608 <phrase role="special"><=</phrase> <phrase role="identifier">size</phrase></code> 4609 and <code><phrase role="identifier">traits_type</phrase><phrase role="special">::</phrase><phrase 4610 role="identifier">is_unbounded</phrase><phrase role="special">()</phrase> 4611 <phrase role="special">||</phrase> <phrase role="special">(</phrase> 4612 <phrase role="identifier">traits_type</phrase><phrase role="special">::</phrase><phrase 4613 role="identifier">maximum_size</phrase><phrase role="special">()</phrase> 4614 <phrase role="special">>=</phrase> <phrase role="identifier">size</phrase><phrase 4615 role="special">)</phrase></code>. 4616 </para> 4617 </listitem> 4618 </varlistentry> 4619 <varlistentry> 4620 <term>Effects:</term> 4621 <listitem> 4622 <para> 4623 Allocates memory of at least <code><phrase role="identifier">size</phrase></code> 4624 bytes and stores a pointer to the stack and its actual size in <code><phrase 4625 role="identifier">sctx</phrase></code>. Depending on the architecture 4626 (the stack grows downwards/upwards) the stored address is the highest/lowest 4627 address of the stack. 4628 </para> 4629 </listitem> 4630 </varlistentry> 4631 </variablelist> 4632 <para> 4633 <bridgehead renderas="sect4" id="fixesize_deallocate_bridgehead"> 4634 <phrase id="fixesize_deallocate"/> 4635 <link linkend="fixesize_deallocate">Member 4636 function <code>deallocate</code>()</link> 4637</bridgehead> 4638 </para> 4639<programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">deallocate</phrase><phrase role="special">(</phrase> <phrase role="identifier">stack_context</phrase> <phrase role="special">&</phrase> <phrase role="identifier">sctx</phrase><phrase role="special">);</phrase> 4640</programlisting> 4641 <variablelist> 4642 <title></title> 4643 <varlistentry> 4644 <term>Preconditions:</term> 4645 <listitem> 4646 <para> 4647 <code><phrase role="identifier">sctx</phrase><phrase role="special">.</phrase><phrase 4648 role="identifier">sp</phrase></code> is valid, <code><phrase role="identifier">traits_type</phrase><phrase 4649 role="special">::</phrase><phrase role="identifier">minimum_size</phrase><phrase 4650 role="special">()</phrase> <phrase role="special"><=</phrase> <phrase 4651 role="identifier">sctx</phrase><phrase role="special">.</phrase><phrase 4652 role="identifier">size</phrase></code> and <code><phrase role="identifier">traits_type</phrase><phrase 4653 role="special">::</phrase><phrase role="identifier">is_unbounded</phrase><phrase 4654 role="special">()</phrase> <phrase role="special">||</phrase> <phrase 4655 role="special">(</phrase> <phrase role="identifier">traits_type</phrase><phrase 4656 role="special">::</phrase><phrase role="identifier">maximum_size</phrase><phrase 4657 role="special">()</phrase> <phrase role="special">>=</phrase> <phrase 4658 role="identifier">sctx</phrase><phrase role="special">.</phrase><phrase 4659 role="identifier">size</phrase><phrase role="special">)</phrase></code>. 4660 </para> 4661 </listitem> 4662 </varlistentry> 4663 <varlistentry> 4664 <term>Effects:</term> 4665 <listitem> 4666 <para> 4667 Deallocates the stack space. 4668 </para> 4669 </listitem> 4670 </varlistentry> 4671 </variablelist> 4672 <para> 4673 <anchor id="segmented"/><bridgehead renderas="sect4" id="class_segmented_stack_bridgehead"> 4674 <phrase id="class_segmented_stack"/> 4675 <link linkend="class_segmented_stack">Class 4676 <code>segmented_stack</code></link> 4677</bridgehead> 4678 </para> 4679 <para> 4680 <emphasis role="bold">Boost.Fiber</emphasis> supports usage of a <link linkend="class_segmented_stack"><code>segmented_stack</code></link>, 4681 i.e. the stack grows on demand. The fiber is created with a minimal stack size 4682 which will be increased as required. Class <link linkend="class_segmented_stack"><code>segmented_stack</code></link> models 4683 the <link linkend="stack_allocator_concept"><emphasis>stack-allocator concept</emphasis></link>. 4684 In contrast to <link linkend="class_protected_fixedsize_stack"><code>protected_fixedsize_stack</code></link> and 4685 <link linkend="class_fixedsize_stack"><code>fixedsize_stack</code></link> it creates a stack which grows on demand. 4686 </para> 4687 <note> 4688 <para> 4689 Segmented stacks are currently only supported by <emphasis role="bold">gcc</emphasis> 4690 from version <emphasis role="bold">4.7</emphasis> and <emphasis role="bold">clang</emphasis> 4691 from version <emphasis role="bold">3.4</emphasis> onwards. In order to use 4692 a <link linkend="class_segmented_stack"><code>segmented_stack</code></link> <emphasis role="bold">Boost.Fiber</emphasis> 4693 must be built with property <code><phrase role="identifier">segmented</phrase><phrase 4694 role="special">-</phrase><phrase role="identifier">stacks</phrase></code>, 4695 e.g. <emphasis role="bold">toolset=gcc segmented-stacks=on</emphasis> and 4696 applying BOOST_USE_SEGMENTED_STACKS at b2/bjam command line. 4697 </para> 4698 </note> 4699 <note> 4700 <para> 4701 Segmented stacks can only be used with callcc() using property <code><phrase 4702 role="identifier">context</phrase><phrase role="special">-</phrase><phrase 4703 role="identifier">impl</phrase><phrase role="special">=</phrase><phrase role="identifier">ucontext</phrase></code>. 4704 </para> 4705 </note> 4706<programlisting><phrase role="preprocessor">#include</phrase> <phrase role="special"><</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">></phrase> 4707 4708<phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase> 4709<phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase> 4710 4711<phrase role="keyword">struct</phrase> <phrase role="identifier">segmented_stack</phrase> <phrase role="special">{</phrase> 4712 <phrase role="identifier">segmented_stack</phrase><phrase role="special">(</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">stack_size</phrase> <phrase role="special">=</phrase> <phrase role="identifier">traits_type</phrase><phrase role="special">::</phrase><phrase role="identifier">default_size</phrase><phrase role="special">());</phrase> 4713 4714 <phrase role="identifier">stack_context</phrase> <phrase role="identifier">allocate</phrase><phrase role="special">();</phrase> 4715 4716 <phrase role="keyword">void</phrase> <phrase role="identifier">deallocate</phrase><phrase role="special">(</phrase> <phrase role="identifier">stack_context</phrase> <phrase role="special">&);</phrase> 4717<phrase role="special">}</phrase> 4718 4719<phrase role="special">}}</phrase> 4720</programlisting> 4721 <para> 4722 <bridgehead renderas="sect4" id="segmented_allocate_bridgehead"> 4723 <phrase id="segmented_allocate"/> 4724 <link linkend="segmented_allocate">Member function 4725 <code>allocate</code>()</link> 4726</bridgehead> 4727 </para> 4728<programlisting><phrase role="identifier">stack_context</phrase> <phrase role="identifier">allocate</phrase><phrase role="special">();</phrase> 4729</programlisting> 4730 <variablelist> 4731 <title></title> 4732 <varlistentry> 4733 <term>Preconditions:</term> 4734 <listitem> 4735 <para> 4736 <code><phrase role="identifier">traits_type</phrase><phrase role="special">::</phrase><phrase 4737 role="identifier">minimum_size</phrase><phrase role="special">()</phrase> 4738 <phrase role="special"><=</phrase> <phrase role="identifier">size</phrase></code> 4739 and <code><phrase role="identifier">traits_type</phrase><phrase role="special">::</phrase><phrase 4740 role="identifier">is_unbounded</phrase><phrase role="special">()</phrase> 4741 <phrase role="special">||</phrase> <phrase role="special">(</phrase> 4742 <phrase role="identifier">traits_type</phrase><phrase role="special">::</phrase><phrase 4743 role="identifier">maximum_size</phrase><phrase role="special">()</phrase> 4744 <phrase role="special">>=</phrase> <phrase role="identifier">size</phrase><phrase 4745 role="special">)</phrase></code>. 4746 </para> 4747 </listitem> 4748 </varlistentry> 4749 <varlistentry> 4750 <term>Effects:</term> 4751 <listitem> 4752 <para> 4753 Allocates memory of at least <code><phrase role="identifier">size</phrase></code> 4754 bytes and stores a pointer to the stack and its actual size in <code><phrase 4755 role="identifier">sctx</phrase></code>. Depending on the architecture 4756 (the stack grows downwards/upwards) the stored address is the highest/lowest 4757 address of the stack. 4758 </para> 4759 </listitem> 4760 </varlistentry> 4761 </variablelist> 4762 <para> 4763 <bridgehead renderas="sect4" id="segmented_deallocate_bridgehead"> 4764 <phrase id="segmented_deallocate"/> 4765 <link linkend="segmented_deallocate">Member 4766 function <code>deallocate</code>()</link> 4767</bridgehead> 4768 </para> 4769<programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">deallocate</phrase><phrase role="special">(</phrase> <phrase role="identifier">stack_context</phrase> <phrase role="special">&</phrase> <phrase role="identifier">sctx</phrase><phrase role="special">);</phrase> 4770</programlisting> 4771 <variablelist> 4772 <title></title> 4773 <varlistentry> 4774 <term>Preconditions:</term> 4775 <listitem> 4776 <para> 4777 <code><phrase role="identifier">sctx</phrase><phrase role="special">.</phrase><phrase 4778 role="identifier">sp</phrase></code> is valid, <code><phrase role="identifier">traits_type</phrase><phrase 4779 role="special">::</phrase><phrase role="identifier">minimum_size</phrase><phrase 4780 role="special">()</phrase> <phrase role="special"><=</phrase> <phrase 4781 role="identifier">sctx</phrase><phrase role="special">.</phrase><phrase 4782 role="identifier">size</phrase></code> and <code><phrase role="identifier">traits_type</phrase><phrase 4783 role="special">::</phrase><phrase role="identifier">is_unbounded</phrase><phrase 4784 role="special">()</phrase> <phrase role="special">||</phrase> <phrase 4785 role="special">(</phrase> <phrase role="identifier">traits_type</phrase><phrase 4786 role="special">::</phrase><phrase role="identifier">maximum_size</phrase><phrase 4787 role="special">()</phrase> <phrase role="special">>=</phrase> <phrase 4788 role="identifier">sctx</phrase><phrase role="special">.</phrase><phrase 4789 role="identifier">size</phrase><phrase role="special">)</phrase></code>. 4790 </para> 4791 </listitem> 4792 </varlistentry> 4793 <varlistentry> 4794 <term>Effects:</term> 4795 <listitem> 4796 <para> 4797 Deallocates the stack space. 4798 </para> 4799 </listitem> 4800 </varlistentry> 4801 </variablelist> 4802 <note> 4803 <para> 4804 If the library is compiled for segmented stacks, <link linkend="class_segmented_stack"><code>segmented_stack</code></link> is 4805 the only available stack allocator. 4806 </para> 4807 </note> 4808 <section id="fiber.stack.valgrind"> 4809 <title><link linkend="fiber.stack.valgrind">Support for valgrind</link></title> 4810 <para> 4811 Running programs that switch stacks under valgrind causes problems. Property 4812 (b2 command-line) <code><phrase role="identifier">valgrind</phrase><phrase 4813 role="special">=</phrase><phrase role="identifier">on</phrase></code> let 4814 valgrind treat the memory regions as stack space which suppresses the errors. 4815 </para> 4816 </section> 4817 </section> 4818 <section id="fiber.synchronization"> 4819 <title><anchor id="synchronization"/><link linkend="fiber.synchronization">Synchronization</link></title> 4820 <para> 4821 In general, <emphasis role="bold">Boost.Fiber</emphasis> synchronization objects 4822 can neither be moved nor copied. A synchronization object acts as a mutually-agreed 4823 rendezvous point between different fibers. If such an object were copied somewhere 4824 else, the new copy would have no consumers. If such an object were <emphasis>moved</emphasis> 4825 somewhere else, leaving the original instance in an unspecified state, existing 4826 consumers would behave strangely. 4827 </para> 4828 <para> 4829 The fiber synchronization objects provided by this library will, by default, 4830 safely synchronize fibers running on different threads. However, this level 4831 of synchronization can be removed (for performance) by building the library 4832 with <emphasis role="bold"><code><phrase role="identifier">BOOST_FIBERS_NO_ATOMICS</phrase></code></emphasis> 4833 defined. When the library is built with that macro, you must ensure that all 4834 the fibers referencing a particular synchronization object are running in the 4835 same thread. 4836 </para> 4837 <section id="fiber.synchronization.mutex_types"> 4838 <title><link linkend="fiber.synchronization.mutex_types">Mutex Types</link></title> 4839 <para> 4840 <bridgehead renderas="sect4" id="class_mutex_bridgehead"> 4841 <phrase id="class_mutex"/> 4842 <link linkend="class_mutex">Class <code>mutex</code></link> 4843</bridgehead> 4844 </para> 4845<programlisting><phrase role="preprocessor">#include</phrase> <phrase role="special"><</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">></phrase> 4846 4847<phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase> 4848<phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase> 4849 4850<phrase role="keyword">class</phrase> <phrase role="identifier">mutex</phrase> <phrase role="special">{</phrase> 4851<phrase role="keyword">public</phrase><phrase role="special">:</phrase> 4852 <phrase role="identifier">mutex</phrase><phrase role="special">();</phrase> 4853 <phrase role="special">~</phrase><phrase role="identifier">mutex</phrase><phrase role="special">();</phrase> 4854 4855 <phrase role="identifier">mutex</phrase><phrase role="special">(</phrase> <phrase role="identifier">mutex</phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="special">=</phrase> <phrase role="keyword">delete</phrase><phrase role="special">;</phrase> 4856 <phrase role="identifier">mutex</phrase> <phrase role="special">&</phrase> <phrase role="keyword">operator</phrase><phrase role="special">=(</phrase> <phrase role="identifier">mutex</phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="special">=</phrase> <phrase role="keyword">delete</phrase><phrase role="special">;</phrase> 4857 4858 <phrase role="keyword">void</phrase> <phrase role="identifier">lock</phrase><phrase role="special">();</phrase> 4859 <phrase role="keyword">bool</phrase> <phrase role="identifier">try_lock</phrase><phrase role="special">();</phrase> 4860 <phrase role="keyword">void</phrase> <phrase role="identifier">unlock</phrase><phrase role="special">();</phrase> 4861<phrase role="special">};</phrase> 4862 4863<phrase role="special">}}</phrase> 4864</programlisting> 4865 <para> 4866 <link linkend="class_mutex"><code>mutex</code></link> provides an exclusive-ownership mutex. At most one fiber 4867 can own the lock on a given instance of <link linkend="class_mutex"><code>mutex</code></link> at any time. Multiple 4868 concurrent calls to <code><phrase role="identifier">lock</phrase><phrase 4869 role="special">()</phrase></code>, <code><phrase role="identifier">try_lock</phrase><phrase 4870 role="special">()</phrase></code> and <code><phrase role="identifier">unlock</phrase><phrase 4871 role="special">()</phrase></code> shall be permitted. 4872 </para> 4873 <para> 4874 Any fiber blocked in <code><phrase role="identifier">lock</phrase><phrase 4875 role="special">()</phrase></code> is suspended until the owning fiber releases 4876 the lock by calling <code><phrase role="identifier">unlock</phrase><phrase 4877 role="special">()</phrase></code>. 4878 </para> 4879 <para> 4880 <bridgehead renderas="sect4" id="mutex_lock_bridgehead"> 4881 <phrase id="mutex_lock"/> 4882 <link linkend="mutex_lock">Member function <code>lock</code>()</link> 4883</bridgehead> 4884 </para> 4885<programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">lock</phrase><phrase role="special">();</phrase> 4886</programlisting> 4887 <variablelist> 4888 <title></title> 4889 <varlistentry> 4890 <term>Precondition:</term> 4891 <listitem> 4892 <para> 4893 The calling fiber doesn't own the mutex. 4894 </para> 4895 </listitem> 4896 </varlistentry> 4897 <varlistentry> 4898 <term>Effects:</term> 4899 <listitem> 4900 <para> 4901 The current fiber blocks until ownership can be obtained. 4902 </para> 4903 </listitem> 4904 </varlistentry> 4905 <varlistentry> 4906 <term>Throws:</term> 4907 <listitem> 4908 <para> 4909 <code><phrase role="identifier">lock_error</phrase></code> 4910 </para> 4911 </listitem> 4912 </varlistentry> 4913 <varlistentry> 4914 <term>Error Conditions:</term> 4915 <listitem> 4916 <para> 4917 <emphasis role="bold">resource_deadlock_would_occur</emphasis>: if 4918 <code><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase 4919 role="identifier">this_fiber</phrase><phrase role="special">::</phrase><phrase 4920 role="identifier">get_id</phrase><phrase role="special">()</phrase></code> 4921 already owns the mutex. 4922 </para> 4923 </listitem> 4924 </varlistentry> 4925 </variablelist> 4926 <para> 4927 <bridgehead renderas="sect4" id="mutex_try_lock_bridgehead"> 4928 <phrase id="mutex_try_lock"/> 4929 <link linkend="mutex_try_lock">Member function <code>try_lock</code>()</link> 4930</bridgehead> 4931 </para> 4932<programlisting><phrase role="keyword">bool</phrase> <phrase role="identifier">try_lock</phrase><phrase role="special">();</phrase> 4933</programlisting> 4934 <variablelist> 4935 <title></title> 4936 <varlistentry> 4937 <term>Precondition:</term> 4938 <listitem> 4939 <para> 4940 The calling fiber doesn't own the mutex. 4941 </para> 4942 </listitem> 4943 </varlistentry> 4944 <varlistentry> 4945 <term>Effects:</term> 4946 <listitem> 4947 <para> 4948 Attempt to obtain ownership for the current fiber without blocking. 4949 </para> 4950 </listitem> 4951 </varlistentry> 4952 <varlistentry> 4953 <term>Returns:</term> 4954 <listitem> 4955 <para> 4956 <code><phrase role="keyword">true</phrase></code> if ownership was 4957 obtained for the current fiber, <code><phrase role="keyword">false</phrase></code> 4958 otherwise. 4959 </para> 4960 </listitem> 4961 </varlistentry> 4962 <varlistentry> 4963 <term>Throws:</term> 4964 <listitem> 4965 <para> 4966 <code><phrase role="identifier">lock_error</phrase></code> 4967 </para> 4968 </listitem> 4969 </varlistentry> 4970 <varlistentry> 4971 <term>Error Conditions:</term> 4972 <listitem> 4973 <para> 4974 <emphasis role="bold">resource_deadlock_would_occur</emphasis>: if 4975 <code><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase 4976 role="identifier">this_fiber</phrase><phrase role="special">::</phrase><phrase 4977 role="identifier">get_id</phrase><phrase role="special">()</phrase></code> 4978 already owns the mutex. 4979 </para> 4980 </listitem> 4981 </varlistentry> 4982 </variablelist> 4983 <para> 4984 <bridgehead renderas="sect4" id="mutex_unlock_bridgehead"> 4985 <phrase id="mutex_unlock"/> 4986 <link linkend="mutex_unlock">Member function <code>unlock</code>()</link> 4987</bridgehead> 4988 </para> 4989<programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">unlock</phrase><phrase role="special">();</phrase> 4990</programlisting> 4991 <variablelist> 4992 <title></title> 4993 <varlistentry> 4994 <term>Precondition:</term> 4995 <listitem> 4996 <para> 4997 The current fiber owns <code><phrase role="special">*</phrase><phrase 4998 role="keyword">this</phrase></code>. 4999 </para> 5000 </listitem> 5001 </varlistentry> 5002 <varlistentry> 5003 <term>Effects:</term> 5004 <listitem> 5005 <para> 5006 Releases a lock on <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code> 5007 by the current fiber. 5008 </para> 5009 </listitem> 5010 </varlistentry> 5011 <varlistentry> 5012 <term>Throws:</term> 5013 <listitem> 5014 <para> 5015 <code><phrase role="identifier">lock_error</phrase></code> 5016 </para> 5017 </listitem> 5018 </varlistentry> 5019 <varlistentry> 5020 <term>Error Conditions:</term> 5021 <listitem> 5022 <para> 5023 <emphasis role="bold">operation_not_permitted</emphasis>: if <code><phrase 5024 role="identifier">boost</phrase><phrase role="special">::</phrase><phrase 5025 role="identifier">this_fiber</phrase><phrase role="special">::</phrase><phrase 5026 role="identifier">get_id</phrase><phrase role="special">()</phrase></code> 5027 does not own the mutex. 5028 </para> 5029 </listitem> 5030 </varlistentry> 5031 </variablelist> 5032 <para> 5033 <bridgehead renderas="sect4" id="class_timed_mutex_bridgehead"> 5034 <phrase id="class_timed_mutex"/> 5035 <link linkend="class_timed_mutex">Class <code>timed_mutex</code></link> 5036</bridgehead> 5037 </para> 5038<programlisting><phrase role="preprocessor">#include</phrase> <phrase role="special"><</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">></phrase> 5039 5040<phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase> 5041<phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase> 5042 5043<phrase role="keyword">class</phrase> <phrase role="identifier">timed_mutex</phrase> <phrase role="special">{</phrase> 5044<phrase role="keyword">public</phrase><phrase role="special">:</phrase> 5045 <phrase role="identifier">timed_mutex</phrase><phrase role="special">();</phrase> 5046 <phrase role="special">~</phrase><phrase role="identifier">timed_mutex</phrase><phrase role="special">();</phrase> 5047 5048 <phrase role="identifier">timed_mutex</phrase><phrase role="special">(</phrase> <phrase role="identifier">timed_mutex</phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="special">=</phrase> <phrase role="keyword">delete</phrase><phrase role="special">;</phrase> 5049 <phrase role="identifier">timed_mutex</phrase> <phrase role="special">&</phrase> <phrase role="keyword">operator</phrase><phrase role="special">=(</phrase> <phrase role="identifier">timed_mutex</phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="special">=</phrase> <phrase role="keyword">delete</phrase><phrase role="special">;</phrase> 5050 5051 <phrase role="keyword">void</phrase> <phrase role="identifier">lock</phrase><phrase role="special">();</phrase> 5052 <phrase role="keyword">bool</phrase> <phrase role="identifier">try_lock</phrase><phrase role="special">();</phrase> 5053 <phrase role="keyword">void</phrase> <phrase role="identifier">unlock</phrase><phrase role="special">();</phrase> 5054 5055 <phrase role="keyword">template</phrase><phrase role="special"><</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Clock</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Duration</phrase> <phrase role="special">></phrase> 5056 <phrase role="keyword">bool</phrase> <phrase role="identifier">try_lock_until</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">time_point</phrase><phrase role="special"><</phrase> <phrase role="identifier">Clock</phrase><phrase role="special">,</phrase> <phrase role="identifier">Duration</phrase> <phrase role="special">></phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">timeout_time</phrase><phrase role="special">);</phrase> 5057 <phrase role="keyword">template</phrase><phrase role="special"><</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Rep</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Period</phrase> <phrase role="special">></phrase> 5058 <phrase role="keyword">bool</phrase> <phrase role="identifier">try_lock_for</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">duration</phrase><phrase role="special"><</phrase> <phrase role="identifier">Rep</phrase><phrase role="special">,</phrase> <phrase role="identifier">Period</phrase> <phrase role="special">></phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">timeout_duration</phrase><phrase role="special">);</phrase> 5059<phrase role="special">};</phrase> 5060 5061<phrase role="special">}}</phrase> 5062</programlisting> 5063 <para> 5064 <link linkend="class_timed_mutex"><code>timed_mutex</code></link> provides an exclusive-ownership mutex. At most 5065 one fiber can own the lock on a given instance of <link linkend="class_timed_mutex"><code>timed_mutex</code></link> at 5066 any time. Multiple concurrent calls to <code><phrase role="identifier">lock</phrase><phrase 5067 role="special">()</phrase></code>, <code><phrase role="identifier">try_lock</phrase><phrase 5068 role="special">()</phrase></code>, <code><phrase role="identifier">try_lock_until</phrase><phrase 5069 role="special">()</phrase></code>, <code><phrase role="identifier">try_lock_for</phrase><phrase 5070 role="special">()</phrase></code> and <code><phrase role="identifier">unlock</phrase><phrase 5071 role="special">()</phrase></code> shall be permitted. 5072 </para> 5073 <para> 5074 <bridgehead renderas="sect4" id="timed_mutex_lock_bridgehead"> 5075 <phrase id="timed_mutex_lock"/> 5076 <link linkend="timed_mutex_lock">Member function 5077 <code>lock</code>()</link> 5078</bridgehead> 5079 </para> 5080<programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">lock</phrase><phrase role="special">();</phrase> 5081</programlisting> 5082 <variablelist> 5083 <title></title> 5084 <varlistentry> 5085 <term>Precondition:</term> 5086 <listitem> 5087 <para> 5088 The calling fiber doesn't own the mutex. 5089 </para> 5090 </listitem> 5091 </varlistentry> 5092 <varlistentry> 5093 <term>Effects:</term> 5094 <listitem> 5095 <para> 5096 The current fiber blocks until ownership can be obtained. 5097 </para> 5098 </listitem> 5099 </varlistentry> 5100 <varlistentry> 5101 <term>Throws:</term> 5102 <listitem> 5103 <para> 5104 <code><phrase role="identifier">lock_error</phrase></code> 5105 </para> 5106 </listitem> 5107 </varlistentry> 5108 <varlistentry> 5109 <term>Error Conditions:</term> 5110 <listitem> 5111 <para> 5112 <emphasis role="bold">resource_deadlock_would_occur</emphasis>: if 5113 <code><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase 5114 role="identifier">this_fiber</phrase><phrase role="special">::</phrase><phrase 5115 role="identifier">get_id</phrase><phrase role="special">()</phrase></code> 5116 already owns the mutex. 5117 </para> 5118 </listitem> 5119 </varlistentry> 5120 </variablelist> 5121 <para> 5122 <bridgehead renderas="sect4" id="timed_mutex_try_lock_bridgehead"> 5123 <phrase id="timed_mutex_try_lock"/> 5124 <link linkend="timed_mutex_try_lock">Member 5125 function <code>try_lock</code>()</link> 5126</bridgehead> 5127 </para> 5128<programlisting><phrase role="keyword">bool</phrase> <phrase role="identifier">try_lock</phrase><phrase role="special">();</phrase> 5129</programlisting> 5130 <variablelist> 5131 <title></title> 5132 <varlistentry> 5133 <term>Precondition:</term> 5134 <listitem> 5135 <para> 5136 The calling fiber doesn't own the mutex. 5137 </para> 5138 </listitem> 5139 </varlistentry> 5140 <varlistentry> 5141 <term>Effects:</term> 5142 <listitem> 5143 <para> 5144 Attempt to obtain ownership for the current fiber without blocking. 5145 </para> 5146 </listitem> 5147 </varlistentry> 5148 <varlistentry> 5149 <term>Returns:</term> 5150 <listitem> 5151 <para> 5152 <code><phrase role="keyword">true</phrase></code> if ownership was 5153 obtained for the current fiber, <code><phrase role="keyword">false</phrase></code> 5154 otherwise. 5155 </para> 5156 </listitem> 5157 </varlistentry> 5158 <varlistentry> 5159 <term>Throws:</term> 5160 <listitem> 5161 <para> 5162 <code><phrase role="identifier">lock_error</phrase></code> 5163 </para> 5164 </listitem> 5165 </varlistentry> 5166 <varlistentry> 5167 <term>Error Conditions:</term> 5168 <listitem> 5169 <para> 5170 <emphasis role="bold">resource_deadlock_would_occur</emphasis>: if 5171 <code><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase 5172 role="identifier">this_fiber</phrase><phrase role="special">::</phrase><phrase 5173 role="identifier">get_id</phrase><phrase role="special">()</phrase></code> 5174 already owns the mutex. 5175 </para> 5176 </listitem> 5177 </varlistentry> 5178 </variablelist> 5179 <para> 5180 <bridgehead renderas="sect4" id="timed_mutex_unlock_bridgehead"> 5181 <phrase id="timed_mutex_unlock"/> 5182 <link linkend="timed_mutex_unlock">Member function 5183 <code>unlock</code>()</link> 5184</bridgehead> 5185 </para> 5186<programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">unlock</phrase><phrase role="special">();</phrase> 5187</programlisting> 5188 <variablelist> 5189 <title></title> 5190 <varlistentry> 5191 <term>Precondition:</term> 5192 <listitem> 5193 <para> 5194 The current fiber owns <code><phrase role="special">*</phrase><phrase 5195 role="keyword">this</phrase></code>. 5196 </para> 5197 </listitem> 5198 </varlistentry> 5199 <varlistentry> 5200 <term>Effects:</term> 5201 <listitem> 5202 <para> 5203 Releases a lock on <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code> 5204 by the current fiber. 5205 </para> 5206 </listitem> 5207 </varlistentry> 5208 <varlistentry> 5209 <term>Throws:</term> 5210 <listitem> 5211 <para> 5212 <code><phrase role="identifier">lock_error</phrase></code> 5213 </para> 5214 </listitem> 5215 </varlistentry> 5216 <varlistentry> 5217 <term>Error Conditions:</term> 5218 <listitem> 5219 <para> 5220 <emphasis role="bold">operation_not_permitted</emphasis>: if <code><phrase 5221 role="identifier">boost</phrase><phrase role="special">::</phrase><phrase 5222 role="identifier">this_fiber</phrase><phrase role="special">::</phrase><phrase 5223 role="identifier">get_id</phrase><phrase role="special">()</phrase></code> 5224 does not own the mutex. 5225 </para> 5226 </listitem> 5227 </varlistentry> 5228 </variablelist> 5229 <para> 5230 <bridgehead renderas="sect4" id="timed_mutex_try_lock_until_bridgehead"> 5231 <phrase id="timed_mutex_try_lock_until"/> 5232 <link linkend="timed_mutex_try_lock_until">Templated 5233 member function <code>try_lock_until</code>()</link> 5234</bridgehead> 5235 </para> 5236<programlisting><phrase role="keyword">template</phrase><phrase role="special"><</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Clock</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Duration</phrase> <phrase role="special">></phrase> 5237<phrase role="keyword">bool</phrase> <phrase role="identifier">try_lock_until</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">time_point</phrase><phrase role="special"><</phrase> <phrase role="identifier">Clock</phrase><phrase role="special">,</phrase> <phrase role="identifier">Duration</phrase> <phrase role="special">></phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">timeout_time</phrase><phrase role="special">);</phrase> 5238</programlisting> 5239 <variablelist> 5240 <title></title> 5241 <varlistentry> 5242 <term>Precondition:</term> 5243 <listitem> 5244 <para> 5245 The calling fiber doesn't own the mutex. 5246 </para> 5247 </listitem> 5248 </varlistentry> 5249 <varlistentry> 5250 <term>Effects:</term> 5251 <listitem> 5252 <para> 5253 Attempt to obtain ownership for the current fiber. Blocks until ownership 5254 can be obtained, or the specified time is reached. If the specified 5255 time has already passed, behaves as <link linkend="timed_mutex_try_lock"><code>timed_mutex::try_lock()</code></link>. 5256 </para> 5257 </listitem> 5258 </varlistentry> 5259 <varlistentry> 5260 <term>Returns:</term> 5261 <listitem> 5262 <para> 5263 <code><phrase role="keyword">true</phrase></code> if ownership was 5264 obtained for the current fiber, <code><phrase role="keyword">false</phrase></code> 5265 otherwise. 5266 </para> 5267 </listitem> 5268 </varlistentry> 5269 <varlistentry> 5270 <term>Throws:</term> 5271 <listitem> 5272 <para> 5273 <code><phrase role="identifier">lock_error</phrase></code>, timeout-related 5274 exceptions. 5275 </para> 5276 </listitem> 5277 </varlistentry> 5278 <varlistentry> 5279 <term>Error Conditions:</term> 5280 <listitem> 5281 <para> 5282 <emphasis role="bold">resource_deadlock_would_occur</emphasis>: if 5283 <code><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase 5284 role="identifier">this_fiber</phrase><phrase role="special">::</phrase><phrase 5285 role="identifier">get_id</phrase><phrase role="special">()</phrase></code> 5286 already owns the mutex. 5287 </para> 5288 </listitem> 5289 </varlistentry> 5290 </variablelist> 5291 <para> 5292 <bridgehead renderas="sect4" id="timed_mutex_try_lock_for_bridgehead"> 5293 <phrase id="timed_mutex_try_lock_for"/> 5294 <link linkend="timed_mutex_try_lock_for">Templated 5295 member function <code>try_lock_for</code>()</link> 5296</bridgehead> 5297 </para> 5298<programlisting><phrase role="keyword">template</phrase><phrase role="special"><</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Rep</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Period</phrase> <phrase role="special">></phrase> 5299<phrase role="keyword">bool</phrase> <phrase role="identifier">try_lock_for</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">duration</phrase><phrase role="special"><</phrase> <phrase role="identifier">Rep</phrase><phrase role="special">,</phrase> <phrase role="identifier">Period</phrase> <phrase role="special">></phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">timeout_duration</phrase><phrase role="special">);</phrase> 5300</programlisting> 5301 <variablelist> 5302 <title></title> 5303 <varlistentry> 5304 <term>Precondition:</term> 5305 <listitem> 5306 <para> 5307 The calling fiber doesn't own the mutex. 5308 </para> 5309 </listitem> 5310 </varlistentry> 5311 <varlistentry> 5312 <term>Effects:</term> 5313 <listitem> 5314 <para> 5315 Attempt to obtain ownership for the current fiber. Blocks until ownership 5316 can be obtained, or the specified time is reached. If the specified 5317 time has already passed, behaves as <link linkend="timed_mutex_try_lock"><code>timed_mutex::try_lock()</code></link>. 5318 </para> 5319 </listitem> 5320 </varlistentry> 5321 <varlistentry> 5322 <term>Returns:</term> 5323 <listitem> 5324 <para> 5325 <code><phrase role="keyword">true</phrase></code> if ownership was 5326 obtained for the current fiber, <code><phrase role="keyword">false</phrase></code> 5327 otherwise. 5328 </para> 5329 </listitem> 5330 </varlistentry> 5331 <varlistentry> 5332 <term>Throws:</term> 5333 <listitem> 5334 <para> 5335 <code><phrase role="identifier">lock_error</phrase></code>, timeout-related 5336 exceptions. 5337 </para> 5338 </listitem> 5339 </varlistentry> 5340 <varlistentry> 5341 <term>Error Conditions:</term> 5342 <listitem> 5343 <para> 5344 <emphasis role="bold">resource_deadlock_would_occur</emphasis>: if 5345 <code><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase 5346 role="identifier">this_fiber</phrase><phrase role="special">::</phrase><phrase 5347 role="identifier">get_id</phrase><phrase role="special">()</phrase></code> 5348 already owns the mutex. 5349 </para> 5350 </listitem> 5351 </varlistentry> 5352 </variablelist> 5353 <para> 5354 <bridgehead renderas="sect4" id="class_recursive_mutex_bridgehead"> 5355 <phrase id="class_recursive_mutex"/> 5356 <link linkend="class_recursive_mutex">Class 5357 <code>recursive_mutex</code></link> 5358</bridgehead> 5359 </para> 5360<programlisting><phrase role="preprocessor">#include</phrase> <phrase role="special"><</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">></phrase> 5361 5362<phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase> 5363<phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase> 5364 5365<phrase role="keyword">class</phrase> <phrase role="identifier">recursive_mutex</phrase> <phrase role="special">{</phrase> 5366<phrase role="keyword">public</phrase><phrase role="special">:</phrase> 5367 <phrase role="identifier">recursive_mutex</phrase><phrase role="special">();</phrase> 5368 <phrase role="special">~</phrase><phrase role="identifier">recursive_mutex</phrase><phrase role="special">();</phrase> 5369 5370 <phrase role="identifier">recursive_mutex</phrase><phrase role="special">(</phrase> <phrase role="identifier">recursive_mutex</phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="special">=</phrase> <phrase role="keyword">delete</phrase><phrase role="special">;</phrase> 5371 <phrase role="identifier">recursive_mutex</phrase> <phrase role="special">&</phrase> <phrase role="keyword">operator</phrase><phrase role="special">=(</phrase> <phrase role="identifier">recursive_mutex</phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="special">=</phrase> <phrase role="keyword">delete</phrase><phrase role="special">;</phrase> 5372 5373 <phrase role="keyword">void</phrase> <phrase role="identifier">lock</phrase><phrase role="special">();</phrase> 5374 <phrase role="keyword">bool</phrase> <phrase role="identifier">try_lock</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 5375 <phrase role="keyword">void</phrase> <phrase role="identifier">unlock</phrase><phrase role="special">();</phrase> 5376<phrase role="special">};</phrase> 5377 5378<phrase role="special">}}</phrase> 5379</programlisting> 5380 <para> 5381 <link linkend="class_recursive_mutex"><code>recursive_mutex</code></link> provides an exclusive-ownership recursive 5382 mutex. At most one fiber can own the lock on a given instance of <link linkend="class_recursive_mutex"><code>recursive_mutex</code></link> at 5383 any time. Multiple concurrent calls to <code><phrase role="identifier">lock</phrase><phrase 5384 role="special">()</phrase></code>, <code><phrase role="identifier">try_lock</phrase><phrase 5385 role="special">()</phrase></code> and <code><phrase role="identifier">unlock</phrase><phrase 5386 role="special">()</phrase></code> shall be permitted. A fiber that already 5387 has exclusive ownership of a given <link linkend="class_recursive_mutex"><code>recursive_mutex</code></link> instance 5388 can call <code><phrase role="identifier">lock</phrase><phrase role="special">()</phrase></code> 5389 or <code><phrase role="identifier">try_lock</phrase><phrase role="special">()</phrase></code> 5390 to acquire an additional level of ownership of the mutex. <code><phrase role="identifier">unlock</phrase><phrase 5391 role="special">()</phrase></code> must be called once for each level of ownership 5392 acquired by a single fiber before ownership can be acquired by another fiber. 5393 </para> 5394 <para> 5395 <bridgehead renderas="sect4" id="recursive_mutex_lock_bridgehead"> 5396 <phrase id="recursive_mutex_lock"/> 5397 <link linkend="recursive_mutex_lock">Member 5398 function <code>lock</code>()</link> 5399</bridgehead> 5400 </para> 5401<programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">lock</phrase><phrase role="special">();</phrase> 5402</programlisting> 5403 <variablelist> 5404 <title></title> 5405 <varlistentry> 5406 <term>Effects:</term> 5407 <listitem> 5408 <para> 5409 The current fiber blocks until ownership can be obtained. 5410 </para> 5411 </listitem> 5412 </varlistentry> 5413 <varlistentry> 5414 <term>Throws:</term> 5415 <listitem> 5416 <para> 5417 Nothing 5418 </para> 5419 </listitem> 5420 </varlistentry> 5421 </variablelist> 5422 <para> 5423 <bridgehead renderas="sect4" id="recursive_mutex_try_lock_bridgehead"> 5424 <phrase id="recursive_mutex_try_lock"/> 5425 <link linkend="recursive_mutex_try_lock">Member 5426 function <code>try_lock</code>()</link> 5427</bridgehead> 5428 </para> 5429<programlisting><phrase role="keyword">bool</phrase> <phrase role="identifier">try_lock</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 5430</programlisting> 5431 <variablelist> 5432 <title></title> 5433 <varlistentry> 5434 <term>Effects:</term> 5435 <listitem> 5436 <para> 5437 Attempt to obtain ownership for the current fiber without blocking. 5438 </para> 5439 </listitem> 5440 </varlistentry> 5441 <varlistentry> 5442 <term>Returns:</term> 5443 <listitem> 5444 <para> 5445 <code><phrase role="keyword">true</phrase></code> if ownership was 5446 obtained for the current fiber, <code><phrase role="keyword">false</phrase></code> 5447 otherwise. 5448 </para> 5449 </listitem> 5450 </varlistentry> 5451 <varlistentry> 5452 <term>Throws:</term> 5453 <listitem> 5454 <para> 5455 Nothing. 5456 </para> 5457 </listitem> 5458 </varlistentry> 5459 </variablelist> 5460 <para> 5461 <bridgehead renderas="sect4" id="recursive_mutex_unlock_bridgehead"> 5462 <phrase id="recursive_mutex_unlock"/> 5463 <link linkend="recursive_mutex_unlock">Member 5464 function <code>unlock</code>()</link> 5465</bridgehead> 5466 </para> 5467<programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">unlock</phrase><phrase role="special">();</phrase> 5468</programlisting> 5469 <variablelist> 5470 <title></title> 5471 <varlistentry> 5472 <term>Effects:</term> 5473 <listitem> 5474 <para> 5475 Releases a lock on <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code> 5476 by the current fiber. 5477 </para> 5478 </listitem> 5479 </varlistentry> 5480 <varlistentry> 5481 <term>Throws:</term> 5482 <listitem> 5483 <para> 5484 <code><phrase role="identifier">lock_error</phrase></code> 5485 </para> 5486 </listitem> 5487 </varlistentry> 5488 <varlistentry> 5489 <term>Error Conditions:</term> 5490 <listitem> 5491 <para> 5492 <emphasis role="bold">operation_not_permitted</emphasis>: if <code><phrase 5493 role="identifier">boost</phrase><phrase role="special">::</phrase><phrase 5494 role="identifier">this_fiber</phrase><phrase role="special">::</phrase><phrase 5495 role="identifier">get_id</phrase><phrase role="special">()</phrase></code> 5496 does not own the mutex. 5497 </para> 5498 </listitem> 5499 </varlistentry> 5500 </variablelist> 5501 <para> 5502 <bridgehead renderas="sect4" id="class_recursive_timed_mutex_bridgehead"> 5503 <phrase id="class_recursive_timed_mutex"/> 5504 <link linkend="class_recursive_timed_mutex">Class 5505 <code>recursive_timed_mutex</code></link> 5506</bridgehead> 5507 </para> 5508<programlisting><phrase role="preprocessor">#include</phrase> <phrase role="special"><</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">></phrase> 5509 5510<phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase> 5511<phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase> 5512 5513<phrase role="keyword">class</phrase> <phrase role="identifier">recursive_timed_mutex</phrase> <phrase role="special">{</phrase> 5514<phrase role="keyword">public</phrase><phrase role="special">:</phrase> 5515 <phrase role="identifier">recursive_timed_mutex</phrase><phrase role="special">();</phrase> 5516 <phrase role="special">~</phrase><phrase role="identifier">recursive_timed_mutex</phrase><phrase role="special">();</phrase> 5517 5518 <phrase role="identifier">recursive_timed_mutex</phrase><phrase role="special">(</phrase> <phrase role="identifier">recursive_timed_mutex</phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="special">=</phrase> <phrase role="keyword">delete</phrase><phrase role="special">;</phrase> 5519 <phrase role="identifier">recursive_timed_mutex</phrase> <phrase role="special">&</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">&</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="special">=</phrase> <phrase role="keyword">delete</phrase><phrase role="special">;</phrase> 5520 5521 <phrase role="keyword">void</phrase> <phrase role="identifier">lock</phrase><phrase role="special">();</phrase> 5522 <phrase role="keyword">bool</phrase> <phrase role="identifier">try_lock</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 5523 <phrase role="keyword">void</phrase> <phrase role="identifier">unlock</phrase><phrase role="special">();</phrase> 5524 5525 <phrase role="keyword">template</phrase><phrase role="special"><</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Clock</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Duration</phrase> <phrase role="special">></phrase> 5526 <phrase role="keyword">bool</phrase> <phrase role="identifier">try_lock_until</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">time_point</phrase><phrase role="special"><</phrase> <phrase role="identifier">Clock</phrase><phrase role="special">,</phrase> <phrase role="identifier">Duration</phrase> <phrase role="special">></phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">timeout_time</phrase><phrase role="special">);</phrase> 5527 <phrase role="keyword">template</phrase><phrase role="special"><</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Rep</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Period</phrase> <phrase role="special">></phrase> 5528 <phrase role="keyword">bool</phrase> <phrase role="identifier">try_lock_for</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">duration</phrase><phrase role="special"><</phrase> <phrase role="identifier">Rep</phrase><phrase role="special">,</phrase> <phrase role="identifier">Period</phrase> <phrase role="special">></phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">timeout_duration</phrase><phrase role="special">);</phrase> 5529<phrase role="special">};</phrase> 5530 5531<phrase role="special">}}</phrase> 5532</programlisting> 5533 <para> 5534 <link linkend="class_recursive_timed_mutex"><code>recursive_timed_mutex</code></link> provides an exclusive-ownership 5535 recursive mutex. At most one fiber can own the lock on a given instance of 5536 <link linkend="class_recursive_timed_mutex"><code>recursive_timed_mutex</code></link> at any time. Multiple concurrent 5537 calls to <code><phrase role="identifier">lock</phrase><phrase role="special">()</phrase></code>, 5538 <code><phrase role="identifier">try_lock</phrase><phrase role="special">()</phrase></code>, 5539 <code><phrase role="identifier">try_lock_for</phrase><phrase role="special">()</phrase></code>, 5540 <code><phrase role="identifier">try_lock_until</phrase><phrase role="special">()</phrase></code> 5541 and <code><phrase role="identifier">unlock</phrase><phrase role="special">()</phrase></code> 5542 shall be permitted. A fiber that already has exclusive ownership of a given 5543 <link linkend="class_recursive_timed_mutex"><code>recursive_timed_mutex</code></link> instance can call <code><phrase 5544 role="identifier">lock</phrase><phrase role="special">()</phrase></code>, 5545 <code><phrase role="identifier">try_lock</phrase><phrase role="special">()</phrase></code>, 5546 <code><phrase role="identifier">try_lock_for</phrase><phrase role="special">()</phrase></code> 5547 or <code><phrase role="identifier">try_lock_until</phrase><phrase role="special">()</phrase></code> 5548 to acquire an additional level of ownership of the mutex. <code><phrase role="identifier">unlock</phrase><phrase 5549 role="special">()</phrase></code> must be called once for each level of ownership 5550 acquired by a single fiber before ownership can be acquired by another fiber. 5551 </para> 5552 <para> 5553 <bridgehead renderas="sect4" id="recursive_timed_mutex_lock_bridgehead"> 5554 <phrase id="recursive_timed_mutex_lock"/> 5555 <link linkend="recursive_timed_mutex_lock">Member 5556 function <code>lock</code>()</link> 5557</bridgehead> 5558 </para> 5559<programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">lock</phrase><phrase role="special">();</phrase> 5560</programlisting> 5561 <variablelist> 5562 <title></title> 5563 <varlistentry> 5564 <term>Effects:</term> 5565 <listitem> 5566 <para> 5567 The current fiber blocks until ownership can be obtained. 5568 </para> 5569 </listitem> 5570 </varlistentry> 5571 <varlistentry> 5572 <term>Throws:</term> 5573 <listitem> 5574 <para> 5575 Nothing 5576 </para> 5577 </listitem> 5578 </varlistentry> 5579 </variablelist> 5580 <para> 5581 <bridgehead renderas="sect4" id="recursive_timed_mutex_try_lock_bridgehead"> 5582 <phrase id="recursive_timed_mutex_try_lock"/> 5583 <link linkend="recursive_timed_mutex_try_lock">Member 5584 function <code>try_lock</code>()</link> 5585</bridgehead> 5586 </para> 5587<programlisting><phrase role="keyword">bool</phrase> <phrase role="identifier">try_lock</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 5588</programlisting> 5589 <variablelist> 5590 <title></title> 5591 <varlistentry> 5592 <term>Effects:</term> 5593 <listitem> 5594 <para> 5595 Attempt to obtain ownership for the current fiber without blocking. 5596 </para> 5597 </listitem> 5598 </varlistentry> 5599 <varlistentry> 5600 <term>Returns:</term> 5601 <listitem> 5602 <para> 5603 <code><phrase role="keyword">true</phrase></code> if ownership was 5604 obtained for the current fiber, <code><phrase role="keyword">false</phrase></code> 5605 otherwise. 5606 </para> 5607 </listitem> 5608 </varlistentry> 5609 <varlistentry> 5610 <term>Throws:</term> 5611 <listitem> 5612 <para> 5613 Nothing. 5614 </para> 5615 </listitem> 5616 </varlistentry> 5617 </variablelist> 5618 <para> 5619 <bridgehead renderas="sect4" id="recursive_timed_mutex_unlock_bridgehead"> 5620 <phrase id="recursive_timed_mutex_unlock"/> 5621 <link linkend="recursive_timed_mutex_unlock">Member 5622 function <code>unlock</code>()</link> 5623</bridgehead> 5624 </para> 5625<programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">unlock</phrase><phrase role="special">();</phrase> 5626</programlisting> 5627 <variablelist> 5628 <title></title> 5629 <varlistentry> 5630 <term>Effects:</term> 5631 <listitem> 5632 <para> 5633 Releases a lock on <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code> 5634 by the current fiber. 5635 </para> 5636 </listitem> 5637 </varlistentry> 5638 <varlistentry> 5639 <term>Throws:</term> 5640 <listitem> 5641 <para> 5642 <code><phrase role="identifier">lock_error</phrase></code> 5643 </para> 5644 </listitem> 5645 </varlistentry> 5646 <varlistentry> 5647 <term>Error Conditions:</term> 5648 <listitem> 5649 <para> 5650 <emphasis role="bold">operation_not_permitted</emphasis>: if <code><phrase 5651 role="identifier">boost</phrase><phrase role="special">::</phrase><phrase 5652 role="identifier">this_fiber</phrase><phrase role="special">::</phrase><phrase 5653 role="identifier">get_id</phrase><phrase role="special">()</phrase></code> 5654 does not own the mutex. 5655 </para> 5656 </listitem> 5657 </varlistentry> 5658 </variablelist> 5659 <para> 5660 <bridgehead renderas="sect4" id="recursive_timed_mutex_try_lock_until_bridgehead"> 5661 <phrase id="recursive_timed_mutex_try_lock_until"/> 5662 <link linkend="recursive_timed_mutex_try_lock_until">Templated 5663 member function <code>try_lock_until</code>()</link> 5664</bridgehead> 5665 </para> 5666<programlisting><phrase role="keyword">template</phrase><phrase role="special"><</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Clock</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Duration</phrase> <phrase role="special">></phrase> 5667<phrase role="keyword">bool</phrase> <phrase role="identifier">try_lock_until</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">time_point</phrase><phrase role="special"><</phrase> <phrase role="identifier">Clock</phrase><phrase role="special">,</phrase> <phrase role="identifier">Duration</phrase> <phrase role="special">></phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">timeout_time</phrase><phrase role="special">);</phrase> 5668</programlisting> 5669 <variablelist> 5670 <title></title> 5671 <varlistentry> 5672 <term>Effects:</term> 5673 <listitem> 5674 <para> 5675 Attempt to obtain ownership for the current fiber. Blocks until ownership 5676 can be obtained, or the specified time is reached. If the specified 5677 time has already passed, behaves as <link linkend="recursive_timed_mutex_try_lock"><code>recursive_timed_mutex::try_lock()</code></link>. 5678 </para> 5679 </listitem> 5680 </varlistentry> 5681 <varlistentry> 5682 <term>Returns:</term> 5683 <listitem> 5684 <para> 5685 <code><phrase role="keyword">true</phrase></code> if ownership was 5686 obtained for the current fiber, <code><phrase role="keyword">false</phrase></code> 5687 otherwise. 5688 </para> 5689 </listitem> 5690 </varlistentry> 5691 <varlistentry> 5692 <term>Throws:</term> 5693 <listitem> 5694 <para> 5695 Timeout-related exceptions. 5696 </para> 5697 </listitem> 5698 </varlistentry> 5699 </variablelist> 5700 <para> 5701 <bridgehead renderas="sect4" id="recursive_timed_mutex_try_lock_for_bridgehead"> 5702 <phrase id="recursive_timed_mutex_try_lock_for"/> 5703 <link linkend="recursive_timed_mutex_try_lock_for">Templated 5704 member function <code>try_lock_for</code>()</link> 5705</bridgehead> 5706 </para> 5707<programlisting><phrase role="keyword">template</phrase><phrase role="special"><</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Rep</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Period</phrase> <phrase role="special">></phrase> 5708<phrase role="keyword">bool</phrase> <phrase role="identifier">try_lock_for</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">duration</phrase><phrase role="special"><</phrase> <phrase role="identifier">Rep</phrase><phrase role="special">,</phrase> <phrase role="identifier">Period</phrase> <phrase role="special">></phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">timeout_duration</phrase><phrase role="special">);</phrase> 5709</programlisting> 5710 <variablelist> 5711 <title></title> 5712 <varlistentry> 5713 <term>Effects:</term> 5714 <listitem> 5715 <para> 5716 Attempt to obtain ownership for the current fiber. Blocks until ownership 5717 can be obtained, or the specified time is reached. If the specified 5718 time has already passed, behaves as <link linkend="recursive_timed_mutex_try_lock"><code>recursive_timed_mutex::try_lock()</code></link>. 5719 </para> 5720 </listitem> 5721 </varlistentry> 5722 <varlistentry> 5723 <term>Returns:</term> 5724 <listitem> 5725 <para> 5726 <code><phrase role="keyword">true</phrase></code> if ownership was 5727 obtained for the current fiber, <code><phrase role="keyword">false</phrase></code> 5728 otherwise. 5729 </para> 5730 </listitem> 5731 </varlistentry> 5732 <varlistentry> 5733 <term>Throws:</term> 5734 <listitem> 5735 <para> 5736 Timeout-related exceptions. 5737 </para> 5738 </listitem> 5739 </varlistentry> 5740 </variablelist> 5741 </section> 5742 <section id="fiber.synchronization.conditions"> 5743 <title><link linkend="fiber.synchronization.conditions">Condition Variables</link></title> 5744 <bridgehead renderas="sect4" id="fiber.synchronization.conditions.h0"> 5745 <phrase id="fiber.synchronization.conditions.synopsis"/><link linkend="fiber.synchronization.conditions.synopsis">Synopsis</link> 5746 </bridgehead> 5747<programlisting><phrase role="keyword">enum</phrase> <phrase role="keyword">class</phrase> <phrase role="identifier">cv_status</phrase><phrase role="special">;</phrase> <phrase role="special">{</phrase> 5748 <phrase role="identifier">no_timeout</phrase><phrase role="special">,</phrase> 5749 <phrase role="identifier">timeout</phrase> 5750<phrase role="special">};</phrase> 5751 5752<phrase role="keyword">class</phrase> <phrase role="identifier">condition_variable</phrase><phrase role="special">;</phrase> 5753<phrase role="keyword">class</phrase> <phrase role="identifier">condition_variable_any</phrase><phrase role="special">;</phrase> 5754</programlisting> 5755 <para> 5756 The class <link linkend="class_condition_variable"><code>condition_variable</code></link> provides a mechanism 5757 for a fiber to wait for notification from another fiber. When the fiber awakens 5758 from the wait, then it checks to see if the appropriate condition is now 5759 true, and continues if so. If the condition is not true, then the fiber calls 5760 <code><phrase role="identifier">wait</phrase></code> again to resume waiting. 5761 In the simplest case, this condition is just a boolean variable: 5762 </para> 5763<programlisting><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">condition_variable</phrase> <phrase role="identifier">cond</phrase><phrase role="special">;</phrase> 5764<phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">mutex</phrase> <phrase role="identifier">mtx</phrase><phrase role="special">;</phrase> 5765<phrase role="keyword">bool</phrase> <phrase role="identifier">data_ready</phrase> <phrase role="special">=</phrase> <phrase role="keyword">false</phrase><phrase role="special">;</phrase> 5766 5767<phrase role="keyword">void</phrase> <phrase role="identifier">process_data</phrase><phrase role="special">();</phrase> 5768 5769<phrase role="keyword">void</phrase> <phrase role="identifier">wait_for_data_to_process</phrase><phrase role="special">()</phrase> <phrase role="special">{</phrase> 5770 <phrase role="special">{</phrase> 5771 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">unique_lock</phrase><phrase role="special"><</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">></phrase> <phrase role="identifier">lk</phrase><phrase role="special">(</phrase> <phrase role="identifier">mtx</phrase><phrase role="special">);</phrase> 5772 <phrase role="keyword">while</phrase> <phrase role="special">(</phrase> <phrase role="special">!</phrase> <phrase role="identifier">data_ready</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase> 5773 <phrase role="identifier">cond</phrase><phrase role="special">.</phrase><phrase role="identifier">wait</phrase><phrase role="special">(</phrase> <phrase role="identifier">lk</phrase><phrase role="special">);</phrase> 5774 <phrase role="special">}</phrase> 5775 <phrase role="special">}</phrase> <phrase role="comment">// release lk</phrase> 5776 <phrase role="identifier">process_data</phrase><phrase role="special">();</phrase> 5777<phrase role="special">}</phrase> 5778</programlisting> 5779 <para> 5780 Notice that the <code><phrase role="identifier">lk</phrase></code> is passed 5781 to <link linkend="condition_variable_wait"><code>condition_variable::wait()</code></link>: <code><phrase role="identifier">wait</phrase><phrase 5782 role="special">()</phrase></code> will atomically add the fiber to the set 5783 of fibers waiting on the condition variable, and unlock the <link linkend="class_mutex"><code>mutex</code></link>. 5784 When the fiber is awakened, the <code><phrase role="identifier">mutex</phrase></code> 5785 will be locked again before the call to <code><phrase role="identifier">wait</phrase><phrase 5786 role="special">()</phrase></code> returns. This allows other fibers to acquire 5787 the <code><phrase role="identifier">mutex</phrase></code> in order to update 5788 the shared data, and ensures that the data associated with the condition 5789 is correctly synchronized. 5790 </para> 5791 <para> 5792 <code><phrase role="identifier">wait_for_data_to_process</phrase><phrase 5793 role="special">()</phrase></code> could equivalently be written: 5794 </para> 5795<programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">wait_for_data_to_process</phrase><phrase role="special">()</phrase> <phrase role="special">{</phrase> 5796 <phrase role="special">{</phrase> 5797 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">unique_lock</phrase><phrase role="special"><</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">></phrase> <phrase role="identifier">lk</phrase><phrase role="special">(</phrase> <phrase role="identifier">mtx</phrase><phrase role="special">);</phrase> 5798 <phrase role="comment">// make condition_variable::wait() perform the loop</phrase> 5799 <phrase role="identifier">cond</phrase><phrase role="special">.</phrase><phrase role="identifier">wait</phrase><phrase role="special">(</phrase> <phrase role="identifier">lk</phrase><phrase role="special">,</phrase> <phrase role="special">[](){</phrase> <phrase role="keyword">return</phrase> <phrase role="identifier">data_ready</phrase><phrase role="special">;</phrase> <phrase role="special">});</phrase> 5800 <phrase role="special">}</phrase> <phrase role="comment">// release lk</phrase> 5801 <phrase role="identifier">process_data</phrase><phrase role="special">();</phrase> 5802<phrase role="special">}</phrase> 5803</programlisting> 5804 <para> 5805 In the meantime, another fiber sets <code><phrase role="identifier">data_ready</phrase></code> 5806 to <code><phrase role="keyword">true</phrase></code>, and then calls either 5807 <link linkend="condition_variable_notify_one"><code>condition_variable::notify_one()</code></link> or <link linkend="condition_variable_notify_all"><code>condition_variable::notify_all()</code></link> on 5808 the <link linkend="class_condition_variable"><code>condition_variable</code></link> <code><phrase role="identifier">cond</phrase></code> 5809 to wake one waiting fiber or all the waiting fibers respectively. 5810 </para> 5811<programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">retrieve_data</phrase><phrase role="special">();</phrase> 5812<phrase role="keyword">void</phrase> <phrase role="identifier">prepare_data</phrase><phrase role="special">();</phrase> 5813 5814<phrase role="keyword">void</phrase> <phrase role="identifier">prepare_data_for_processing</phrase><phrase role="special">()</phrase> <phrase role="special">{</phrase> 5815 <phrase role="identifier">retrieve_data</phrase><phrase role="special">();</phrase> 5816 <phrase role="identifier">prepare_data</phrase><phrase role="special">();</phrase> 5817 <phrase role="special">{</phrase> 5818 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">unique_lock</phrase><phrase role="special"><</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">></phrase> <phrase role="identifier">lk</phrase><phrase role="special">(</phrase> <phrase role="identifier">mtx</phrase><phrase role="special">);</phrase> 5819 <phrase role="identifier">data_ready</phrase> <phrase role="special">=</phrase> <phrase role="keyword">true</phrase><phrase role="special">;</phrase> 5820 <phrase role="special">}</phrase> 5821 <phrase role="identifier">cond</phrase><phrase role="special">.</phrase><phrase role="identifier">notify_one</phrase><phrase role="special">();</phrase> 5822<phrase role="special">}</phrase> 5823</programlisting> 5824 <para> 5825 Note that the same <link linkend="class_mutex"><code>mutex</code></link> is locked before the shared data is updated, 5826 but that the <code><phrase role="identifier">mutex</phrase></code> does not 5827 have to be locked across the call to <link linkend="condition_variable_notify_one"><code>condition_variable::notify_one()</code></link>. 5828 </para> 5829 <para> 5830 Locking is important because the synchronization objects provided by <emphasis 5831 role="bold">Boost.Fiber</emphasis> can be used to synchronize fibers running 5832 on different threads. 5833 </para> 5834 <para> 5835 <emphasis role="bold">Boost.Fiber</emphasis> provides both <link linkend="class_condition_variable"><code>condition_variable</code></link> and 5836 <link linkend="class_condition_variable_any"><code>condition_variable_any</code></link>. <code><phrase role="identifier">boost</phrase><phrase 5837 role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase 5838 role="special">::</phrase><phrase role="identifier">condition_variable</phrase></code> 5839 can only wait on <ulink url="http://en.cppreference.com/w/cpp/thread/unique_lock"><code><phrase 5840 role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">unique_lock</phrase></code></ulink><code><phrase 5841 role="special"><</phrase> <phrase role="identifier">boost</phrase><phrase 5842 role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase 5843 role="special">::</phrase></code><link linkend="class_mutex"><code>mutex</code></link><code> <phrase role="special">></phrase></code> 5844 while <code><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase 5845 role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase 5846 role="identifier">condition_variable_any</phrase></code> can wait on user-defined 5847 lock types. 5848 </para> 5849 <anchor id="condition_variable_spurious_wakeups"/> 5850 <bridgehead renderas="sect4" id="fiber.synchronization.conditions.h1"> 5851 <phrase id="fiber.synchronization.conditions.no_spurious_wakeups"/><link 5852 linkend="fiber.synchronization.conditions.no_spurious_wakeups">No Spurious 5853 Wakeups</link> 5854 </bridgehead> 5855 <para> 5856 Neither <link linkend="class_condition_variable"><code>condition_variable</code></link> nor <link linkend="class_condition_variable_any"><code>condition_variable_any</code></link> are 5857 subject to spurious wakeup: <link linkend="condition_variable_wait"><code>condition_variable::wait()</code></link> can 5858 only wake up when <link linkend="condition_variable_notify_one"><code>condition_variable::notify_one()</code></link> or 5859 <link linkend="condition_variable_notify_all"><code>condition_variable::notify_all()</code></link> is called. Even 5860 so, it is prudent to use one of the <code><phrase role="identifier">wait</phrase><phrase 5861 role="special">(</phrase> <phrase role="identifier">lock</phrase><phrase 5862 role="special">,</phrase> <phrase role="identifier">predicate</phrase> <phrase 5863 role="special">)</phrase></code> overloads. 5864 </para> 5865 <para> 5866 Consider a set of consumer fibers processing items from a <ulink url="http://en.cppreference.com/w/cpp/container/queue"><code><phrase 5867 role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">queue</phrase></code></ulink>. 5868 The queue is continually populated by a set of producer fibers. 5869 </para> 5870 <para> 5871 The consumer fibers might reasonably wait on a <code><phrase role="identifier">condition_variable</phrase></code> 5872 as long as the queue remains <ulink url="http://en.cppreference.com/w/cpp/container/queue/empty"><code><phrase 5873 role="identifier">empty</phrase><phrase role="special">()</phrase></code></ulink>. 5874 </para> 5875 <para> 5876 Because producer fibers might <ulink url="http://en.cppreference.com/w/cpp/container/queue/push"><code><phrase 5877 role="identifier">push</phrase><phrase role="special">()</phrase></code></ulink> 5878 items to the queue in bursts, they call <link linkend="condition_variable_notify_all"><code>condition_variable::notify_all()</code></link> rather 5879 than <link linkend="condition_variable_notify_one"><code>condition_variable::notify_one()</code></link>. 5880 </para> 5881 <para> 5882 But a given consumer fiber might well wake up from <link linkend="condition_variable_wait"><code>condition_variable::wait()</code></link> and 5883 find the queue <code><phrase role="identifier">empty</phrase><phrase role="special">()</phrase></code>, 5884 because other consumer fibers might already have processed all pending items. 5885 </para> 5886 <para> 5887 (See also <link linkend="spurious_wakeup">spurious wakeup</link>.) 5888 </para> 5889 <anchor id="class_cv_status"/> 5890 <bridgehead renderas="sect4" id="fiber.synchronization.conditions.h2"> 5891 <phrase id="fiber.synchronization.conditions.enumeration__code__phrase_role__identifier__cv_status__phrase___code_"/><link 5892 linkend="fiber.synchronization.conditions.enumeration__code__phrase_role__identifier__cv_status__phrase___code_">Enumeration 5893 <code><phrase role="identifier">cv_status</phrase></code></link> 5894 </bridgehead> 5895 <para> 5896 A timed wait operation might return because of timeout or not. 5897 </para> 5898<programlisting><phrase role="keyword">enum</phrase> <phrase role="keyword">class</phrase> <phrase role="identifier">cv_status</phrase> <phrase role="special">{</phrase> 5899 <phrase role="identifier">no_timeout</phrase><phrase role="special">,</phrase> 5900 <phrase role="identifier">timeout</phrase> 5901<phrase role="special">};</phrase> 5902</programlisting> 5903 <bridgehead renderas="sect4" id="fiber.synchronization.conditions.h3"> 5904 <phrase id="fiber.synchronization.conditions._code__phrase_role__identifier__no_timeout__phrase___code_"/><link 5905 linkend="fiber.synchronization.conditions._code__phrase_role__identifier__no_timeout__phrase___code_"><code><phrase 5906 role="identifier">no_timeout</phrase></code></link> 5907 </bridgehead> 5908 <variablelist> 5909 <title></title> 5910 <varlistentry> 5911 <term>Effects:</term> 5912 <listitem> 5913 <para> 5914 The condition variable was awakened with <code><phrase role="identifier">notify_one</phrase></code> 5915 or <code><phrase role="identifier">notify_all</phrase></code>. 5916 </para> 5917 </listitem> 5918 </varlistentry> 5919 </variablelist> 5920 <bridgehead renderas="sect4" id="fiber.synchronization.conditions.h4"> 5921 <phrase id="fiber.synchronization.conditions._code__phrase_role__identifier__timeout__phrase___code_"/><link 5922 linkend="fiber.synchronization.conditions._code__phrase_role__identifier__timeout__phrase___code_"><code><phrase 5923 role="identifier">timeout</phrase></code></link> 5924 </bridgehead> 5925 <variablelist> 5926 <title></title> 5927 <varlistentry> 5928 <term>Effects:</term> 5929 <listitem> 5930 <para> 5931 The condition variable was awakened by timeout. 5932 </para> 5933 </listitem> 5934 </varlistentry> 5935 </variablelist> 5936 <para> 5937 <bridgehead renderas="sect4" id="class_condition_variable_any_bridgehead"> 5938 <phrase id="class_condition_variable_any"/> 5939 <link linkend="class_condition_variable_any">Class 5940 <code>condition_variable_any</code></link> 5941</bridgehead> 5942 </para> 5943<programlisting><phrase role="preprocessor">#include</phrase> <phrase role="special"><</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">></phrase> 5944 5945<phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase> 5946<phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase> 5947 5948<phrase role="keyword">class</phrase> condition_variable_any <phrase role="special">{</phrase> 5949<phrase role="keyword">public</phrase><phrase role="special">:</phrase> 5950 condition_variable_any<phrase role="special">();</phrase> 5951 <phrase role="special">~</phrase>condition_variable_any<phrase role="special">();</phrase> 5952 5953 condition_variable_any<phrase role="special">(</phrase> condition_variable_any <phrase role="keyword">const</phrase><phrase role="special">&)</phrase> <phrase role="special">=</phrase> <phrase role="keyword">delete</phrase><phrase role="special">;</phrase> 5954 condition_variable_any <phrase role="special">&</phrase> <phrase role="keyword">operator</phrase><phrase role="special">=(</phrase> condition_variable_any <phrase role="keyword">const</phrase><phrase role="special">&)</phrase> <phrase role="special">=</phrase> <phrase role="keyword">delete</phrase><phrase role="special">;</phrase> 5955 5956 <phrase role="keyword">void</phrase> <phrase role="identifier">notify_one</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 5957 <phrase role="keyword">void</phrase> <phrase role="identifier">notify_all</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 5958 5959 template< typename LockType > 5960 void <phrase role="identifier">wait</phrase><phrase role="special">(</phrase> LockType <phrase role="special">&);</phrase> 5961 5962 <phrase role="keyword">template</phrase><phrase role="special"><</phrase> typename LockType, typename <phrase role="identifier">Pred</phrase> <phrase role="special">></phrase> 5963 <phrase role="keyword">void</phrase> <phrase role="identifier">wait</phrase><phrase role="special">(</phrase> LockType <phrase role="special">&,</phrase> <phrase role="identifier">Pred</phrase><phrase role="special">);</phrase> 5964 5965 <phrase role="keyword">template</phrase><phrase role="special"><</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> 5966 <phrase role="identifier">cv_status</phrase> <phrase role="identifier">wait_until</phrase><phrase role="special">(</phrase> LockType <phrase role="special">&,</phrase> 5967 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">time_point</phrase><phrase role="special"><</phrase> <phrase role="identifier">Clock</phrase><phrase role="special">,</phrase> <phrase role="identifier">Duration</phrase> <phrase role="special">></phrase> <phrase role="keyword">const</phrase><phrase role="special">&);</phrase> 5968 5969 <phrase role="keyword">template</phrase><phrase role="special"><</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">></phrase> 5970 <phrase role="keyword">bool</phrase> <phrase role="identifier">wait_until</phrase><phrase role="special">(</phrase> LockType <phrase role="special">&,</phrase> 5971 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">time_point</phrase><phrase role="special"><</phrase> <phrase role="identifier">Clock</phrase><phrase role="special">,</phrase> <phrase role="identifier">Duration</phrase> <phrase role="special">></phrase> <phrase role="keyword">const</phrase><phrase role="special">&,</phrase> 5972 <phrase role="identifier">Pred</phrase><phrase role="special">);</phrase> 5973 5974 <phrase role="keyword">template</phrase><phrase role="special"><</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> 5975 <phrase role="identifier">cv_status</phrase> <phrase role="identifier">wait_for</phrase><phrase role="special">(</phrase> LockType <phrase role="special">&,</phrase> 5976 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">duration</phrase><phrase role="special"><</phrase> <phrase role="identifier">Rep</phrase><phrase role="special">,</phrase> <phrase role="identifier">Period</phrase> <phrase role="special">></phrase> <phrase role="keyword">const</phrase><phrase role="special">&);</phrase> 5977 5978 <phrase role="keyword">template</phrase><phrase role="special"><</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">></phrase> 5979 <phrase role="keyword">bool</phrase> <phrase role="identifier">wait_for</phrase><phrase role="special">(</phrase> LockType <phrase role="special">&,</phrase> 5980 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">duration</phrase><phrase role="special"><</phrase> <phrase role="identifier">Rep</phrase><phrase role="special">,</phrase> <phrase role="identifier">Period</phrase> <phrase role="special">></phrase> <phrase role="keyword">const</phrase><phrase role="special">&,</phrase> 5981 <phrase role="identifier">Pred</phrase><phrase role="special">);</phrase> 5982<phrase role="special">};</phrase> 5983 5984<phrase role="special">}}</phrase> 5985</programlisting> 5986 <bridgehead renderas="sect4" id="fiber.synchronization.conditions.h5"> 5987 <phrase id="fiber.synchronization.conditions.constructor"/><link linkend="fiber.synchronization.conditions.constructor">Constructor</link> 5988 </bridgehead> 5989<programlisting>condition_variable_any<phrase role="special">()</phrase> 5990</programlisting> 5991 <variablelist> 5992 <title></title> 5993 <varlistentry> 5994 <term>Effects:</term> 5995 <listitem> 5996 <para> 5997 Creates the object. 5998 </para> 5999 </listitem> 6000 </varlistentry> 6001 <varlistentry> 6002 <term>Throws:</term> 6003 <listitem> 6004 <para> 6005 Nothing. 6006 </para> 6007 </listitem> 6008 </varlistentry> 6009 </variablelist> 6010 <bridgehead renderas="sect4" id="fiber.synchronization.conditions.h6"> 6011 <phrase id="fiber.synchronization.conditions.destructor"/><link linkend="fiber.synchronization.conditions.destructor">Destructor</link> 6012 </bridgehead> 6013<programlisting><phrase role="special">~</phrase>condition_variable_any<phrase role="special">()</phrase> 6014</programlisting> 6015 <variablelist> 6016 <title></title> 6017 <varlistentry> 6018 <term>Precondition:</term> 6019 <listitem> 6020 <para> 6021 All fibers waiting on <code><phrase role="special">*</phrase><phrase 6022 role="keyword">this</phrase></code> have been notified by a call to 6023 <code><phrase role="identifier">notify_one</phrase></code> or <code><phrase 6024 role="identifier">notify_all</phrase></code> (though the respective 6025 calls to <code><phrase role="identifier">wait</phrase></code>, <code><phrase 6026 role="identifier">wait_for</phrase></code> or <code><phrase role="identifier">wait_until</phrase></code> 6027 need not have returned). 6028 </para> 6029 </listitem> 6030 </varlistentry> 6031 <varlistentry> 6032 <term>Effects:</term> 6033 <listitem> 6034 <para> 6035 Destroys the object. 6036 </para> 6037 </listitem> 6038 </varlistentry> 6039 </variablelist> 6040 <para> 6041 <bridgehead renderas="sect4" id="condition_variable_any_notify_one_bridgehead"> 6042 <phrase id="condition_variable_any_notify_one"/> 6043 <link linkend="condition_variable_any_notify_one">Member 6044 function <code>notify_one</code>()</link> 6045</bridgehead> 6046 </para> 6047<programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">notify_one</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 6048</programlisting> 6049 <variablelist> 6050 <title></title> 6051 <varlistentry> 6052 <term>Effects:</term> 6053 <listitem> 6054 <para> 6055 If any fibers are currently <link linkend="blocking"><emphasis>blocked</emphasis></link> 6056 waiting on <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code> 6057 in a call to <code><phrase role="identifier">wait</phrase></code>, 6058 <code><phrase role="identifier">wait_for</phrase></code> or <code><phrase 6059 role="identifier">wait_until</phrase></code>, unblocks one of those 6060 fibers. 6061 </para> 6062 </listitem> 6063 </varlistentry> 6064 <varlistentry> 6065 <term>Throws:</term> 6066 <listitem> 6067 <para> 6068 Nothing. 6069 </para> 6070 </listitem> 6071 </varlistentry> 6072 <varlistentry> 6073 <term>Note:</term> 6074 <listitem> 6075 <para> 6076 It is arbitrary which waiting fiber is resumed. 6077 </para> 6078 </listitem> 6079 </varlistentry> 6080 </variablelist> 6081 <para> 6082 <bridgehead renderas="sect4" id="condition_variable_any_notify_all_bridgehead"> 6083 <phrase id="condition_variable_any_notify_all"/> 6084 <link linkend="condition_variable_any_notify_all">Member 6085 function <code>notify_all</code>()</link> 6086</bridgehead> 6087 </para> 6088<programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">notify_all</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 6089</programlisting> 6090 <variablelist> 6091 <title></title> 6092 <varlistentry> 6093 <term>Effects:</term> 6094 <listitem> 6095 <para> 6096 If any fibers are currently <link linkend="blocking"><emphasis>blocked</emphasis></link> 6097 waiting on <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code> 6098 in a call to <code><phrase role="identifier">wait</phrase></code>, 6099 <code><phrase role="identifier">wait_for</phrase></code> or <code><phrase 6100 role="identifier">wait_until</phrase></code>, unblocks all of those 6101 fibers. 6102 </para> 6103 </listitem> 6104 </varlistentry> 6105 <varlistentry> 6106 <term>Throws:</term> 6107 <listitem> 6108 <para> 6109 Nothing. 6110 </para> 6111 </listitem> 6112 </varlistentry> 6113 <varlistentry> 6114 <term>Note:</term> 6115 <listitem> 6116 <para> 6117 This is why a waiting fiber must <emphasis>also</emphasis> check for 6118 the desired program state using a mechanism external to the <code>condition_variable_any</code>, 6119 and retry the wait until that state is reached. A fiber waiting on 6120 a <code>condition_variable_any</code> might well wake up a number of times before 6121 the desired state is reached. 6122 </para> 6123 </listitem> 6124 </varlistentry> 6125 </variablelist> 6126 <para> 6127 <bridgehead renderas="sect4" id="condition_variable_any_wait_bridgehead"> 6128 <phrase id="condition_variable_any_wait"/> 6129 <link linkend="condition_variable_any_wait">Templated 6130 member function <code>wait</code>()</link> 6131</bridgehead> 6132 </para> 6133<programlisting>template< typename LockType > 6134 void <phrase role="identifier">wait</phrase><phrase role="special">(</phrase> LockType <phrase role="special">&</phrase> <phrase role="identifier">lk</phrase><phrase role="special">);</phrase> 6135 6136<phrase role="keyword">template</phrase><phrase role="special"><</phrase> typename LockType, typename <phrase role="identifier">Pred</phrase> <phrase role="special">></phrase> 6137<phrase role="keyword">void</phrase> <phrase role="identifier">wait</phrase><phrase role="special">(</phrase> LockType <phrase role="special">&</phrase> <phrase role="identifier">lk</phrase><phrase role="special">,</phrase> <phrase role="identifier">Pred</phrase> <phrase role="identifier">pred</phrase><phrase role="special">);</phrase> 6138</programlisting> 6139 <variablelist> 6140 <title></title> 6141 <varlistentry> 6142 <term>Precondition:</term> 6143 <listitem> 6144 <para> 6145 <code><phrase role="identifier">lk</phrase></code> is locked by the 6146 current fiber, and either no other fiber is currently waiting on <code><phrase 6147 role="special">*</phrase><phrase role="keyword">this</phrase></code>, 6148 or the execution of the <ulink url="http://en.cppreference.com/w/cpp/thread/unique_lock/mutex"><code><phrase 6149 role="identifier">mutex</phrase><phrase role="special">()</phrase></code></ulink> 6150 member function on the <code><phrase role="identifier">lk</phrase></code> 6151 objects supplied in the calls to <code><phrase role="identifier">wait</phrase></code> 6152 in all the fibers currently waiting on <code><phrase role="special">*</phrase><phrase 6153 role="keyword">this</phrase></code> would return the same value as 6154 <code><phrase role="identifier">lk</phrase><phrase role="special">-></phrase><phrase 6155 role="identifier">mutex</phrase><phrase role="special">()</phrase></code> 6156 for this call to <code><phrase role="identifier">wait</phrase></code>. 6157 </para> 6158 </listitem> 6159 </varlistentry> 6160 <varlistentry> 6161 <term>Effects:</term> 6162 <listitem> 6163 <para> 6164 Atomically call <code><phrase role="identifier">lk</phrase><phrase 6165 role="special">.</phrase><phrase role="identifier">unlock</phrase><phrase 6166 role="special">()</phrase></code> and blocks the current fiber. The 6167 fiber will unblock when notified by a call to <code><phrase role="keyword">this</phrase><phrase 6168 role="special">-></phrase><phrase role="identifier">notify_one</phrase><phrase 6169 role="special">()</phrase></code> or <code><phrase role="keyword">this</phrase><phrase 6170 role="special">-></phrase><phrase role="identifier">notify_all</phrase><phrase 6171 role="special">()</phrase></code>. When the fiber is unblocked (for 6172 whatever reason), the lock is reacquired by invoking <code><phrase 6173 role="identifier">lk</phrase><phrase role="special">.</phrase><phrase 6174 role="identifier">lock</phrase><phrase role="special">()</phrase></code> 6175 before the call to <code><phrase role="identifier">wait</phrase></code> 6176 returns. The lock is also reacquired by invoking <code><phrase role="identifier">lk</phrase><phrase 6177 role="special">.</phrase><phrase role="identifier">lock</phrase><phrase 6178 role="special">()</phrase></code> if the function exits with an exception. 6179 The member function accepting <code><phrase role="identifier">pred</phrase></code> 6180 is shorthand for: 6181<programlisting><phrase role="keyword">while</phrase> <phrase role="special">(</phrase> <phrase role="special">!</phrase> <phrase role="identifier">pred</phrase><phrase role="special">()</phrase> <phrase role="special">)</phrase> <phrase role="special">{</phrase> 6182 <phrase role="identifier">wait</phrase><phrase role="special">(</phrase> <phrase role="identifier">lk</phrase><phrase role="special">);</phrase> 6183<phrase role="special">}</phrase> 6184</programlisting> 6185 </para> 6186 </listitem> 6187 </varlistentry> 6188 <varlistentry> 6189 <term>Postcondition:</term> 6190 <listitem> 6191 <para> 6192 <code><phrase role="identifier">lk</phrase></code> is locked by the 6193 current fiber. 6194 </para> 6195 </listitem> 6196 </varlistentry> 6197 <varlistentry> 6198 <term>Throws:</term> 6199 <listitem> 6200 <para> 6201 <code><phrase role="identifier">fiber_error</phrase></code> if an error 6202 occurs. 6203 </para> 6204 </listitem> 6205 </varlistentry> 6206 <varlistentry> 6207 <term>Note:</term> 6208 <listitem> 6209 <para> 6210 The Precondition is a bit dense. It merely states that all the fibers 6211 concurrently calling <code><phrase role="identifier">wait</phrase></code> 6212 on <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code> 6213 must wait on <code><phrase role="identifier">lk</phrase></code> objects 6214 governing the <emphasis>same</emphasis> <link linkend="class_mutex"><code>mutex</code></link>. Three distinct 6215 objects are involved in any <code>condition_variable_any::wait()</code> call: the 6216 <code>condition_variable_any</code> itself, the <code><phrase role="identifier">mutex</phrase></code> 6217 coordinating access between fibers and a local lock object (e.g. <ulink 6218 url="http://en.cppreference.com/w/cpp/thread/unique_lock"><code><phrase 6219 role="identifier">std</phrase><phrase role="special">::</phrase><phrase 6220 role="identifier">unique_lock</phrase></code></ulink>). In general, 6221 you can partition the lifespan of a given <code>condition_variable_any</code> instance 6222 into periods with one or more fibers waiting on it, separated by periods 6223 when no fibers are waiting on it. When more than one fiber is waiting 6224 on that <code>condition_variable_any</code>, all must pass lock objects referencing 6225 the <emphasis>same</emphasis> <code><phrase role="identifier">mutex</phrase></code> 6226 instance. 6227 </para> 6228 </listitem> 6229 </varlistentry> 6230 </variablelist> 6231 <para> 6232 <bridgehead renderas="sect4" id="condition_variable_any_wait_until_bridgehead"> 6233 <phrase id="condition_variable_any_wait_until"/> 6234 <link linkend="condition_variable_any_wait_until">Templated 6235 member function <code>wait_until</code>()</link> 6236</bridgehead> 6237 </para> 6238<programlisting><phrase role="keyword">template</phrase><phrase role="special"><</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> 6239<phrase role="identifier">cv_status</phrase> <phrase role="identifier">wait_until</phrase><phrase role="special">(</phrase> LockType <phrase role="special">&</phrase> <phrase role="identifier">lk</phrase><phrase role="special">,</phrase> 6240 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">time_point</phrase><phrase role="special"><</phrase> <phrase role="identifier">Clock</phrase><phrase role="special">,</phrase> <phrase role="identifier">Duration</phrase> <phrase role="special">></phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">abs_time</phrase><phrase role="special">);</phrase> 6241 6242<phrase role="keyword">template</phrase><phrase role="special"><</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">></phrase> 6243<phrase role="keyword">bool</phrase> <phrase role="identifier">wait_until</phrase><phrase role="special">(</phrase> LockType <phrase role="special">&</phrase> <phrase role="identifier">lk</phrase><phrase role="special">,</phrase> 6244 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">time_point</phrase><phrase role="special"><</phrase> <phrase role="identifier">Clock</phrase><phrase role="special">,</phrase> <phrase role="identifier">Duration</phrase> <phrase role="special">></phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">abs_time</phrase><phrase role="special">,</phrase> 6245 <phrase role="identifier">Pred</phrase> <phrase role="identifier">pred</phrase><phrase role="special">);</phrase> 6246</programlisting> 6247 <variablelist> 6248 <title></title> 6249 <varlistentry> 6250 <term>Precondition:</term> 6251 <listitem> 6252 <para> 6253 <code><phrase role="identifier">lk</phrase></code> is locked by the 6254 current fiber, and either no other fiber is currently waiting on <code><phrase 6255 role="special">*</phrase><phrase role="keyword">this</phrase></code>, 6256 or the execution of the <code><phrase role="identifier">mutex</phrase><phrase 6257 role="special">()</phrase></code> member function on the <code><phrase 6258 role="identifier">lk</phrase></code> objects supplied in the calls 6259 to <code><phrase role="identifier">wait</phrase></code>, <code><phrase 6260 role="identifier">wait_for</phrase></code> or <code><phrase role="identifier">wait_until</phrase></code> 6261 in all the fibers currently waiting on <code><phrase role="special">*</phrase><phrase 6262 role="keyword">this</phrase></code> would return the same value as 6263 <code><phrase role="identifier">lk</phrase><phrase role="special">.</phrase><phrase 6264 role="identifier">mutex</phrase><phrase role="special">()</phrase></code> 6265 for this call to <code><phrase role="identifier">wait_until</phrase></code>. 6266 </para> 6267 </listitem> 6268 </varlistentry> 6269 <varlistentry> 6270 <term>Effects:</term> 6271 <listitem> 6272 <para> 6273 Atomically call <code><phrase role="identifier">lk</phrase><phrase 6274 role="special">.</phrase><phrase role="identifier">unlock</phrase><phrase 6275 role="special">()</phrase></code> and blocks the current fiber. The 6276 fiber will unblock when notified by a call to <code><phrase role="keyword">this</phrase><phrase 6277 role="special">-></phrase><phrase role="identifier">notify_one</phrase><phrase 6278 role="special">()</phrase></code> or <code><phrase role="keyword">this</phrase><phrase 6279 role="special">-></phrase><phrase role="identifier">notify_all</phrase><phrase 6280 role="special">()</phrase></code>, when the system time would be equal 6281 to or later than the specified <code><phrase role="identifier">abs_time</phrase></code>. 6282 When the fiber is unblocked (for whatever reason), the lock is reacquired 6283 by invoking <code><phrase role="identifier">lk</phrase><phrase role="special">.</phrase><phrase 6284 role="identifier">lock</phrase><phrase role="special">()</phrase></code> 6285 before the call to <code><phrase role="identifier">wait_until</phrase></code> 6286 returns. The lock is also reacquired by invoking <code><phrase role="identifier">lk</phrase><phrase 6287 role="special">.</phrase><phrase role="identifier">lock</phrase><phrase 6288 role="special">()</phrase></code> if the function exits with an exception. 6289 The member function accepting <code><phrase role="identifier">pred</phrase></code> 6290 is shorthand for: 6291<programlisting><phrase role="keyword">while</phrase> <phrase role="special">(</phrase> <phrase role="special">!</phrase> <phrase role="identifier">pred</phrase><phrase role="special">()</phrase> <phrase role="special">)</phrase> <phrase role="special">{</phrase> 6292 <phrase role="keyword">if</phrase> <phrase role="special">(</phrase> <phrase role="identifier">cv_status</phrase><phrase role="special">::</phrase><phrase role="identifier">timeout</phrase> <phrase role="special">==</phrase> <phrase role="identifier">wait_until</phrase><phrase role="special">(</phrase> <phrase role="identifier">lk</phrase><phrase role="special">,</phrase> <phrase role="identifier">abs_time</phrase><phrase role="special">)</phrase> <phrase role="special">)</phrase> 6293 <phrase role="keyword">return</phrase> <phrase role="identifier">pred</phrase><phrase role="special">();</phrase> 6294<phrase role="special">}</phrase> 6295<phrase role="keyword">return</phrase> <phrase role="keyword">true</phrase><phrase role="special">;</phrase> 6296</programlisting> 6297 That is, even if <code><phrase role="identifier">wait_until</phrase><phrase 6298 role="special">()</phrase></code> times out, it can still return <code><phrase 6299 role="keyword">true</phrase></code> if <code><phrase role="identifier">pred</phrase><phrase 6300 role="special">()</phrase></code> returns <code><phrase role="keyword">true</phrase></code> 6301 at that time. 6302 </para> 6303 </listitem> 6304 </varlistentry> 6305 <varlistentry> 6306 <term>Postcondition:</term> 6307 <listitem> 6308 <para> 6309 <code><phrase role="identifier">lk</phrase></code> is locked by the 6310 current fiber. 6311 </para> 6312 </listitem> 6313 </varlistentry> 6314 <varlistentry> 6315 <term>Throws:</term> 6316 <listitem> 6317 <para> 6318 <code><phrase role="identifier">fiber_error</phrase></code> if an error 6319 occurs or timeout-related exceptions. 6320 </para> 6321 </listitem> 6322 </varlistentry> 6323 <varlistentry> 6324 <term>Returns:</term> 6325 <listitem> 6326 <para> 6327 The overload without <code><phrase role="identifier">pred</phrase></code> 6328 returns <code><phrase role="identifier">cv_status</phrase><phrase role="special">::</phrase><phrase 6329 role="identifier">no_timeout</phrase></code> if awakened by <code><phrase 6330 role="identifier">notify_one</phrase><phrase role="special">()</phrase></code> 6331 or <code><phrase role="identifier">notify_all</phrase><phrase role="special">()</phrase></code>, 6332 or <code><phrase role="identifier">cv_status</phrase><phrase role="special">::</phrase><phrase 6333 role="identifier">timeout</phrase></code> if awakened because the system 6334 time is past <code><phrase role="identifier">abs_time</phrase></code>. 6335 </para> 6336 </listitem> 6337 </varlistentry> 6338 <varlistentry> 6339 <term>Returns:</term> 6340 <listitem> 6341 <para> 6342 The overload accepting <code><phrase role="identifier">pred</phrase></code> 6343 returns <code><phrase role="keyword">false</phrase></code> if the call 6344 is returning because the time specified by <code><phrase role="identifier">abs_time</phrase></code> 6345 was reached and the predicate returns <code><phrase role="keyword">false</phrase></code>, 6346 <code><phrase role="keyword">true</phrase></code> otherwise. 6347 </para> 6348 </listitem> 6349 </varlistentry> 6350 <varlistentry> 6351 <term>Note:</term> 6352 <listitem> 6353 <para> 6354 See <emphasis role="bold">Note</emphasis> for <link linkend="condition_variable_any_wait"><code>condition_variable_any::wait()</code></link>. 6355 </para> 6356 </listitem> 6357 </varlistentry> 6358 </variablelist> 6359 <para> 6360 <bridgehead renderas="sect4" id="condition_variable_any_wait_for_bridgehead"> 6361 <phrase id="condition_variable_any_wait_for"/> 6362 <link linkend="condition_variable_any_wait_for">Templated 6363 member function <code>wait_for</code>()</link> 6364</bridgehead> 6365 </para> 6366<programlisting><phrase role="keyword">template</phrase><phrase role="special"><</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> 6367<phrase role="identifier">cv_status</phrase> <phrase role="identifier">wait_for</phrase><phrase role="special">(</phrase> LockType <phrase role="special">&</phrase> <phrase role="identifier">lk</phrase><phrase role="special">,</phrase> 6368 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">duration</phrase><phrase role="special"><</phrase> <phrase role="identifier">Rep</phrase><phrase role="special">,</phrase> <phrase role="identifier">Period</phrase> <phrase role="special">></phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">rel_time</phrase><phrase role="special">);</phrase> 6369 6370<phrase role="keyword">template</phrase><phrase role="special"><</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">></phrase> 6371<phrase role="keyword">bool</phrase> <phrase role="identifier">wait_for</phrase><phrase role="special">(</phrase> LockType <phrase role="special">&</phrase> <phrase role="identifier">lk</phrase><phrase role="special">,</phrase> 6372 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">duration</phrase><phrase role="special"><</phrase> <phrase role="identifier">Rep</phrase><phrase role="special">,</phrase> <phrase role="identifier">Period</phrase> <phrase role="special">></phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">rel_time</phrase><phrase role="special">,</phrase> 6373 <phrase role="identifier">Pred</phrase> <phrase role="identifier">pred</phrase><phrase role="special">);</phrase> 6374</programlisting> 6375 <variablelist> 6376 <title></title> 6377 <varlistentry> 6378 <term>Precondition:</term> 6379 <listitem> 6380 <para> 6381 <code><phrase role="identifier">lk</phrase></code> is locked by the 6382 current fiber, and either no other fiber is currently waiting on <code><phrase 6383 role="special">*</phrase><phrase role="keyword">this</phrase></code>, 6384 or the execution of the <code><phrase role="identifier">mutex</phrase><phrase 6385 role="special">()</phrase></code> member function on the <code><phrase 6386 role="identifier">lk</phrase></code> objects supplied in the calls 6387 to <code><phrase role="identifier">wait</phrase></code>, <code><phrase 6388 role="identifier">wait_for</phrase></code> or <code><phrase role="identifier">wait_until</phrase></code> 6389 in all the fibers currently waiting on <code><phrase role="special">*</phrase><phrase 6390 role="keyword">this</phrase></code> would return the same value as 6391 <code><phrase role="identifier">lk</phrase><phrase role="special">.</phrase><phrase 6392 role="identifier">mutex</phrase><phrase role="special">()</phrase></code> 6393 for this call to <code><phrase role="identifier">wait_for</phrase></code>. 6394 </para> 6395 </listitem> 6396 </varlistentry> 6397 <varlistentry> 6398 <term>Effects:</term> 6399 <listitem> 6400 <para> 6401 Atomically call <code><phrase role="identifier">lk</phrase><phrase 6402 role="special">.</phrase><phrase role="identifier">unlock</phrase><phrase 6403 role="special">()</phrase></code> and blocks the current fiber. The 6404 fiber will unblock when notified by a call to <code><phrase role="keyword">this</phrase><phrase 6405 role="special">-></phrase><phrase role="identifier">notify_one</phrase><phrase 6406 role="special">()</phrase></code> or <code><phrase role="keyword">this</phrase><phrase 6407 role="special">-></phrase><phrase role="identifier">notify_all</phrase><phrase 6408 role="special">()</phrase></code>, when a time interval equal to or 6409 greater than the specified <code><phrase role="identifier">rel_time</phrase></code> 6410 has elapsed. When the fiber is unblocked (for whatever reason), the 6411 lock is reacquired by invoking <code><phrase role="identifier">lk</phrase><phrase 6412 role="special">.</phrase><phrase role="identifier">lock</phrase><phrase 6413 role="special">()</phrase></code> before the call to <code><phrase 6414 role="identifier">wait</phrase></code> returns. The lock is also reacquired 6415 by invoking <code><phrase role="identifier">lk</phrase><phrase role="special">.</phrase><phrase 6416 role="identifier">lock</phrase><phrase role="special">()</phrase></code> 6417 if the function exits with an exception. The <code><phrase role="identifier">wait_for</phrase><phrase 6418 role="special">()</phrase></code> member function accepting <code><phrase 6419 role="identifier">pred</phrase></code> is shorthand for: 6420<programlisting><phrase role="keyword">while</phrase> <phrase role="special">(</phrase> <phrase role="special">!</phrase> <phrase role="identifier">pred</phrase><phrase role="special">()</phrase> <phrase role="special">)</phrase> <phrase role="special">{</phrase> 6421 <phrase role="keyword">if</phrase> <phrase role="special">(</phrase> <phrase role="identifier">cv_status</phrase><phrase role="special">::</phrase><phrase role="identifier">timeout</phrase> <phrase role="special">==</phrase> <phrase role="identifier">wait_for</phrase><phrase role="special">(</phrase> <phrase role="identifier">lk</phrase><phrase role="special">,</phrase> <phrase role="identifier">rel_time</phrase><phrase role="special">)</phrase> <phrase role="special">)</phrase> <phrase role="special">{</phrase> 6422 <phrase role="keyword">return</phrase> <phrase role="identifier">pred</phrase><phrase role="special">();</phrase> 6423 <phrase role="special">}</phrase> 6424<phrase role="special">}</phrase> 6425<phrase role="keyword">return</phrase> <phrase role="keyword">true</phrase><phrase role="special">;</phrase> 6426</programlisting> 6427 (except of course that <code><phrase role="identifier">rel_time</phrase></code> 6428 is adjusted for each iteration). The point is that, even if <code><phrase 6429 role="identifier">wait_for</phrase><phrase role="special">()</phrase></code> 6430 times out, it can still return <code><phrase role="keyword">true</phrase></code> 6431 if <code><phrase role="identifier">pred</phrase><phrase role="special">()</phrase></code> 6432 returns <code><phrase role="keyword">true</phrase></code> at that time. 6433 </para> 6434 </listitem> 6435 </varlistentry> 6436 <varlistentry> 6437 <term>Postcondition:</term> 6438 <listitem> 6439 <para> 6440 <code><phrase role="identifier">lk</phrase></code> is locked by the 6441 current fiber. 6442 </para> 6443 </listitem> 6444 </varlistentry> 6445 <varlistentry> 6446 <term>Throws:</term> 6447 <listitem> 6448 <para> 6449 <code><phrase role="identifier">fiber_error</phrase></code> if an error 6450 occurs or timeout-related exceptions. 6451 </para> 6452 </listitem> 6453 </varlistentry> 6454 <varlistentry> 6455 <term>Returns:</term> 6456 <listitem> 6457 <para> 6458 The overload without <code><phrase role="identifier">pred</phrase></code> 6459 returns <code><phrase role="identifier">cv_status</phrase><phrase role="special">::</phrase><phrase 6460 role="identifier">no_timeout</phrase></code> if awakened by <code><phrase 6461 role="identifier">notify_one</phrase><phrase role="special">()</phrase></code> 6462 or <code><phrase role="identifier">notify_all</phrase><phrase role="special">()</phrase></code>, 6463 or <code><phrase role="identifier">cv_status</phrase><phrase role="special">::</phrase><phrase 6464 role="identifier">timeout</phrase></code> if awakened because at least 6465 <code><phrase role="identifier">rel_time</phrase></code> has elapsed. 6466 </para> 6467 </listitem> 6468 </varlistentry> 6469 <varlistentry> 6470 <term>Returns:</term> 6471 <listitem> 6472 <para> 6473 The overload accepting <code><phrase role="identifier">pred</phrase></code> 6474 returns <code><phrase role="keyword">false</phrase></code> if the call 6475 is returning because at least <code><phrase role="identifier">rel_time</phrase></code> 6476 has elapsed and the predicate returns <code><phrase role="keyword">false</phrase></code>, 6477 <code><phrase role="keyword">true</phrase></code> otherwise. 6478 </para> 6479 </listitem> 6480 </varlistentry> 6481 <varlistentry> 6482 <term>Note:</term> 6483 <listitem> 6484 <para> 6485 See <emphasis role="bold">Note</emphasis> for <link linkend="condition_variable_any_wait"><code>condition_variable_any::wait()</code></link>. 6486 </para> 6487 </listitem> 6488 </varlistentry> 6489 </variablelist> 6490 <para> 6491 <bridgehead renderas="sect4" id="class_condition_variable_bridgehead"> 6492 <phrase id="class_condition_variable"/> 6493 <link linkend="class_condition_variable">Class 6494 <code>condition_variable</code></link> 6495</bridgehead> 6496 </para> 6497<programlisting><phrase role="preprocessor">#include</phrase> <phrase role="special"><</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">></phrase> 6498 6499<phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase> 6500<phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase> 6501 6502<phrase role="keyword">class</phrase> condition_variable <phrase role="special">{</phrase> 6503<phrase role="keyword">public</phrase><phrase role="special">:</phrase> 6504 condition_variable<phrase role="special">();</phrase> 6505 <phrase role="special">~</phrase>condition_variable<phrase role="special">();</phrase> 6506 6507 condition_variable<phrase role="special">(</phrase> condition_variable <phrase role="keyword">const</phrase><phrase role="special">&)</phrase> <phrase role="special">=</phrase> <phrase role="keyword">delete</phrase><phrase role="special">;</phrase> 6508 condition_variable <phrase role="special">&</phrase> <phrase role="keyword">operator</phrase><phrase role="special">=(</phrase> condition_variable <phrase role="keyword">const</phrase><phrase role="special">&)</phrase> <phrase role="special">=</phrase> <phrase role="keyword">delete</phrase><phrase role="special">;</phrase> 6509 6510 <phrase role="keyword">void</phrase> <phrase role="identifier">notify_one</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 6511 <phrase role="keyword">void</phrase> <phrase role="identifier">notify_all</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 6512 6513 void <phrase role="identifier">wait</phrase><phrase role="special">(</phrase> std::unique_lock< mutex > <phrase role="special">&);</phrase> 6514 6515 <phrase role="keyword">template</phrase><phrase role="special"><</phrase> typename <phrase role="identifier">Pred</phrase> <phrase role="special">></phrase> 6516 <phrase role="keyword">void</phrase> <phrase role="identifier">wait</phrase><phrase role="special">(</phrase> std::unique_lock< mutex > <phrase role="special">&,</phrase> <phrase role="identifier">Pred</phrase><phrase role="special">);</phrase> 6517 6518 <phrase role="keyword">template</phrase><phrase role="special"><</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> 6519 <phrase role="identifier">cv_status</phrase> <phrase role="identifier">wait_until</phrase><phrase role="special">(</phrase> std::unique_lock< mutex > <phrase role="special">&,</phrase> 6520 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">time_point</phrase><phrase role="special"><</phrase> <phrase role="identifier">Clock</phrase><phrase role="special">,</phrase> <phrase role="identifier">Duration</phrase> <phrase role="special">></phrase> <phrase role="keyword">const</phrase><phrase role="special">&);</phrase> 6521 6522 <phrase role="keyword">template</phrase><phrase role="special"><</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">></phrase> 6523 <phrase role="keyword">bool</phrase> <phrase role="identifier">wait_until</phrase><phrase role="special">(</phrase> std::unique_lock< mutex > <phrase role="special">&,</phrase> 6524 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">time_point</phrase><phrase role="special"><</phrase> <phrase role="identifier">Clock</phrase><phrase role="special">,</phrase> <phrase role="identifier">Duration</phrase> <phrase role="special">></phrase> <phrase role="keyword">const</phrase><phrase role="special">&,</phrase> 6525 <phrase role="identifier">Pred</phrase><phrase role="special">);</phrase> 6526 6527 <phrase role="keyword">template</phrase><phrase role="special"><</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> 6528 <phrase role="identifier">cv_status</phrase> <phrase role="identifier">wait_for</phrase><phrase role="special">(</phrase> std::unique_lock< mutex > <phrase role="special">&,</phrase> 6529 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">duration</phrase><phrase role="special"><</phrase> <phrase role="identifier">Rep</phrase><phrase role="special">,</phrase> <phrase role="identifier">Period</phrase> <phrase role="special">></phrase> <phrase role="keyword">const</phrase><phrase role="special">&);</phrase> 6530 6531 <phrase role="keyword">template</phrase><phrase role="special"><</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">></phrase> 6532 <phrase role="keyword">bool</phrase> <phrase role="identifier">wait_for</phrase><phrase role="special">(</phrase> std::unique_lock< mutex > <phrase role="special">&,</phrase> 6533 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">duration</phrase><phrase role="special"><</phrase> <phrase role="identifier">Rep</phrase><phrase role="special">,</phrase> <phrase role="identifier">Period</phrase> <phrase role="special">></phrase> <phrase role="keyword">const</phrase><phrase role="special">&,</phrase> 6534 <phrase role="identifier">Pred</phrase><phrase role="special">);</phrase> 6535<phrase role="special">};</phrase> 6536 6537<phrase role="special">}}</phrase> 6538</programlisting> 6539 <bridgehead renderas="sect4" id="fiber.synchronization.conditions.h7"> 6540 <phrase id="fiber.synchronization.conditions.constructor0"/><link linkend="fiber.synchronization.conditions.constructor0">Constructor</link> 6541 </bridgehead> 6542<programlisting>condition_variable<phrase role="special">()</phrase> 6543</programlisting> 6544 <variablelist> 6545 <title></title> 6546 <varlistentry> 6547 <term>Effects:</term> 6548 <listitem> 6549 <para> 6550 Creates the object. 6551 </para> 6552 </listitem> 6553 </varlistentry> 6554 <varlistentry> 6555 <term>Throws:</term> 6556 <listitem> 6557 <para> 6558 Nothing. 6559 </para> 6560 </listitem> 6561 </varlistentry> 6562 </variablelist> 6563 <bridgehead renderas="sect4" id="fiber.synchronization.conditions.h8"> 6564 <phrase id="fiber.synchronization.conditions.destructor0"/><link linkend="fiber.synchronization.conditions.destructor0">Destructor</link> 6565 </bridgehead> 6566<programlisting><phrase role="special">~</phrase>condition_variable<phrase role="special">()</phrase> 6567</programlisting> 6568 <variablelist> 6569 <title></title> 6570 <varlistentry> 6571 <term>Precondition:</term> 6572 <listitem> 6573 <para> 6574 All fibers waiting on <code><phrase role="special">*</phrase><phrase 6575 role="keyword">this</phrase></code> have been notified by a call to 6576 <code><phrase role="identifier">notify_one</phrase></code> or <code><phrase 6577 role="identifier">notify_all</phrase></code> (though the respective 6578 calls to <code><phrase role="identifier">wait</phrase></code>, <code><phrase 6579 role="identifier">wait_for</phrase></code> or <code><phrase role="identifier">wait_until</phrase></code> 6580 need not have returned). 6581 </para> 6582 </listitem> 6583 </varlistentry> 6584 <varlistentry> 6585 <term>Effects:</term> 6586 <listitem> 6587 <para> 6588 Destroys the object. 6589 </para> 6590 </listitem> 6591 </varlistentry> 6592 </variablelist> 6593 <para> 6594 <bridgehead renderas="sect4" id="condition_variable_notify_one_bridgehead"> 6595 <phrase id="condition_variable_notify_one"/> 6596 <link linkend="condition_variable_notify_one">Member 6597 function <code>notify_one</code>()</link> 6598</bridgehead> 6599 </para> 6600<programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">notify_one</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 6601</programlisting> 6602 <variablelist> 6603 <title></title> 6604 <varlistentry> 6605 <term>Effects:</term> 6606 <listitem> 6607 <para> 6608 If any fibers are currently <link linkend="blocking"><emphasis>blocked</emphasis></link> 6609 waiting on <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code> 6610 in a call to <code><phrase role="identifier">wait</phrase></code>, 6611 <code><phrase role="identifier">wait_for</phrase></code> or <code><phrase 6612 role="identifier">wait_until</phrase></code>, unblocks one of those 6613 fibers. 6614 </para> 6615 </listitem> 6616 </varlistentry> 6617 <varlistentry> 6618 <term>Throws:</term> 6619 <listitem> 6620 <para> 6621 Nothing. 6622 </para> 6623 </listitem> 6624 </varlistentry> 6625 <varlistentry> 6626 <term>Note:</term> 6627 <listitem> 6628 <para> 6629 It is arbitrary which waiting fiber is resumed. 6630 </para> 6631 </listitem> 6632 </varlistentry> 6633 </variablelist> 6634 <para> 6635 <bridgehead renderas="sect4" id="condition_variable_notify_all_bridgehead"> 6636 <phrase id="condition_variable_notify_all"/> 6637 <link linkend="condition_variable_notify_all">Member 6638 function <code>notify_all</code>()</link> 6639</bridgehead> 6640 </para> 6641<programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">notify_all</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 6642</programlisting> 6643 <variablelist> 6644 <title></title> 6645 <varlistentry> 6646 <term>Effects:</term> 6647 <listitem> 6648 <para> 6649 If any fibers are currently <link linkend="blocking"><emphasis>blocked</emphasis></link> 6650 waiting on <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code> 6651 in a call to <code><phrase role="identifier">wait</phrase></code>, 6652 <code><phrase role="identifier">wait_for</phrase></code> or <code><phrase 6653 role="identifier">wait_until</phrase></code>, unblocks all of those 6654 fibers. 6655 </para> 6656 </listitem> 6657 </varlistentry> 6658 <varlistentry> 6659 <term>Throws:</term> 6660 <listitem> 6661 <para> 6662 Nothing. 6663 </para> 6664 </listitem> 6665 </varlistentry> 6666 <varlistentry> 6667 <term>Note:</term> 6668 <listitem> 6669 <para> 6670 This is why a waiting fiber must <emphasis>also</emphasis> check for 6671 the desired program state using a mechanism external to the <code>condition_variable</code>, 6672 and retry the wait until that state is reached. A fiber waiting on 6673 a <code>condition_variable</code> might well wake up a number of times before the 6674 desired state is reached. 6675 </para> 6676 </listitem> 6677 </varlistentry> 6678 </variablelist> 6679 <para> 6680 <bridgehead renderas="sect4" id="condition_variable_wait_bridgehead"> 6681 <phrase id="condition_variable_wait"/> 6682 <link linkend="condition_variable_wait">Templated 6683 member function <code>wait</code>()</link> 6684</bridgehead> 6685 </para> 6686<programlisting>void <phrase role="identifier">wait</phrase><phrase role="special">(</phrase> std::unique_lock< mutex > <phrase role="special">&</phrase> <phrase role="identifier">lk</phrase><phrase role="special">);</phrase> 6687 6688<phrase role="keyword">template</phrase><phrase role="special"><</phrase> typename <phrase role="identifier">Pred</phrase> <phrase role="special">></phrase> 6689<phrase role="keyword">void</phrase> <phrase role="identifier">wait</phrase><phrase role="special">(</phrase> std::unique_lock< mutex > <phrase role="special">&</phrase> <phrase role="identifier">lk</phrase><phrase role="special">,</phrase> <phrase role="identifier">Pred</phrase> <phrase role="identifier">pred</phrase><phrase role="special">);</phrase> 6690</programlisting> 6691 <variablelist> 6692 <title></title> 6693 <varlistentry> 6694 <term>Precondition:</term> 6695 <listitem> 6696 <para> 6697 <code><phrase role="identifier">lk</phrase></code> is locked by the 6698 current fiber, and either no other fiber is currently waiting on <code><phrase 6699 role="special">*</phrase><phrase role="keyword">this</phrase></code>, 6700 or the execution of the <ulink url="http://en.cppreference.com/w/cpp/thread/unique_lock/mutex"><code><phrase 6701 role="identifier">mutex</phrase><phrase role="special">()</phrase></code></ulink> 6702 member function on the <code><phrase role="identifier">lk</phrase></code> 6703 objects supplied in the calls to <code><phrase role="identifier">wait</phrase></code> 6704 in all the fibers currently waiting on <code><phrase role="special">*</phrase><phrase 6705 role="keyword">this</phrase></code> would return the same value as 6706 <code><phrase role="identifier">lk</phrase><phrase role="special">-></phrase><phrase 6707 role="identifier">mutex</phrase><phrase role="special">()</phrase></code> 6708 for this call to <code><phrase role="identifier">wait</phrase></code>. 6709 </para> 6710 </listitem> 6711 </varlistentry> 6712 <varlistentry> 6713 <term>Effects:</term> 6714 <listitem> 6715 <para> 6716 Atomically call <code><phrase role="identifier">lk</phrase><phrase 6717 role="special">.</phrase><phrase role="identifier">unlock</phrase><phrase 6718 role="special">()</phrase></code> and blocks the current fiber. The 6719 fiber will unblock when notified by a call to <code><phrase role="keyword">this</phrase><phrase 6720 role="special">-></phrase><phrase role="identifier">notify_one</phrase><phrase 6721 role="special">()</phrase></code> or <code><phrase role="keyword">this</phrase><phrase 6722 role="special">-></phrase><phrase role="identifier">notify_all</phrase><phrase 6723 role="special">()</phrase></code>. When the fiber is unblocked (for 6724 whatever reason), the lock is reacquired by invoking <code><phrase 6725 role="identifier">lk</phrase><phrase role="special">.</phrase><phrase 6726 role="identifier">lock</phrase><phrase role="special">()</phrase></code> 6727 before the call to <code><phrase role="identifier">wait</phrase></code> 6728 returns. The lock is also reacquired by invoking <code><phrase role="identifier">lk</phrase><phrase 6729 role="special">.</phrase><phrase role="identifier">lock</phrase><phrase 6730 role="special">()</phrase></code> if the function exits with an exception. 6731 The member function accepting <code><phrase role="identifier">pred</phrase></code> 6732 is shorthand for: 6733<programlisting><phrase role="keyword">while</phrase> <phrase role="special">(</phrase> <phrase role="special">!</phrase> <phrase role="identifier">pred</phrase><phrase role="special">()</phrase> <phrase role="special">)</phrase> <phrase role="special">{</phrase> 6734 <phrase role="identifier">wait</phrase><phrase role="special">(</phrase> <phrase role="identifier">lk</phrase><phrase role="special">);</phrase> 6735<phrase role="special">}</phrase> 6736</programlisting> 6737 </para> 6738 </listitem> 6739 </varlistentry> 6740 <varlistentry> 6741 <term>Postcondition:</term> 6742 <listitem> 6743 <para> 6744 <code><phrase role="identifier">lk</phrase></code> is locked by the 6745 current fiber. 6746 </para> 6747 </listitem> 6748 </varlistentry> 6749 <varlistentry> 6750 <term>Throws:</term> 6751 <listitem> 6752 <para> 6753 <code><phrase role="identifier">fiber_error</phrase></code> if an error 6754 occurs. 6755 </para> 6756 </listitem> 6757 </varlistentry> 6758 <varlistentry> 6759 <term>Note:</term> 6760 <listitem> 6761 <para> 6762 The Precondition is a bit dense. It merely states that all the fibers 6763 concurrently calling <code><phrase role="identifier">wait</phrase></code> 6764 on <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code> 6765 must wait on <code><phrase role="identifier">lk</phrase></code> objects 6766 governing the <emphasis>same</emphasis> <link linkend="class_mutex"><code>mutex</code></link>. Three distinct 6767 objects are involved in any <code>condition_variable::wait()</code> call: the <code>condition_variable</code> itself, 6768 the <code><phrase role="identifier">mutex</phrase></code> coordinating 6769 access between fibers and a local lock object (e.g. <ulink url="http://en.cppreference.com/w/cpp/thread/unique_lock"><code><phrase 6770 role="identifier">std</phrase><phrase role="special">::</phrase><phrase 6771 role="identifier">unique_lock</phrase></code></ulink>). In general, 6772 you can partition the lifespan of a given <code>condition_variable</code> instance 6773 into periods with one or more fibers waiting on it, separated by periods 6774 when no fibers are waiting on it. When more than one fiber is waiting 6775 on that <code>condition_variable</code>, all must pass lock objects referencing 6776 the <emphasis>same</emphasis> <code><phrase role="identifier">mutex</phrase></code> 6777 instance. 6778 </para> 6779 </listitem> 6780 </varlistentry> 6781 </variablelist> 6782 <para> 6783 <bridgehead renderas="sect4" id="condition_variable_wait_until_bridgehead"> 6784 <phrase id="condition_variable_wait_until"/> 6785 <link linkend="condition_variable_wait_until">Templated 6786 member function <code>wait_until</code>()</link> 6787</bridgehead> 6788 </para> 6789<programlisting><phrase role="keyword">template</phrase><phrase role="special"><</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> 6790<phrase role="identifier">cv_status</phrase> <phrase role="identifier">wait_until</phrase><phrase role="special">(</phrase> std::unique_lock< mutex > <phrase role="special">&</phrase> <phrase role="identifier">lk</phrase><phrase role="special">,</phrase> 6791 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">time_point</phrase><phrase role="special"><</phrase> <phrase role="identifier">Clock</phrase><phrase role="special">,</phrase> <phrase role="identifier">Duration</phrase> <phrase role="special">></phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">abs_time</phrase><phrase role="special">);</phrase> 6792 6793<phrase role="keyword">template</phrase><phrase role="special"><</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">></phrase> 6794<phrase role="keyword">bool</phrase> <phrase role="identifier">wait_until</phrase><phrase role="special">(</phrase> std::unique_lock< mutex > <phrase role="special">&</phrase> <phrase role="identifier">lk</phrase><phrase role="special">,</phrase> 6795 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">time_point</phrase><phrase role="special"><</phrase> <phrase role="identifier">Clock</phrase><phrase role="special">,</phrase> <phrase role="identifier">Duration</phrase> <phrase role="special">></phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">abs_time</phrase><phrase role="special">,</phrase> 6796 <phrase role="identifier">Pred</phrase> <phrase role="identifier">pred</phrase><phrase role="special">);</phrase> 6797</programlisting> 6798 <variablelist> 6799 <title></title> 6800 <varlistentry> 6801 <term>Precondition:</term> 6802 <listitem> 6803 <para> 6804 <code><phrase role="identifier">lk</phrase></code> is locked by the 6805 current fiber, and either no other fiber is currently waiting on <code><phrase 6806 role="special">*</phrase><phrase role="keyword">this</phrase></code>, 6807 or the execution of the <code><phrase role="identifier">mutex</phrase><phrase 6808 role="special">()</phrase></code> member function on the <code><phrase 6809 role="identifier">lk</phrase></code> objects supplied in the calls 6810 to <code><phrase role="identifier">wait</phrase></code>, <code><phrase 6811 role="identifier">wait_for</phrase></code> or <code><phrase role="identifier">wait_until</phrase></code> 6812 in all the fibers currently waiting on <code><phrase role="special">*</phrase><phrase 6813 role="keyword">this</phrase></code> would return the same value as 6814 <code><phrase role="identifier">lk</phrase><phrase role="special">.</phrase><phrase 6815 role="identifier">mutex</phrase><phrase role="special">()</phrase></code> 6816 for this call to <code><phrase role="identifier">wait_until</phrase></code>. 6817 </para> 6818 </listitem> 6819 </varlistentry> 6820 <varlistentry> 6821 <term>Effects:</term> 6822 <listitem> 6823 <para> 6824 Atomically call <code><phrase role="identifier">lk</phrase><phrase 6825 role="special">.</phrase><phrase role="identifier">unlock</phrase><phrase 6826 role="special">()</phrase></code> and blocks the current fiber. The 6827 fiber will unblock when notified by a call to <code><phrase role="keyword">this</phrase><phrase 6828 role="special">-></phrase><phrase role="identifier">notify_one</phrase><phrase 6829 role="special">()</phrase></code> or <code><phrase role="keyword">this</phrase><phrase 6830 role="special">-></phrase><phrase role="identifier">notify_all</phrase><phrase 6831 role="special">()</phrase></code>, when the system time would be equal 6832 to or later than the specified <code><phrase role="identifier">abs_time</phrase></code>. 6833 When the fiber is unblocked (for whatever reason), the lock is reacquired 6834 by invoking <code><phrase role="identifier">lk</phrase><phrase role="special">.</phrase><phrase 6835 role="identifier">lock</phrase><phrase role="special">()</phrase></code> 6836 before the call to <code><phrase role="identifier">wait_until</phrase></code> 6837 returns. The lock is also reacquired by invoking <code><phrase role="identifier">lk</phrase><phrase 6838 role="special">.</phrase><phrase role="identifier">lock</phrase><phrase 6839 role="special">()</phrase></code> if the function exits with an exception. 6840 The member function accepting <code><phrase role="identifier">pred</phrase></code> 6841 is shorthand for: 6842<programlisting><phrase role="keyword">while</phrase> <phrase role="special">(</phrase> <phrase role="special">!</phrase> <phrase role="identifier">pred</phrase><phrase role="special">()</phrase> <phrase role="special">)</phrase> <phrase role="special">{</phrase> 6843 <phrase role="keyword">if</phrase> <phrase role="special">(</phrase> <phrase role="identifier">cv_status</phrase><phrase role="special">::</phrase><phrase role="identifier">timeout</phrase> <phrase role="special">==</phrase> <phrase role="identifier">wait_until</phrase><phrase role="special">(</phrase> <phrase role="identifier">lk</phrase><phrase role="special">,</phrase> <phrase role="identifier">abs_time</phrase><phrase role="special">)</phrase> <phrase role="special">)</phrase> 6844 <phrase role="keyword">return</phrase> <phrase role="identifier">pred</phrase><phrase role="special">();</phrase> 6845<phrase role="special">}</phrase> 6846<phrase role="keyword">return</phrase> <phrase role="keyword">true</phrase><phrase role="special">;</phrase> 6847</programlisting> 6848 That is, even if <code><phrase role="identifier">wait_until</phrase><phrase 6849 role="special">()</phrase></code> times out, it can still return <code><phrase 6850 role="keyword">true</phrase></code> if <code><phrase role="identifier">pred</phrase><phrase 6851 role="special">()</phrase></code> returns <code><phrase role="keyword">true</phrase></code> 6852 at that time. 6853 </para> 6854 </listitem> 6855 </varlistentry> 6856 <varlistentry> 6857 <term>Postcondition:</term> 6858 <listitem> 6859 <para> 6860 <code><phrase role="identifier">lk</phrase></code> is locked by the 6861 current fiber. 6862 </para> 6863 </listitem> 6864 </varlistentry> 6865 <varlistentry> 6866 <term>Throws:</term> 6867 <listitem> 6868 <para> 6869 <code><phrase role="identifier">fiber_error</phrase></code> if an error 6870 occurs or timeout-related exceptions. 6871 </para> 6872 </listitem> 6873 </varlistentry> 6874 <varlistentry> 6875 <term>Returns:</term> 6876 <listitem> 6877 <para> 6878 The overload without <code><phrase role="identifier">pred</phrase></code> 6879 returns <code><phrase role="identifier">cv_status</phrase><phrase role="special">::</phrase><phrase 6880 role="identifier">no_timeout</phrase></code> if awakened by <code><phrase 6881 role="identifier">notify_one</phrase><phrase role="special">()</phrase></code> 6882 or <code><phrase role="identifier">notify_all</phrase><phrase role="special">()</phrase></code>, 6883 or <code><phrase role="identifier">cv_status</phrase><phrase role="special">::</phrase><phrase 6884 role="identifier">timeout</phrase></code> if awakened because the system 6885 time is past <code><phrase role="identifier">abs_time</phrase></code>. 6886 </para> 6887 </listitem> 6888 </varlistentry> 6889 <varlistentry> 6890 <term>Returns:</term> 6891 <listitem> 6892 <para> 6893 The overload accepting <code><phrase role="identifier">pred</phrase></code> 6894 returns <code><phrase role="keyword">false</phrase></code> if the call 6895 is returning because the time specified by <code><phrase role="identifier">abs_time</phrase></code> 6896 was reached and the predicate returns <code><phrase role="keyword">false</phrase></code>, 6897 <code><phrase role="keyword">true</phrase></code> otherwise. 6898 </para> 6899 </listitem> 6900 </varlistentry> 6901 <varlistentry> 6902 <term>Note:</term> 6903 <listitem> 6904 <para> 6905 See <emphasis role="bold">Note</emphasis> for <link linkend="condition_variable_wait"><code>condition_variable::wait()</code></link>. 6906 </para> 6907 </listitem> 6908 </varlistentry> 6909 </variablelist> 6910 <para> 6911 <bridgehead renderas="sect4" id="condition_variable_wait_for_bridgehead"> 6912 <phrase id="condition_variable_wait_for"/> 6913 <link linkend="condition_variable_wait_for">Templated 6914 member function <code>wait_for</code>()</link> 6915</bridgehead> 6916 </para> 6917<programlisting><phrase role="keyword">template</phrase><phrase role="special"><</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> 6918<phrase role="identifier">cv_status</phrase> <phrase role="identifier">wait_for</phrase><phrase role="special">(</phrase> std::unique_lock< mutex > <phrase role="special">&</phrase> <phrase role="identifier">lk</phrase><phrase role="special">,</phrase> 6919 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">duration</phrase><phrase role="special"><</phrase> <phrase role="identifier">Rep</phrase><phrase role="special">,</phrase> <phrase role="identifier">Period</phrase> <phrase role="special">></phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">rel_time</phrase><phrase role="special">);</phrase> 6920 6921<phrase role="keyword">template</phrase><phrase role="special"><</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">></phrase> 6922<phrase role="keyword">bool</phrase> <phrase role="identifier">wait_for</phrase><phrase role="special">(</phrase> std::unique_lock< mutex > <phrase role="special">&</phrase> <phrase role="identifier">lk</phrase><phrase role="special">,</phrase> 6923 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">duration</phrase><phrase role="special"><</phrase> <phrase role="identifier">Rep</phrase><phrase role="special">,</phrase> <phrase role="identifier">Period</phrase> <phrase role="special">></phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">rel_time</phrase><phrase role="special">,</phrase> 6924 <phrase role="identifier">Pred</phrase> <phrase role="identifier">pred</phrase><phrase role="special">);</phrase> 6925</programlisting> 6926 <variablelist> 6927 <title></title> 6928 <varlistentry> 6929 <term>Precondition:</term> 6930 <listitem> 6931 <para> 6932 <code><phrase role="identifier">lk</phrase></code> is locked by the 6933 current fiber, and either no other fiber is currently waiting on <code><phrase 6934 role="special">*</phrase><phrase role="keyword">this</phrase></code>, 6935 or the execution of the <code><phrase role="identifier">mutex</phrase><phrase 6936 role="special">()</phrase></code> member function on the <code><phrase 6937 role="identifier">lk</phrase></code> objects supplied in the calls 6938 to <code><phrase role="identifier">wait</phrase></code>, <code><phrase 6939 role="identifier">wait_for</phrase></code> or <code><phrase role="identifier">wait_until</phrase></code> 6940 in all the fibers currently waiting on <code><phrase role="special">*</phrase><phrase 6941 role="keyword">this</phrase></code> would return the same value as 6942 <code><phrase role="identifier">lk</phrase><phrase role="special">.</phrase><phrase 6943 role="identifier">mutex</phrase><phrase role="special">()</phrase></code> 6944 for this call to <code><phrase role="identifier">wait_for</phrase></code>. 6945 </para> 6946 </listitem> 6947 </varlistentry> 6948 <varlistentry> 6949 <term>Effects:</term> 6950 <listitem> 6951 <para> 6952 Atomically call <code><phrase role="identifier">lk</phrase><phrase 6953 role="special">.</phrase><phrase role="identifier">unlock</phrase><phrase 6954 role="special">()</phrase></code> and blocks the current fiber. The 6955 fiber will unblock when notified by a call to <code><phrase role="keyword">this</phrase><phrase 6956 role="special">-></phrase><phrase role="identifier">notify_one</phrase><phrase 6957 role="special">()</phrase></code> or <code><phrase role="keyword">this</phrase><phrase 6958 role="special">-></phrase><phrase role="identifier">notify_all</phrase><phrase 6959 role="special">()</phrase></code>, when a time interval equal to or 6960 greater than the specified <code><phrase role="identifier">rel_time</phrase></code> 6961 has elapsed. When the fiber is unblocked (for whatever reason), the 6962 lock is reacquired by invoking <code><phrase role="identifier">lk</phrase><phrase 6963 role="special">.</phrase><phrase role="identifier">lock</phrase><phrase 6964 role="special">()</phrase></code> before the call to <code><phrase 6965 role="identifier">wait</phrase></code> returns. The lock is also reacquired 6966 by invoking <code><phrase role="identifier">lk</phrase><phrase role="special">.</phrase><phrase 6967 role="identifier">lock</phrase><phrase role="special">()</phrase></code> 6968 if the function exits with an exception. The <code><phrase role="identifier">wait_for</phrase><phrase 6969 role="special">()</phrase></code> member function accepting <code><phrase 6970 role="identifier">pred</phrase></code> is shorthand for: 6971<programlisting><phrase role="keyword">while</phrase> <phrase role="special">(</phrase> <phrase role="special">!</phrase> <phrase role="identifier">pred</phrase><phrase role="special">()</phrase> <phrase role="special">)</phrase> <phrase role="special">{</phrase> 6972 <phrase role="keyword">if</phrase> <phrase role="special">(</phrase> <phrase role="identifier">cv_status</phrase><phrase role="special">::</phrase><phrase role="identifier">timeout</phrase> <phrase role="special">==</phrase> <phrase role="identifier">wait_for</phrase><phrase role="special">(</phrase> <phrase role="identifier">lk</phrase><phrase role="special">,</phrase> <phrase role="identifier">rel_time</phrase><phrase role="special">)</phrase> <phrase role="special">)</phrase> <phrase role="special">{</phrase> 6973 <phrase role="keyword">return</phrase> <phrase role="identifier">pred</phrase><phrase role="special">();</phrase> 6974 <phrase role="special">}</phrase> 6975<phrase role="special">}</phrase> 6976<phrase role="keyword">return</phrase> <phrase role="keyword">true</phrase><phrase role="special">;</phrase> 6977</programlisting> 6978 (except of course that <code><phrase role="identifier">rel_time</phrase></code> 6979 is adjusted for each iteration). The point is that, even if <code><phrase 6980 role="identifier">wait_for</phrase><phrase role="special">()</phrase></code> 6981 times out, it can still return <code><phrase role="keyword">true</phrase></code> 6982 if <code><phrase role="identifier">pred</phrase><phrase role="special">()</phrase></code> 6983 returns <code><phrase role="keyword">true</phrase></code> at that time. 6984 </para> 6985 </listitem> 6986 </varlistentry> 6987 <varlistentry> 6988 <term>Postcondition:</term> 6989 <listitem> 6990 <para> 6991 <code><phrase role="identifier">lk</phrase></code> is locked by the 6992 current fiber. 6993 </para> 6994 </listitem> 6995 </varlistentry> 6996 <varlistentry> 6997 <term>Throws:</term> 6998 <listitem> 6999 <para> 7000 <code><phrase role="identifier">fiber_error</phrase></code> if an error 7001 occurs or timeout-related exceptions. 7002 </para> 7003 </listitem> 7004 </varlistentry> 7005 <varlistentry> 7006 <term>Returns:</term> 7007 <listitem> 7008 <para> 7009 The overload without <code><phrase role="identifier">pred</phrase></code> 7010 returns <code><phrase role="identifier">cv_status</phrase><phrase role="special">::</phrase><phrase 7011 role="identifier">no_timeout</phrase></code> if awakened by <code><phrase 7012 role="identifier">notify_one</phrase><phrase role="special">()</phrase></code> 7013 or <code><phrase role="identifier">notify_all</phrase><phrase role="special">()</phrase></code>, 7014 or <code><phrase role="identifier">cv_status</phrase><phrase role="special">::</phrase><phrase 7015 role="identifier">timeout</phrase></code> if awakened because at least 7016 <code><phrase role="identifier">rel_time</phrase></code> has elapsed. 7017 </para> 7018 </listitem> 7019 </varlistentry> 7020 <varlistentry> 7021 <term>Returns:</term> 7022 <listitem> 7023 <para> 7024 The overload accepting <code><phrase role="identifier">pred</phrase></code> 7025 returns <code><phrase role="keyword">false</phrase></code> if the call 7026 is returning because at least <code><phrase role="identifier">rel_time</phrase></code> 7027 has elapsed and the predicate returns <code><phrase role="keyword">false</phrase></code>, 7028 <code><phrase role="keyword">true</phrase></code> otherwise. 7029 </para> 7030 </listitem> 7031 </varlistentry> 7032 <varlistentry> 7033 <term>Note:</term> 7034 <listitem> 7035 <para> 7036 See <emphasis role="bold">Note</emphasis> for <link linkend="condition_variable_wait"><code>condition_variable::wait()</code></link>. 7037 </para> 7038 </listitem> 7039 </varlistentry> 7040 </variablelist> 7041 </section> 7042 <section id="fiber.synchronization.barriers"> 7043 <title><link linkend="fiber.synchronization.barriers">Barriers</link></title> 7044 <para> 7045 A barrier is a concept also known as a <emphasis>rendezvous</emphasis>, it 7046 is a synchronization point between multiple contexts of execution (fibers). 7047 The barrier is configured for a particular number of fibers (<code><phrase 7048 role="identifier">n</phrase></code>), and as fibers reach the barrier they 7049 must wait until all <code><phrase role="identifier">n</phrase></code> fibers 7050 have arrived. Once the <code><phrase role="identifier">n</phrase></code>-th 7051 fiber has reached the barrier, all the waiting fibers can proceed, and the 7052 barrier is reset. 7053 </para> 7054 <para> 7055 The fact that the barrier automatically resets is significant. Consider a 7056 case in which you launch some number of fibers and want to wait only until 7057 the first of them has completed. You might be tempted to use a <code><phrase 7058 role="identifier">barrier</phrase><phrase role="special">(</phrase><phrase 7059 role="number">2</phrase><phrase role="special">)</phrase></code> as the synchronization 7060 mechanism, making each new fiber call its <link linkend="barrier_wait"><code>barrier::wait()</code></link> method, 7061 then calling <code><phrase role="identifier">wait</phrase><phrase role="special">()</phrase></code> 7062 in the launching fiber to wait until the first other fiber completes. 7063 </para> 7064 <para> 7065 That will in fact unblock the launching fiber. The unfortunate part is that 7066 it will continue blocking the <emphasis>remaining</emphasis> fibers. 7067 </para> 7068 <para> 7069 Consider the following scenario: 7070 </para> 7071 <orderedlist> 7072 <listitem> 7073 <simpara> 7074 Fiber <quote>main</quote> launches fibers A, B, C and D, then calls 7075 <code><phrase role="identifier">barrier</phrase><phrase role="special">::</phrase><phrase 7076 role="identifier">wait</phrase><phrase role="special">()</phrase></code>. 7077 </simpara> 7078 </listitem> 7079 <listitem> 7080 <simpara> 7081 Fiber C finishes first and likewise calls <code><phrase role="identifier">barrier</phrase><phrase 7082 role="special">::</phrase><phrase role="identifier">wait</phrase><phrase 7083 role="special">()</phrase></code>. 7084 </simpara> 7085 </listitem> 7086 <listitem> 7087 <simpara> 7088 Fiber <quote>main</quote> is unblocked, as desired. 7089 </simpara> 7090 </listitem> 7091 <listitem> 7092 <simpara> 7093 Fiber B calls <code><phrase role="identifier">barrier</phrase><phrase 7094 role="special">::</phrase><phrase role="identifier">wait</phrase><phrase 7095 role="special">()</phrase></code>. Fiber B is <emphasis>blocked!</emphasis> 7096 </simpara> 7097 </listitem> 7098 <listitem> 7099 <simpara> 7100 Fiber A calls <code><phrase role="identifier">barrier</phrase><phrase 7101 role="special">::</phrase><phrase role="identifier">wait</phrase><phrase 7102 role="special">()</phrase></code>. Fibers A and B are unblocked. 7103 </simpara> 7104 </listitem> 7105 <listitem> 7106 <simpara> 7107 Fiber D calls <code><phrase role="identifier">barrier</phrase><phrase 7108 role="special">::</phrase><phrase role="identifier">wait</phrase><phrase 7109 role="special">()</phrase></code>. Fiber D is blocked indefinitely. 7110 </simpara> 7111 </listitem> 7112 </orderedlist> 7113 <para> 7114 (See also <link linkend="wait_first_simple_section">when_any, simple completion</link>.) 7115 </para> 7116 <note> 7117 <para> 7118 It is unwise to tie the lifespan of a barrier to any one of its participating 7119 fibers. Although conceptually all waiting fibers awaken <quote>simultaneously,</quote> 7120 because of the nature of fibers, in practice they will awaken one by one 7121 in indeterminate order.<footnote id="fiber.synchronization.barriers.f0"> 7122 <para> 7123 The current implementation wakes fibers in FIFO order: the first to call 7124 <code><phrase role="identifier">wait</phrase><phrase role="special">()</phrase></code> 7125 wakes first, and so forth. But it is perilous to rely on the order in 7126 which the various fibers will reach the <code><phrase role="identifier">wait</phrase><phrase 7127 role="special">()</phrase></code> call. 7128 </para> 7129 </footnote> The rest of the waiting fibers will still be blocked in <code><phrase 7130 role="identifier">wait</phrase><phrase role="special">()</phrase></code>, 7131 which must, before returning, access data members in the barrier object. 7132 </para> 7133 </note> 7134 <para> 7135 <bridgehead renderas="sect4" id="class_barrier_bridgehead"> 7136 <phrase id="class_barrier"/> 7137 <link linkend="class_barrier">Class <code>barrier</code></link> 7138</bridgehead> 7139 </para> 7140<programlisting><phrase role="preprocessor">#include</phrase> <phrase role="special"><</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">></phrase> 7141 7142<phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase> 7143<phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase> 7144 7145<phrase role="keyword">class</phrase> <phrase role="identifier">barrier</phrase> <phrase role="special">{</phrase> 7146<phrase role="keyword">public</phrase><phrase role="special">:</phrase> 7147 <phrase role="keyword">explicit</phrase> <phrase role="identifier">barrier</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase><phrase role="special">);</phrase> 7148 7149 <phrase role="identifier">barrier</phrase><phrase role="special">(</phrase> <phrase role="identifier">barrier</phrase> <phrase role="keyword">const</phrase><phrase role="special">&)</phrase> <phrase role="special">=</phrase> <phrase role="keyword">delete</phrase><phrase role="special">;</phrase> 7150 <phrase role="identifier">barrier</phrase> <phrase role="special">&</phrase> <phrase role="keyword">operator</phrase><phrase role="special">=(</phrase> <phrase role="identifier">barrier</phrase> <phrase role="keyword">const</phrase><phrase role="special">&)</phrase> <phrase role="special">=</phrase> <phrase role="keyword">delete</phrase><phrase role="special">;</phrase> 7151 7152 <phrase role="keyword">bool</phrase> <phrase role="identifier">wait</phrase><phrase role="special">();</phrase> 7153<phrase role="special">};</phrase> 7154 7155<phrase role="special">}}</phrase> 7156</programlisting> 7157 <para> 7158 Instances of <link linkend="class_barrier"><code>barrier</code></link> are not copyable or movable. 7159 </para> 7160 <bridgehead renderas="sect4" id="fiber.synchronization.barriers.h0"> 7161 <phrase id="fiber.synchronization.barriers.constructor"/><link linkend="fiber.synchronization.barriers.constructor">Constructor</link> 7162 </bridgehead> 7163<programlisting><phrase role="keyword">explicit</phrase> <phrase role="identifier">barrier</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">initial</phrase><phrase role="special">);</phrase> 7164</programlisting> 7165 <variablelist> 7166 <title></title> 7167 <varlistentry> 7168 <term>Effects:</term> 7169 <listitem> 7170 <para> 7171 Construct a barrier for <code><phrase role="identifier">initial</phrase></code> 7172 fibers. 7173 </para> 7174 </listitem> 7175 </varlistentry> 7176 <varlistentry> 7177 <term>Throws:</term> 7178 <listitem> 7179 <para> 7180 <code><phrase role="identifier">fiber_error</phrase></code> 7181 </para> 7182 </listitem> 7183 </varlistentry> 7184 <varlistentry> 7185 <term>Error Conditions:</term> 7186 <listitem> 7187 <para> 7188 <emphasis role="bold">invalid_argument</emphasis>: if <code><phrase 7189 role="identifier">initial</phrase></code> is zero. 7190 </para> 7191 </listitem> 7192 </varlistentry> 7193 </variablelist> 7194 <para> 7195 <bridgehead renderas="sect4" id="barrier_wait_bridgehead"> 7196 <phrase id="barrier_wait"/> 7197 <link linkend="barrier_wait">Member function <code>wait</code>()</link> 7198</bridgehead> 7199 </para> 7200<programlisting><phrase role="keyword">bool</phrase> <phrase role="identifier">wait</phrase><phrase role="special">();</phrase> 7201</programlisting> 7202 <variablelist> 7203 <title></title> 7204 <varlistentry> 7205 <term>Effects:</term> 7206 <listitem> 7207 <para> 7208 Block until <code><phrase role="identifier">initial</phrase></code> 7209 fibers have called <code><phrase role="identifier">wait</phrase></code> 7210 on <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>. 7211 When the <code><phrase role="identifier">initial</phrase></code>-th 7212 fiber calls <code><phrase role="identifier">wait</phrase></code>, all 7213 waiting fibers are unblocked, and the barrier is reset. 7214 </para> 7215 </listitem> 7216 </varlistentry> 7217 <varlistentry> 7218 <term>Returns:</term> 7219 <listitem> 7220 <para> 7221 <code><phrase role="keyword">true</phrase></code> for exactly one fiber 7222 from each batch of waiting fibers, <code><phrase role="keyword">false</phrase></code> 7223 otherwise. 7224 </para> 7225 </listitem> 7226 </varlistentry> 7227 <varlistentry> 7228 <term>Throws:</term> 7229 <listitem> 7230 <para> 7231 <code><phrase role="identifier">fiber_error</phrase></code> 7232 </para> 7233 </listitem> 7234 </varlistentry> 7235 </variablelist> 7236 </section> 7237 <section id="fiber.synchronization.channels"> 7238 <title><link linkend="fiber.synchronization.channels">Channels</link></title> 7239 <para> 7240 A channel is a model to communicate and synchronize <code><phrase role="identifier">Threads</phrase> 7241 <phrase role="identifier">of</phrase> <phrase role="identifier">Execution</phrase></code> 7242 <footnote id="fiber.synchronization.channels.f0"> 7243 <para> 7244 The smallest ordered sequence of instructions that can be managed independently 7245 by a scheduler is called a <code><phrase role="identifier">Thread</phrase> 7246 <phrase role="identifier">of</phrase> <phrase role="identifier">Execution</phrase></code>. 7247 </para> 7248 </footnote> via message passing. 7249 </para> 7250 <anchor id="class_channel_op_status"/> 7251 <bridgehead renderas="sect4" id="fiber.synchronization.channels.h0"> 7252 <phrase id="fiber.synchronization.channels.enumeration__code__phrase_role__identifier__channel_op_status__phrase___code_"/><link 7253 linkend="fiber.synchronization.channels.enumeration__code__phrase_role__identifier__channel_op_status__phrase___code_">Enumeration 7254 <code><phrase role="identifier">channel_op_status</phrase></code></link> 7255 </bridgehead> 7256 <para> 7257 channel operations return the state of the channel. 7258 </para> 7259<programlisting><phrase role="keyword">enum</phrase> <phrase role="keyword">class</phrase> <phrase role="identifier">channel_op_status</phrase> <phrase role="special">{</phrase> 7260 <phrase role="identifier">success</phrase><phrase role="special">,</phrase> 7261 <phrase role="identifier">empty</phrase><phrase role="special">,</phrase> 7262 <phrase role="identifier">full</phrase><phrase role="special">,</phrase> 7263 <phrase role="identifier">closed</phrase><phrase role="special">,</phrase> 7264 <phrase role="identifier">timeout</phrase> 7265<phrase role="special">};</phrase> 7266</programlisting> 7267 <bridgehead renderas="sect4" id="fiber.synchronization.channels.h1"> 7268 <phrase id="fiber.synchronization.channels._code__phrase_role__identifier__success__phrase___code_"/><link 7269 linkend="fiber.synchronization.channels._code__phrase_role__identifier__success__phrase___code_"><code><phrase 7270 role="identifier">success</phrase></code></link> 7271 </bridgehead> 7272 <variablelist> 7273 <title></title> 7274 <varlistentry> 7275 <term>Effects:</term> 7276 <listitem> 7277 <para> 7278 Operation was successful. 7279 </para> 7280 </listitem> 7281 </varlistentry> 7282 </variablelist> 7283 <bridgehead renderas="sect4" id="fiber.synchronization.channels.h2"> 7284 <phrase id="fiber.synchronization.channels._code__phrase_role__identifier__empty__phrase___code_"/><link 7285 linkend="fiber.synchronization.channels._code__phrase_role__identifier__empty__phrase___code_"><code><phrase 7286 role="identifier">empty</phrase></code></link> 7287 </bridgehead> 7288 <variablelist> 7289 <title></title> 7290 <varlistentry> 7291 <term>Effects:</term> 7292 <listitem> 7293 <para> 7294 channel is empty, operation failed. 7295 </para> 7296 </listitem> 7297 </varlistentry> 7298 </variablelist> 7299 <bridgehead renderas="sect4" id="fiber.synchronization.channels.h3"> 7300 <phrase id="fiber.synchronization.channels._code__phrase_role__identifier__full__phrase___code_"/><link 7301 linkend="fiber.synchronization.channels._code__phrase_role__identifier__full__phrase___code_"><code><phrase 7302 role="identifier">full</phrase></code></link> 7303 </bridgehead> 7304 <variablelist> 7305 <title></title> 7306 <varlistentry> 7307 <term>Effects:</term> 7308 <listitem> 7309 <para> 7310 channel is full, operation failed. 7311 </para> 7312 </listitem> 7313 </varlistentry> 7314 </variablelist> 7315 <bridgehead renderas="sect4" id="fiber.synchronization.channels.h4"> 7316 <phrase id="fiber.synchronization.channels._code__phrase_role__identifier__closed__phrase___code_"/><link 7317 linkend="fiber.synchronization.channels._code__phrase_role__identifier__closed__phrase___code_"><code><phrase 7318 role="identifier">closed</phrase></code></link> 7319 </bridgehead> 7320 <variablelist> 7321 <title></title> 7322 <varlistentry> 7323 <term>Effects:</term> 7324 <listitem> 7325 <para> 7326 channel is closed, operation failed. 7327 </para> 7328 </listitem> 7329 </varlistentry> 7330 </variablelist> 7331 <bridgehead renderas="sect4" id="fiber.synchronization.channels.h5"> 7332 <phrase id="fiber.synchronization.channels._code__phrase_role__identifier__timeout__phrase___code_"/><link 7333 linkend="fiber.synchronization.channels._code__phrase_role__identifier__timeout__phrase___code_"><code><phrase 7334 role="identifier">timeout</phrase></code></link> 7335 </bridgehead> 7336 <variablelist> 7337 <title></title> 7338 <varlistentry> 7339 <term>Effects:</term> 7340 <listitem> 7341 <para> 7342 The operation did not become ready before specified timeout elapsed. 7343 </para> 7344 </listitem> 7345 </varlistentry> 7346 </variablelist> 7347 <section id="fiber.synchronization.channels.buffered_channel"> 7348 <title><link linkend="fiber.synchronization.channels.buffered_channel">Buffered 7349 Channel</link></title> 7350 <para> 7351 <emphasis role="bold">Boost.Fiber</emphasis> provides a bounded, buffered 7352 channel (MPMC queue) suitable to synchonize fibers (running on same or 7353 different threads) via asynchronouss message passing. 7354 </para> 7355<programlisting><phrase role="keyword">typedef</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">buffered_channel</phrase><phrase role="special"><</phrase> <phrase role="keyword">int</phrase> <phrase role="special">></phrase> <phrase role="identifier">channel_t</phrase><phrase role="special">;</phrase> 7356 7357<phrase role="keyword">void</phrase> <phrase role="identifier">send</phrase><phrase role="special">(</phrase> <phrase role="identifier">channel_t</phrase> <phrase role="special">&</phrase> <phrase role="identifier">chan</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase> 7358 <phrase role="keyword">for</phrase> <phrase role="special">(</phrase> <phrase role="keyword">int</phrase> <phrase role="identifier">i</phrase> <phrase role="special">=</phrase> <phrase role="number">0</phrase><phrase role="special">;</phrase> <phrase role="identifier">i</phrase> <phrase role="special"><</phrase> <phrase role="number">5</phrase><phrase role="special">;</phrase> <phrase role="special">++</phrase><phrase role="identifier">i</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase> 7359 <phrase role="identifier">chan</phrase><phrase role="special">.</phrase><phrase role="identifier">push</phrase><phrase role="special">(</phrase> <phrase role="identifier">i</phrase><phrase role="special">);</phrase> 7360 <phrase role="special">}</phrase> 7361 <phrase role="identifier">chan</phrase><phrase role="special">.</phrase><phrase role="identifier">close</phrase><phrase role="special">();</phrase> 7362<phrase role="special">}</phrase> 7363 7364<phrase role="keyword">void</phrase> <phrase role="identifier">recv</phrase><phrase role="special">(</phrase> <phrase role="identifier">channel_t</phrase> <phrase role="special">&</phrase> <phrase role="identifier">chan</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase> 7365 <phrase role="keyword">int</phrase> <phrase role="identifier">i</phrase><phrase role="special">;</phrase> 7366 <phrase role="keyword">while</phrase> <phrase role="special">(</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">channel_op_status</phrase><phrase role="special">::</phrase><phrase role="identifier">success</phrase> <phrase role="special">==</phrase> <phrase role="identifier">chan</phrase><phrase role="special">.</phrase><phrase role="identifier">pop</phrase><phrase role="special">(</phrase><phrase role="identifier">i</phrase><phrase role="special">)</phrase> <phrase role="special">)</phrase> <phrase role="special">{</phrase> 7367 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cout</phrase> <phrase role="special"><<</phrase> <phrase role="string">"received "</phrase> <phrase role="special"><<</phrase> <phrase role="identifier">i</phrase> <phrase role="special"><<</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">endl</phrase><phrase role="special">;</phrase> 7368 <phrase role="special">}</phrase> 7369<phrase role="special">}</phrase> 7370 7371<phrase role="identifier">channel_t</phrase> <phrase role="identifier">chan</phrase><phrase role="special">{</phrase> <phrase role="number">2</phrase> <phrase role="special">};</phrase> 7372<phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">fiber</phrase> <phrase role="identifier">f1</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">bind</phrase><phrase role="special">(</phrase> <phrase role="identifier">send</phrase><phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">ref</phrase><phrase role="special">(</phrase> <phrase role="identifier">chan</phrase><phrase role="special">)</phrase> <phrase role="special">)</phrase> <phrase role="special">);</phrase> 7373<phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">fiber</phrase> <phrase role="identifier">f2</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">bind</phrase><phrase role="special">(</phrase> <phrase role="identifier">recv</phrase><phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">ref</phrase><phrase role="special">(</phrase> <phrase role="identifier">chan</phrase><phrase role="special">)</phrase> <phrase role="special">)</phrase> <phrase role="special">);</phrase> 7374 7375<phrase role="identifier">f1</phrase><phrase role="special">.</phrase><phrase role="identifier">join</phrase><phrase role="special">();</phrase> 7376<phrase role="identifier">f2</phrase><phrase role="special">.</phrase><phrase role="identifier">join</phrase><phrase role="special">();</phrase> 7377</programlisting> 7378 <para> 7379 Class <code><phrase role="identifier">buffered_channel</phrase></code> 7380 supports range-for syntax: 7381 </para> 7382<programlisting><phrase role="keyword">typedef</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">buffered_channel</phrase><phrase role="special"><</phrase> <phrase role="keyword">int</phrase> <phrase role="special">></phrase> <phrase role="identifier">channel_t</phrase><phrase role="special">;</phrase> 7383 7384<phrase role="keyword">void</phrase> <phrase role="identifier">foo</phrase><phrase role="special">(</phrase> <phrase role="identifier">channel_t</phrase> <phrase role="special">&</phrase> <phrase role="identifier">chan</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase> 7385 <phrase role="identifier">chan</phrase><phrase role="special">.</phrase><phrase role="identifier">push</phrase><phrase role="special">(</phrase> <phrase role="number">1</phrase><phrase role="special">);</phrase> 7386 <phrase role="identifier">chan</phrase><phrase role="special">.</phrase><phrase role="identifier">push</phrase><phrase role="special">(</phrase> <phrase role="number">1</phrase><phrase role="special">);</phrase> 7387 <phrase role="identifier">chan</phrase><phrase role="special">.</phrase><phrase role="identifier">push</phrase><phrase role="special">(</phrase> <phrase role="number">2</phrase><phrase role="special">);</phrase> 7388 <phrase role="identifier">chan</phrase><phrase role="special">.</phrase><phrase role="identifier">push</phrase><phrase role="special">(</phrase> <phrase role="number">3</phrase><phrase role="special">);</phrase> 7389 <phrase role="identifier">chan</phrase><phrase role="special">.</phrase><phrase role="identifier">push</phrase><phrase role="special">(</phrase> <phrase role="number">5</phrase><phrase role="special">);</phrase> 7390 <phrase role="identifier">chan</phrase><phrase role="special">.</phrase><phrase role="identifier">push</phrase><phrase role="special">(</phrase> <phrase role="number">8</phrase><phrase role="special">);</phrase> 7391 <phrase role="identifier">chan</phrase><phrase role="special">.</phrase><phrase role="identifier">push</phrase><phrase role="special">(</phrase> <phrase role="number">12</phrase><phrase role="special">);</phrase> 7392 <phrase role="identifier">chan</phrase><phrase role="special">.</phrase><phrase role="identifier">close</phrase><phrase role="special">();</phrase> 7393<phrase role="special">}</phrase> 7394 7395<phrase role="keyword">void</phrase> <phrase role="identifier">bar</phrase><phrase role="special">(</phrase> <phrase role="identifier">channel_t</phrase> <phrase role="special">&</phrase> <phrase role="identifier">chan</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase> 7396 <phrase role="keyword">for</phrase> <phrase role="special">(</phrase> <phrase role="keyword">unsigned</phrase> <phrase role="keyword">int</phrase> <phrase role="identifier">value</phrase> <phrase role="special">:</phrase> <phrase role="identifier">chan</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase> 7397 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cout</phrase> <phrase role="special"><<</phrase> <phrase role="identifier">value</phrase> <phrase role="special"><<</phrase> <phrase role="string">" "</phrase><phrase role="special">;</phrase> 7398 <phrase role="special">}</phrase> 7399 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cout</phrase> <phrase role="special"><<</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">endl</phrase><phrase role="special">;</phrase> 7400<phrase role="special">}</phrase> 7401</programlisting> 7402 <para> 7403 <bridgehead renderas="sect4" id="class_buffered_channel_bridgehead"> 7404 <phrase id="class_buffered_channel"/> 7405 <link linkend="class_buffered_channel">Template 7406 <code>buffered_channel<></code></link> 7407</bridgehead> 7408 </para> 7409<programlisting><phrase role="preprocessor">#include</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">buffered_channel</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">></phrase> 7410 7411<phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase> 7412<phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase> 7413 7414<phrase role="keyword">template</phrase><phrase role="special"><</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">T</phrase> <phrase role="special">></phrase> 7415<phrase role="keyword">class</phrase> <phrase role="identifier">buffered_channel</phrase> <phrase role="special">{</phrase> 7416<phrase role="keyword">public</phrase><phrase role="special">:</phrase> 7417 <phrase role="keyword">typedef</phrase> <phrase role="identifier">T</phrase> <phrase role="identifier">value_type</phrase><phrase role="special">;</phrase> 7418 7419 <phrase role="keyword">class</phrase> <phrase role="identifier">iterator</phrase><phrase role="special">;</phrase> 7420 7421 <phrase role="keyword">explicit</phrase> <phrase role="identifier">buffered_channel</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">capacity</phrase><phrase role="special">);</phrase> 7422 7423 <phrase role="identifier">buffered_channel</phrase><phrase role="special">(</phrase> <phrase role="identifier">buffered_channel</phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="special">=</phrase> <phrase role="keyword">delete</phrase><phrase role="special">;</phrase> 7424 <phrase role="identifier">buffered_channel</phrase> <phrase role="special">&</phrase> <phrase role="keyword">operator</phrase><phrase role="special">=(</phrase> <phrase role="identifier">buffered_channel</phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="special">=</phrase> <phrase role="keyword">delete</phrase><phrase role="special">;</phrase> 7425 7426 <phrase role="keyword">void</phrase> <phrase role="identifier">close</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 7427 7428 <phrase role="identifier">channel_op_status</phrase> <phrase role="identifier">push</phrase><phrase role="special">(</phrase> <phrase role="identifier">value_type</phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">va</phrase><phrase role="special">);</phrase> 7429 <phrase role="identifier">channel_op_status</phrase> <phrase role="identifier">push</phrase><phrase role="special">(</phrase> <phrase role="identifier">value_type</phrase> <phrase role="special">&&</phrase> <phrase role="identifier">va</phrase><phrase role="special">);</phrase> 7430 <phrase role="keyword">template</phrase><phrase role="special"><</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Rep</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Period</phrase> <phrase role="special">></phrase> 7431 <phrase role="identifier">channel_op_status</phrase> <phrase role="identifier">push_wait_for</phrase><phrase role="special">(</phrase> 7432 <phrase role="identifier">value_type</phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">va</phrase><phrase role="special">,</phrase> 7433 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">duration</phrase><phrase role="special"><</phrase> <phrase role="identifier">Rep</phrase><phrase role="special">,</phrase> <phrase role="identifier">Period</phrase> <phrase role="special">></phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">timeout_duration</phrase><phrase role="special">);</phrase> 7434 <phrase role="identifier">channel_op_status</phrase> <phrase role="identifier">push_wait_for</phrase><phrase role="special">(</phrase> <phrase role="identifier">value_type</phrase> <phrase role="special">&&</phrase> <phrase role="identifier">va</phrase><phrase role="special">,</phrase> 7435 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">duration</phrase><phrase role="special"><</phrase> <phrase role="identifier">Rep</phrase><phrase role="special">,</phrase> <phrase role="identifier">Period</phrase> <phrase role="special">></phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">timeout_duration</phrase><phrase role="special">);</phrase> 7436 <phrase role="keyword">template</phrase><phrase role="special"><</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Clock</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Duration</phrase> <phrase role="special">></phrase> 7437 <phrase role="identifier">channel_op_status</phrase> <phrase role="identifier">push_wait_until</phrase><phrase role="special">(</phrase> 7438 <phrase role="identifier">value_type</phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">va</phrase><phrase role="special">,</phrase> 7439 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">time_point</phrase><phrase role="special"><</phrase> <phrase role="identifier">Clock</phrase><phrase role="special">,</phrase> <phrase role="identifier">Duration</phrase> <phrase role="special">></phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">timeout_time</phrase><phrase role="special">);</phrase> 7440 <phrase role="keyword">template</phrase><phrase role="special"><</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Clock</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Duration</phrase> <phrase role="special">></phrase> 7441 <phrase role="identifier">channel_op_status</phrase> <phrase role="identifier">push_wait_until</phrase><phrase role="special">(</phrase> 7442 <phrase role="identifier">value_type</phrase> <phrase role="special">&&</phrase> <phrase role="identifier">va</phrase><phrase role="special">,</phrase> 7443 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">time_point</phrase><phrase role="special"><</phrase> <phrase role="identifier">Clock</phrase><phrase role="special">,</phrase> <phrase role="identifier">Duration</phrase> <phrase role="special">></phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">timeout_time</phrase><phrase role="special">);</phrase> 7444 <phrase role="identifier">channel_op_status</phrase> <phrase role="identifier">try_push</phrase><phrase role="special">(</phrase> <phrase role="identifier">value_type</phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">va</phrase><phrase role="special">);</phrase> 7445 <phrase role="identifier">channel_op_status</phrase> <phrase role="identifier">try_push</phrase><phrase role="special">(</phrase> <phrase role="identifier">value_type</phrase> <phrase role="special">&&</phrase> <phrase role="identifier">va</phrase><phrase role="special">);</phrase> 7446 7447 <phrase role="identifier">channel_op_status</phrase> <phrase role="identifier">pop</phrase><phrase role="special">(</phrase> <phrase role="identifier">value_type</phrase> <phrase role="special">&</phrase> <phrase role="identifier">va</phrase><phrase role="special">);</phrase> 7448 <phrase role="identifier">value_type</phrase> <phrase role="identifier">value_pop</phrase><phrase role="special">();</phrase> 7449 <phrase role="keyword">template</phrase><phrase role="special"><</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Rep</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Period</phrase> <phrase role="special">></phrase> 7450 <phrase role="identifier">channel_op_status</phrase> <phrase role="identifier">pop_wait_for</phrase><phrase role="special">(</phrase> 7451 <phrase role="identifier">value_type</phrase> <phrase role="special">&</phrase> <phrase role="identifier">va</phrase><phrase role="special">,</phrase> 7452 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">duration</phrase><phrase role="special"><</phrase> <phrase role="identifier">Rep</phrase><phrase role="special">,</phrase> <phrase role="identifier">Period</phrase> <phrase role="special">></phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">timeout_duration</phrase><phrase role="special">);</phrase> 7453 <phrase role="keyword">template</phrase><phrase role="special"><</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Clock</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Duration</phrase> <phrase role="special">></phrase> 7454 <phrase role="identifier">channel_op_status</phrase> <phrase role="identifier">pop_wait_until</phrase><phrase role="special">(</phrase> 7455 <phrase role="identifier">value_type</phrase> <phrase role="special">&</phrase> <phrase role="identifier">va</phrase><phrase role="special">,</phrase> 7456 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">time_point</phrase><phrase role="special"><</phrase> <phrase role="identifier">Clock</phrase><phrase role="special">,</phrase> <phrase role="identifier">Duration</phrase> <phrase role="special">></phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">timeout_time</phrase><phrase role="special">);</phrase> 7457 <phrase role="identifier">channel_op_status</phrase> <phrase role="identifier">try_pop</phrase><phrase role="special">(</phrase> <phrase role="identifier">value_type</phrase> <phrase role="special">&</phrase> <phrase role="identifier">va</phrase><phrase role="special">);</phrase> 7458<phrase role="special">};</phrase> 7459 7460<phrase role="keyword">template</phrase><phrase role="special"><</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">T</phrase> <phrase role="special">></phrase> 7461<phrase role="identifier">buffered_channel</phrase><phrase role="special"><</phrase> <phrase role="identifier">T</phrase> <phrase role="special">>::</phrase><phrase role="identifier">iterator</phrase> <phrase role="identifier">begin</phrase><phrase role="special">(</phrase> <phrase role="identifier">buffered_channel</phrase><phrase role="special"><</phrase> <phrase role="identifier">T</phrase> <phrase role="special">></phrase> <phrase role="special">&</phrase> <phrase role="identifier">chan</phrase><phrase role="special">);</phrase> 7462 7463<phrase role="keyword">template</phrase><phrase role="special"><</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">T</phrase> <phrase role="special">></phrase> 7464<phrase role="identifier">buffered_channel</phrase><phrase role="special"><</phrase> <phrase role="identifier">T</phrase> <phrase role="special">>::</phrase><phrase role="identifier">iterator</phrase> <phrase role="identifier">end</phrase><phrase role="special">(</phrase> <phrase role="identifier">buffered_channel</phrase><phrase role="special"><</phrase> <phrase role="identifier">T</phrase> <phrase role="special">></phrase> <phrase role="special">&</phrase> <phrase role="identifier">chan</phrase><phrase role="special">);</phrase> 7465 7466<phrase role="special">}}</phrase> 7467</programlisting> 7468 <bridgehead renderas="sect5" id="fiber.synchronization.channels.buffered_channel.h0"> 7469 <phrase id="fiber.synchronization.channels.buffered_channel.constructor"/><link 7470 linkend="fiber.synchronization.channels.buffered_channel.constructor">Constructor</link> 7471 </bridgehead> 7472<programlisting><phrase role="keyword">explicit</phrase> <phrase role="identifier">buffered_channel</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">capacity</phrase><phrase role="special">);</phrase> 7473</programlisting> 7474 <variablelist> 7475 <title></title> 7476 <varlistentry> 7477 <term>Preconditions:</term> 7478 <listitem> 7479 <para> 7480 <code><phrase role="number">2</phrase><phrase role="special"><=</phrase><phrase 7481 role="identifier">capacity</phrase> <phrase role="special">&&</phrase> 7482 <phrase role="number">0</phrase><phrase role="special">==(</phrase><phrase 7483 role="identifier">capacity</phrase> <phrase role="special">&</phrase> 7484 <phrase role="special">(</phrase><phrase role="identifier">capacity</phrase><phrase 7485 role="special">-</phrase><phrase role="number">1</phrase><phrase 7486 role="special">))</phrase></code> 7487 </para> 7488 </listitem> 7489 </varlistentry> 7490 <varlistentry> 7491 <term>Effects:</term> 7492 <listitem> 7493 <para> 7494 The constructor constructs an object of class <code><phrase role="identifier">buffered_channel</phrase></code> 7495 with an internal buffer of size <code><phrase role="identifier">capacity</phrase></code>. 7496 </para> 7497 </listitem> 7498 </varlistentry> 7499 <varlistentry> 7500 <term>Throws:</term> 7501 <listitem> 7502 <para> 7503 <code><phrase role="identifier">fiber_error</phrase></code> 7504 </para> 7505 </listitem> 7506 </varlistentry> 7507 <varlistentry> 7508 <term>Error Conditions:</term> 7509 <listitem> 7510 <para> 7511 <emphasis role="bold">invalid_argument</emphasis>: if <code><phrase 7512 role="number">0</phrase><phrase role="special">==</phrase><phrase 7513 role="identifier">capacity</phrase> <phrase role="special">||</phrase> 7514 <phrase role="number">0</phrase><phrase role="special">!=(</phrase><phrase 7515 role="identifier">capacity</phrase> <phrase role="special">&</phrase> 7516 <phrase role="special">(</phrase><phrase role="identifier">capacity</phrase><phrase 7517 role="special">-</phrase><phrase role="number">1</phrase><phrase 7518 role="special">))</phrase></code>. 7519 </para> 7520 </listitem> 7521 </varlistentry> 7522 <varlistentry> 7523 <term>Notes:</term> 7524 <listitem> 7525 <para> 7526 A <code><phrase role="identifier">push</phrase><phrase role="special">()</phrase></code>, 7527 <code><phrase role="identifier">push_wait_for</phrase><phrase role="special">()</phrase></code> 7528 or <code><phrase role="identifier">push_wait_until</phrase><phrase 7529 role="special">()</phrase></code> will not block until the number 7530 of values in the channel becomes equal to <code><phrase role="identifier">capacity</phrase></code>. 7531 The channel can hold only <code><phrase role="identifier">capacity</phrase> 7532 <phrase role="special">-</phrase> <phrase role="number">1</phrase></code> 7533 elements, otherwise it is considered to be full. 7534 </para> 7535 </listitem> 7536 </varlistentry> 7537 </variablelist> 7538 <para> 7539 <bridgehead renderas="sect4" id="buffered_channel_close_bridgehead"> 7540 <phrase id="buffered_channel_close"/> 7541 <link linkend="buffered_channel_close">Member 7542 function <code>close</code>()</link> 7543</bridgehead> 7544 </para> 7545<programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">close</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 7546</programlisting> 7547 <variablelist> 7548 <title></title> 7549 <varlistentry> 7550 <term>Effects:</term> 7551 <listitem> 7552 <para> 7553 Deactivates the channel. No values can be put after calling <code><phrase 7554 role="keyword">this</phrase><phrase role="special">-></phrase><phrase 7555 role="identifier">close</phrase><phrase role="special">()</phrase></code>. 7556 Fibers blocked in <code><phrase role="keyword">this</phrase><phrase 7557 role="special">-></phrase><phrase role="identifier">pop</phrase><phrase 7558 role="special">()</phrase></code>, <code><phrase role="keyword">this</phrase><phrase 7559 role="special">-></phrase><phrase role="identifier">pop_wait_for</phrase><phrase 7560 role="special">()</phrase></code> or <code><phrase role="keyword">this</phrase><phrase 7561 role="special">-></phrase><phrase role="identifier">pop_wait_until</phrase><phrase 7562 role="special">()</phrase></code> will return <code><phrase role="identifier">closed</phrase></code>. 7563 Fibers blocked in <code><phrase role="keyword">this</phrase><phrase 7564 role="special">-></phrase><phrase role="identifier">value_pop</phrase><phrase 7565 role="special">()</phrase></code> will receive an exception. 7566 </para> 7567 </listitem> 7568 </varlistentry> 7569 <varlistentry> 7570 <term>Throws:</term> 7571 <listitem> 7572 <para> 7573 Nothing. 7574 </para> 7575 </listitem> 7576 </varlistentry> 7577 <varlistentry> 7578 <term>Note:</term> 7579 <listitem> 7580 <para> 7581 <code><phrase role="identifier">close</phrase><phrase role="special">()</phrase></code> 7582 is like closing a pipe. It informs waiting consumers that no more 7583 values will arrive. 7584 </para> 7585 </listitem> 7586 </varlistentry> 7587 </variablelist> 7588 <para> 7589 <bridgehead renderas="sect4" id="buffered_channel_push_bridgehead"> 7590 <phrase id="buffered_channel_push"/> 7591 <link linkend="buffered_channel_push">Member 7592 function <code>push</code>()</link> 7593</bridgehead> 7594 </para> 7595<programlisting><phrase role="identifier">channel_op_status</phrase> <phrase role="identifier">push</phrase><phrase role="special">(</phrase> <phrase role="identifier">value_type</phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">va</phrase><phrase role="special">);</phrase> 7596<phrase role="identifier">channel_op_status</phrase> <phrase role="identifier">push</phrase><phrase role="special">(</phrase> <phrase role="identifier">value_type</phrase> <phrase role="special">&&</phrase> <phrase role="identifier">va</phrase><phrase role="special">);</phrase> 7597</programlisting> 7598 <variablelist> 7599 <title></title> 7600 <varlistentry> 7601 <term>Effects:</term> 7602 <listitem> 7603 <para> 7604 If channel is closed, returns <code><phrase role="identifier">closed</phrase></code>. 7605 Otherwise enqueues the value in the channel, wakes up a fiber blocked 7606 on <code><phrase role="keyword">this</phrase><phrase role="special">-></phrase><phrase 7607 role="identifier">pop</phrase><phrase role="special">()</phrase></code>, 7608 <code><phrase role="keyword">this</phrase><phrase role="special">-></phrase><phrase 7609 role="identifier">value_pop</phrase><phrase role="special">()</phrase></code>, 7610 <code><phrase role="keyword">this</phrase><phrase role="special">-></phrase><phrase 7611 role="identifier">pop_wait_for</phrase><phrase role="special">()</phrase></code> 7612 or <code><phrase role="keyword">this</phrase><phrase role="special">-></phrase><phrase 7613 role="identifier">pop_wait_until</phrase><phrase role="special">()</phrase></code> 7614 and returns <code><phrase role="identifier">success</phrase></code>. 7615 If the channel is full, the fiber is blocked. 7616 </para> 7617 </listitem> 7618 </varlistentry> 7619 <varlistentry> 7620 <term>Throws:</term> 7621 <listitem> 7622 <para> 7623 Exceptions thrown by copy- or move-operations. 7624 </para> 7625 </listitem> 7626 </varlistentry> 7627 </variablelist> 7628 <para> 7629 <bridgehead renderas="sect4" id="buffered_channel_try_push_bridgehead"> 7630 <phrase id="buffered_channel_try_push"/> 7631 <link linkend="buffered_channel_try_push">Member 7632 function <code>try_push</code>()</link> 7633</bridgehead> 7634 </para> 7635<programlisting><phrase role="identifier">channel_op_status</phrase> <phrase role="identifier">try_push</phrase><phrase role="special">(</phrase> <phrase role="identifier">value_type</phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">va</phrase><phrase role="special">);</phrase> 7636<phrase role="identifier">channel_op_status</phrase> <phrase role="identifier">try_push</phrase><phrase role="special">(</phrase> <phrase role="identifier">value_type</phrase> <phrase role="special">&&</phrase> <phrase role="identifier">va</phrase><phrase role="special">);</phrase> 7637</programlisting> 7638 <variablelist> 7639 <title></title> 7640 <varlistentry> 7641 <term>Effects:</term> 7642 <listitem> 7643 <para> 7644 If channel is closed, returns <code><phrase role="identifier">closed</phrase></code>. 7645 Otherwise enqueues the value in the channel, wakes up a fiber blocked 7646 on <code><phrase role="keyword">this</phrase><phrase role="special">-></phrase><phrase 7647 role="identifier">pop</phrase><phrase role="special">()</phrase></code>, 7648 <code><phrase role="keyword">this</phrase><phrase role="special">-></phrase><phrase 7649 role="identifier">value_pop</phrase><phrase role="special">()</phrase></code>, 7650 <code><phrase role="keyword">this</phrase><phrase role="special">-></phrase><phrase 7651 role="identifier">pop_wait_for</phrase><phrase role="special">()</phrase></code> 7652 or <code><phrase role="keyword">this</phrase><phrase role="special">-></phrase><phrase 7653 role="identifier">pop_wait_until</phrase><phrase role="special">()</phrase></code> 7654 and returns <code><phrase role="identifier">success</phrase></code>. 7655 If the channel is full, it doesn't block and returns <code><phrase 7656 role="identifier">full</phrase></code>. 7657 </para> 7658 </listitem> 7659 </varlistentry> 7660 <varlistentry> 7661 <term>Throws:</term> 7662 <listitem> 7663 <para> 7664 Exceptions thrown by copy- or move-operations. 7665 </para> 7666 </listitem> 7667 </varlistentry> 7668 </variablelist> 7669 <para> 7670 <bridgehead renderas="sect4" id="buffered_channel_pop_bridgehead"> 7671 <phrase id="buffered_channel_pop"/> 7672 <link linkend="buffered_channel_pop">Member 7673 function <code>pop</code>()</link> 7674</bridgehead> 7675 </para> 7676<programlisting><phrase role="identifier">channel_op_status</phrase> <phrase role="identifier">pop</phrase><phrase role="special">(</phrase> <phrase role="identifier">value_type</phrase> <phrase role="special">&</phrase> <phrase role="identifier">va</phrase><phrase role="special">);</phrase> 7677</programlisting> 7678 <variablelist> 7679 <title></title> 7680 <varlistentry> 7681 <term>Effects:</term> 7682 <listitem> 7683 <para> 7684 Dequeues a value from the channel. If the channel is empty, the fiber 7685 gets suspended until at least one new item is <code><phrase role="identifier">push</phrase><phrase 7686 role="special">()</phrase></code>ed (return value <code><phrase role="identifier">success</phrase></code> 7687 and <code><phrase role="identifier">va</phrase></code> contains dequeued 7688 value) or the channel gets <code><phrase role="identifier">close</phrase><phrase 7689 role="special">()</phrase></code>d (return value <code><phrase role="identifier">closed</phrase></code>). 7690 </para> 7691 </listitem> 7692 </varlistentry> 7693 <varlistentry> 7694 <term>Throws:</term> 7695 <listitem> 7696 <para> 7697 Exceptions thrown by copy- or move-operations. 7698 </para> 7699 </listitem> 7700 </varlistentry> 7701 </variablelist> 7702 <para> 7703 <bridgehead renderas="sect4" id="buffered_channel_value_pop_bridgehead"> 7704 <phrase id="buffered_channel_value_pop"/> 7705 <link linkend="buffered_channel_value_pop">Member 7706 function <code>value_pop</code>()</link> 7707</bridgehead> 7708 </para> 7709<programlisting><phrase role="identifier">value_type</phrase> <phrase role="identifier">value_pop</phrase><phrase role="special">();</phrase> 7710</programlisting> 7711 <variablelist> 7712 <title></title> 7713 <varlistentry> 7714 <term>Effects:</term> 7715 <listitem> 7716 <para> 7717 Dequeues a value from the channel. If the channel is empty, the fiber 7718 gets suspended until at least one new item is <code><phrase role="identifier">push</phrase><phrase 7719 role="special">()</phrase></code>ed or the channel gets <code><phrase 7720 role="identifier">close</phrase><phrase role="special">()</phrase></code>d 7721 (which throws an exception). 7722 </para> 7723 </listitem> 7724 </varlistentry> 7725 <varlistentry> 7726 <term>Throws:</term> 7727 <listitem> 7728 <para> 7729 <code><phrase role="identifier">fiber_error</phrase></code> if <code><phrase 7730 role="special">*</phrase><phrase role="keyword">this</phrase></code> 7731 is closed or by copy- or move-operations. 7732 </para> 7733 </listitem> 7734 </varlistentry> 7735 <varlistentry> 7736 <term>Error conditions:</term> 7737 <listitem> 7738 <para> 7739 <code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase 7740 role="identifier">errc</phrase><phrase role="special">::</phrase><phrase 7741 role="identifier">operation_not_permitted</phrase></code> 7742 </para> 7743 </listitem> 7744 </varlistentry> 7745 </variablelist> 7746 <para> 7747 <bridgehead renderas="sect4" id="buffered_channel_try_pop_bridgehead"> 7748 <phrase id="buffered_channel_try_pop"/> 7749 <link linkend="buffered_channel_try_pop">Member 7750 function <code>try_pop</code>()</link> 7751</bridgehead> 7752 </para> 7753<programlisting><phrase role="identifier">channel_op_status</phrase> <phrase role="identifier">try_pop</phrase><phrase role="special">(</phrase> <phrase role="identifier">value_type</phrase> <phrase role="special">&</phrase> <phrase role="identifier">va</phrase><phrase role="special">);</phrase> 7754</programlisting> 7755 <variablelist> 7756 <title></title> 7757 <varlistentry> 7758 <term>Effects:</term> 7759 <listitem> 7760 <para> 7761 If channel is empty, returns <code><phrase role="identifier">empty</phrase></code>. 7762 If channel is closed, returns <code><phrase role="identifier">closed</phrase></code>. 7763 Otherwise it returns <code><phrase role="identifier">success</phrase></code> 7764 and <code><phrase role="identifier">va</phrase></code> contains the 7765 dequeued value. 7766 </para> 7767 </listitem> 7768 </varlistentry> 7769 <varlistentry> 7770 <term>Throws:</term> 7771 <listitem> 7772 <para> 7773 Exceptions thrown by copy- or move-operations. 7774 </para> 7775 </listitem> 7776 </varlistentry> 7777 </variablelist> 7778 <para> 7779 <bridgehead renderas="sect4" id="buffered_channel_pop_wait_for_bridgehead"> 7780 <phrase id="buffered_channel_pop_wait_for"/> 7781 <link linkend="buffered_channel_pop_wait_for">Member 7782 function <code>pop_wait_for</code>()</link> 7783</bridgehead> 7784 </para> 7785<programlisting><phrase role="keyword">template</phrase><phrase role="special"><</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Rep</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Period</phrase> <phrase role="special">></phrase> 7786<phrase role="identifier">channel_op_status</phrase> <phrase role="identifier">pop_wait_for</phrase><phrase role="special">(</phrase> 7787 <phrase role="identifier">value_type</phrase> <phrase role="special">&</phrase> <phrase role="identifier">va</phrase><phrase role="special">,</phrase> 7788 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">duration</phrase><phrase role="special"><</phrase> <phrase role="identifier">Rep</phrase><phrase role="special">,</phrase> <phrase role="identifier">Period</phrase> <phrase role="special">></phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">timeout_duration</phrase><phrase role="special">)</phrase> 7789</programlisting> 7790 <variablelist> 7791 <title></title> 7792 <varlistentry> 7793 <term>Effects:</term> 7794 <listitem> 7795 <para> 7796 Accepts <code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase 7797 role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase 7798 role="identifier">duration</phrase></code> and internally computes 7799 a timeout time as (system time + <code><phrase role="identifier">timeout_duration</phrase></code>). 7800 If channel is not empty, immediately dequeues a value from the channel. 7801 Otherwise the fiber gets suspended until at least one new item is 7802 <code><phrase role="identifier">push</phrase><phrase role="special">()</phrase></code>ed 7803 (return value <code><phrase role="identifier">success</phrase></code> 7804 and <code><phrase role="identifier">va</phrase></code> contains dequeued 7805 value), or the channel gets <code><phrase role="identifier">close</phrase><phrase 7806 role="special">()</phrase></code>d (return value <code><phrase role="identifier">closed</phrase></code>), 7807 or the system time reaches the computed timeout time (return value 7808 <code><phrase role="identifier">timeout</phrase></code>). 7809 </para> 7810 </listitem> 7811 </varlistentry> 7812 <varlistentry> 7813 <term>Throws:</term> 7814 <listitem> 7815 <para> 7816 timeout-related exceptions or by copy- or move-operations. 7817 </para> 7818 </listitem> 7819 </varlistentry> 7820 </variablelist> 7821 <para> 7822 <bridgehead renderas="sect4" id="buffered_channel_pop_wait_until_bridgehead"> 7823 <phrase id="buffered_channel_pop_wait_until"/> 7824 <link linkend="buffered_channel_pop_wait_until">Member 7825 function <code>pop_wait_until</code>()</link> 7826</bridgehead> 7827 </para> 7828<programlisting><phrase role="keyword">template</phrase><phrase role="special"><</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Clock</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Duration</phrase> <phrase role="special">></phrase> 7829<phrase role="identifier">channel_op_status</phrase> <phrase role="identifier">pop_wait_until</phrase><phrase role="special">(</phrase> 7830 <phrase role="identifier">value_type</phrase> <phrase role="special">&</phrase> <phrase role="identifier">va</phrase><phrase role="special">,</phrase> 7831 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">time_point</phrase><phrase role="special"><</phrase> <phrase role="identifier">Clock</phrase><phrase role="special">,</phrase> <phrase role="identifier">Duration</phrase> <phrase role="special">></phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">timeout_time</phrase><phrase role="special">)</phrase> 7832</programlisting> 7833 <variablelist> 7834 <title></title> 7835 <varlistentry> 7836 <term>Effects:</term> 7837 <listitem> 7838 <para> 7839 Accepts a <code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase 7840 role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase 7841 role="identifier">time_point</phrase><phrase role="special"><</phrase> 7842 <phrase role="identifier">Clock</phrase><phrase role="special">,</phrase> 7843 <phrase role="identifier">Duration</phrase> <phrase role="special">></phrase></code>. 7844 If channel is not empty, immediately dequeues a value from the channel. 7845 Otherwise the fiber gets suspended until at least one new item is 7846 <code><phrase role="identifier">push</phrase><phrase role="special">()</phrase></code>ed 7847 (return value <code><phrase role="identifier">success</phrase></code> 7848 and <code><phrase role="identifier">va</phrase></code> contains dequeued 7849 value), or the channel gets <code><phrase role="identifier">close</phrase><phrase 7850 role="special">()</phrase></code>d (return value <code><phrase role="identifier">closed</phrase></code>), 7851 or the system time reaches the passed <code><phrase role="identifier">time_point</phrase></code> 7852 (return value <code><phrase role="identifier">timeout</phrase></code>). 7853 </para> 7854 </listitem> 7855 </varlistentry> 7856 <varlistentry> 7857 <term>Throws:</term> 7858 <listitem> 7859 <para> 7860 timeout-related exceptions or by copy- or move-operations. 7861 </para> 7862 </listitem> 7863 </varlistentry> 7864 </variablelist> 7865 <bridgehead renderas="sect5" id="fiber.synchronization.channels.buffered_channel.h1"> 7866 <phrase id="fiber.synchronization.channels.buffered_channel.non_member_function__code__phrase_role__identifier__begin__phrase__phrase_role__special_____phrase___phrase_role__identifier__buffered_channel__phrase__phrase_role__special___lt___phrase___phrase_role__identifier__t__phrase___phrase_role__special___gt___phrase___phrase_role__special___amp____phrase___code_"/><link 7867 linkend="fiber.synchronization.channels.buffered_channel.non_member_function__code__phrase_role__identifier__begin__phrase__phrase_role__special_____phrase___phrase_role__identifier__buffered_channel__phrase__phrase_role__special___lt___phrase___phrase_role__identifier__t__phrase___phrase_role__special___gt___phrase___phrase_role__special___amp____phrase___code_">Non-member 7868 function <code><phrase role="identifier">begin</phrase><phrase role="special">(</phrase> 7869 <phrase role="identifier">buffered_channel</phrase><phrase role="special"><</phrase> 7870 <phrase role="identifier">T</phrase> <phrase role="special">></phrase> 7871 <phrase role="special">&)</phrase></code></link> 7872 </bridgehead> 7873<programlisting><phrase role="keyword">template</phrase><phrase role="special"><</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">T</phrase> <phrase role="special">></phrase> 7874<phrase role="identifier">buffered_channel</phrase><phrase role="special"><</phrase> <phrase role="identifier">T</phrase> <phrase role="special">>::</phrase><phrase role="identifier">iterator</phrase> <phrase role="identifier">begin</phrase><phrase role="special">(</phrase> <phrase role="identifier">buffered_channel</phrase><phrase role="special"><</phrase> <phrase role="identifier">T</phrase> <phrase role="special">></phrase> <phrase role="special">&);</phrase> 7875</programlisting> 7876 <variablelist> 7877 <title></title> 7878 <varlistentry> 7879 <term>Returns:</term> 7880 <listitem> 7881 <para> 7882 Returns a range-iterator (input-iterator). 7883 </para> 7884 </listitem> 7885 </varlistentry> 7886 </variablelist> 7887 <bridgehead renderas="sect5" id="fiber.synchronization.channels.buffered_channel.h2"> 7888 <phrase id="fiber.synchronization.channels.buffered_channel.non_member_function__code__phrase_role__identifier__end__phrase__phrase_role__special_____phrase___phrase_role__identifier__buffered_channel__phrase__phrase_role__special___lt___phrase___phrase_role__identifier__t__phrase___phrase_role__special___gt___phrase___phrase_role__special___amp____phrase___code_"/><link 7889 linkend="fiber.synchronization.channels.buffered_channel.non_member_function__code__phrase_role__identifier__end__phrase__phrase_role__special_____phrase___phrase_role__identifier__buffered_channel__phrase__phrase_role__special___lt___phrase___phrase_role__identifier__t__phrase___phrase_role__special___gt___phrase___phrase_role__special___amp____phrase___code_">Non-member 7890 function <code><phrase role="identifier">end</phrase><phrase role="special">(</phrase> 7891 <phrase role="identifier">buffered_channel</phrase><phrase role="special"><</phrase> 7892 <phrase role="identifier">T</phrase> <phrase role="special">></phrase> 7893 <phrase role="special">&)</phrase></code></link> 7894 </bridgehead> 7895<programlisting><phrase role="keyword">template</phrase><phrase role="special"><</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">T</phrase> <phrase role="special">></phrase> 7896<phrase role="identifier">buffered_channel</phrase><phrase role="special"><</phrase> <phrase role="identifier">R</phrase> <phrase role="special">>::</phrase><phrase role="identifier">iterator</phrase> <phrase role="identifier">end</phrase><phrase role="special">(</phrase> <phrase role="identifier">buffered_channel</phrase><phrase role="special"><</phrase> <phrase role="identifier">T</phrase> <phrase role="special">></phrase> <phrase role="special">&);</phrase> 7897</programlisting> 7898 <variablelist> 7899 <title></title> 7900 <varlistentry> 7901 <term>Returns:</term> 7902 <listitem> 7903 <para> 7904 Returns an end range-iterator (input-iterator). 7905 </para> 7906 </listitem> 7907 </varlistentry> 7908 </variablelist> 7909 </section> 7910 <section id="fiber.synchronization.channels.unbuffered_channel"> 7911 <title><link linkend="fiber.synchronization.channels.unbuffered_channel">Unbuffered 7912 Channel</link></title> 7913 <para> 7914 <emphasis role="bold">Boost.Fiber</emphasis> provides template <code><phrase 7915 role="identifier">unbuffered_channel</phrase></code> suitable to synchonize 7916 fibers (running on same or different threads) via synchronous message passing. 7917 A fiber waiting to consume an value will block until the value is produced. 7918 If a fiber attempts to send a value through an unbuffered channel and no 7919 fiber is waiting to receive the value, the channel will block the sending 7920 fiber. 7921 </para> 7922 <para> 7923 The unbuffered channel acts as an <code><phrase role="identifier">rendezvous</phrase> 7924 <phrase role="identifier">point</phrase></code>. 7925 </para> 7926<programlisting><phrase role="keyword">typedef</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">unbuffered_channel</phrase><phrase role="special"><</phrase> <phrase role="keyword">int</phrase> <phrase role="special">></phrase> <phrase role="identifier">channel_t</phrase><phrase role="special">;</phrase> 7927 7928<phrase role="keyword">void</phrase> <phrase role="identifier">send</phrase><phrase role="special">(</phrase> <phrase role="identifier">channel_t</phrase> <phrase role="special">&</phrase> <phrase role="identifier">chan</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase> 7929 <phrase role="keyword">for</phrase> <phrase role="special">(</phrase> <phrase role="keyword">int</phrase> <phrase role="identifier">i</phrase> <phrase role="special">=</phrase> <phrase role="number">0</phrase><phrase role="special">;</phrase> <phrase role="identifier">i</phrase> <phrase role="special"><</phrase> <phrase role="number">5</phrase><phrase role="special">;</phrase> <phrase role="special">++</phrase><phrase role="identifier">i</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase> 7930 <phrase role="identifier">chan</phrase><phrase role="special">.</phrase><phrase role="identifier">push</phrase><phrase role="special">(</phrase> <phrase role="identifier">i</phrase><phrase role="special">);</phrase> 7931 <phrase role="special">}</phrase> 7932 <phrase role="identifier">chan</phrase><phrase role="special">.</phrase><phrase role="identifier">close</phrase><phrase role="special">();</phrase> 7933<phrase role="special">}</phrase> 7934 7935<phrase role="keyword">void</phrase> <phrase role="identifier">recv</phrase><phrase role="special">(</phrase> <phrase role="identifier">channel_t</phrase> <phrase role="special">&</phrase> <phrase role="identifier">chan</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase> 7936 <phrase role="keyword">int</phrase> <phrase role="identifier">i</phrase><phrase role="special">;</phrase> 7937 <phrase role="keyword">while</phrase> <phrase role="special">(</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">channel_op_status</phrase><phrase role="special">::</phrase><phrase role="identifier">success</phrase> <phrase role="special">==</phrase> <phrase role="identifier">chan</phrase><phrase role="special">.</phrase><phrase role="identifier">pop</phrase><phrase role="special">(</phrase><phrase role="identifier">i</phrase><phrase role="special">)</phrase> <phrase role="special">)</phrase> <phrase role="special">{</phrase> 7938 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cout</phrase> <phrase role="special"><<</phrase> <phrase role="string">"received "</phrase> <phrase role="special"><<</phrase> <phrase role="identifier">i</phrase> <phrase role="special"><<</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">endl</phrase><phrase role="special">;</phrase> 7939 <phrase role="special">}</phrase> 7940<phrase role="special">}</phrase> 7941 7942<phrase role="identifier">channel_t</phrase> <phrase role="identifier">chan</phrase><phrase role="special">{</phrase> <phrase role="number">1</phrase> <phrase role="special">};</phrase> 7943<phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">fiber</phrase> <phrase role="identifier">f1</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">bind</phrase><phrase role="special">(</phrase> <phrase role="identifier">send</phrase><phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">ref</phrase><phrase role="special">(</phrase> <phrase role="identifier">chan</phrase><phrase role="special">)</phrase> <phrase role="special">)</phrase> <phrase role="special">);</phrase> 7944<phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">fiber</phrase> <phrase role="identifier">f2</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">bind</phrase><phrase role="special">(</phrase> <phrase role="identifier">recv</phrase><phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">ref</phrase><phrase role="special">(</phrase> <phrase role="identifier">chan</phrase><phrase role="special">)</phrase> <phrase role="special">)</phrase> <phrase role="special">);</phrase> 7945 7946<phrase role="identifier">f1</phrase><phrase role="special">.</phrase><phrase role="identifier">join</phrase><phrase role="special">();</phrase> 7947<phrase role="identifier">f2</phrase><phrase role="special">.</phrase><phrase role="identifier">join</phrase><phrase role="special">();</phrase> 7948</programlisting> 7949 <para> 7950 Range-for syntax is supported: 7951 </para> 7952<programlisting><phrase role="keyword">typedef</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">unbuffered_channel</phrase><phrase role="special"><</phrase> <phrase role="keyword">int</phrase> <phrase role="special">></phrase> <phrase role="identifier">channel_t</phrase><phrase role="special">;</phrase> 7953 7954<phrase role="keyword">void</phrase> <phrase role="identifier">foo</phrase><phrase role="special">(</phrase> <phrase role="identifier">channel_t</phrase> <phrase role="special">&</phrase> <phrase role="identifier">chan</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase> 7955 <phrase role="identifier">chan</phrase><phrase role="special">.</phrase><phrase role="identifier">push</phrase><phrase role="special">(</phrase> <phrase role="number">1</phrase><phrase role="special">);</phrase> 7956 <phrase role="identifier">chan</phrase><phrase role="special">.</phrase><phrase role="identifier">push</phrase><phrase role="special">(</phrase> <phrase role="number">1</phrase><phrase role="special">);</phrase> 7957 <phrase role="identifier">chan</phrase><phrase role="special">.</phrase><phrase role="identifier">push</phrase><phrase role="special">(</phrase> <phrase role="number">2</phrase><phrase role="special">);</phrase> 7958 <phrase role="identifier">chan</phrase><phrase role="special">.</phrase><phrase role="identifier">push</phrase><phrase role="special">(</phrase> <phrase role="number">3</phrase><phrase role="special">);</phrase> 7959 <phrase role="identifier">chan</phrase><phrase role="special">.</phrase><phrase role="identifier">push</phrase><phrase role="special">(</phrase> <phrase role="number">5</phrase><phrase role="special">);</phrase> 7960 <phrase role="identifier">chan</phrase><phrase role="special">.</phrase><phrase role="identifier">push</phrase><phrase role="special">(</phrase> <phrase role="number">8</phrase><phrase role="special">);</phrase> 7961 <phrase role="identifier">chan</phrase><phrase role="special">.</phrase><phrase role="identifier">push</phrase><phrase role="special">(</phrase> <phrase role="number">12</phrase><phrase role="special">);</phrase> 7962 <phrase role="identifier">chan</phrase><phrase role="special">.</phrase><phrase role="identifier">close</phrase><phrase role="special">();</phrase> 7963<phrase role="special">}</phrase> 7964 7965<phrase role="keyword">void</phrase> <phrase role="identifier">bar</phrase><phrase role="special">(</phrase> <phrase role="identifier">channel_t</phrase> <phrase role="special">&</phrase> <phrase role="identifier">chan</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase> 7966 <phrase role="keyword">for</phrase> <phrase role="special">(</phrase> <phrase role="keyword">unsigned</phrase> <phrase role="keyword">int</phrase> <phrase role="identifier">value</phrase> <phrase role="special">:</phrase> <phrase role="identifier">chan</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase> 7967 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cout</phrase> <phrase role="special"><<</phrase> <phrase role="identifier">value</phrase> <phrase role="special"><<</phrase> <phrase role="string">" "</phrase><phrase role="special">;</phrase> 7968 <phrase role="special">}</phrase> 7969 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cout</phrase> <phrase role="special"><<</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">endl</phrase><phrase role="special">;</phrase> 7970<phrase role="special">}</phrase> 7971</programlisting> 7972 <para> 7973 <bridgehead renderas="sect4" id="class_unbuffered_channel_bridgehead"> 7974 <phrase id="class_unbuffered_channel"/> 7975 <link linkend="class_unbuffered_channel">Template 7976 <code>unbuffered_channel<></code></link> 7977</bridgehead> 7978 </para> 7979<programlisting><phrase role="preprocessor">#include</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">unbuffered_channel</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">></phrase> 7980 7981<phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase> 7982<phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase> 7983 7984<phrase role="keyword">template</phrase><phrase role="special"><</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">T</phrase> <phrase role="special">></phrase> 7985<phrase role="keyword">class</phrase> <phrase role="identifier">unbuffered_channel</phrase> <phrase role="special">{</phrase> 7986<phrase role="keyword">public</phrase><phrase role="special">:</phrase> 7987 <phrase role="keyword">typedef</phrase> <phrase role="identifier">T</phrase> <phrase role="identifier">value_type</phrase><phrase role="special">;</phrase> 7988 7989 <phrase role="keyword">class</phrase> <phrase role="identifier">iterator</phrase><phrase role="special">;</phrase> 7990 7991 <phrase role="identifier">unbuffered_channel</phrase><phrase role="special">();</phrase> 7992 7993 <phrase role="identifier">unbuffered_channel</phrase><phrase role="special">(</phrase> <phrase role="identifier">unbuffered_channel</phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="special">=</phrase> <phrase role="keyword">delete</phrase><phrase role="special">;</phrase> 7994 <phrase role="identifier">unbuffered_channel</phrase> <phrase role="special">&</phrase> <phrase role="keyword">operator</phrase><phrase role="special">=(</phrase> <phrase role="identifier">unbuffered_channel</phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="special">=</phrase> <phrase role="keyword">delete</phrase><phrase role="special">;</phrase> 7995 7996 <phrase role="keyword">void</phrase> <phrase role="identifier">close</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 7997 7998 <phrase role="identifier">channel_op_status</phrase> <phrase role="identifier">push</phrase><phrase role="special">(</phrase> <phrase role="identifier">value_type</phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">va</phrase><phrase role="special">);</phrase> 7999 <phrase role="identifier">channel_op_status</phrase> <phrase role="identifier">push</phrase><phrase role="special">(</phrase> <phrase role="identifier">value_type</phrase> <phrase role="special">&&</phrase> <phrase role="identifier">va</phrase><phrase role="special">);</phrase> 8000 <phrase role="keyword">template</phrase><phrase role="special"><</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Rep</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Period</phrase> <phrase role="special">></phrase> 8001 <phrase role="identifier">channel_op_status</phrase> <phrase role="identifier">push_wait_for</phrase><phrase role="special">(</phrase> 8002 <phrase role="identifier">value_type</phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">va</phrase><phrase role="special">,</phrase> 8003 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">duration</phrase><phrase role="special"><</phrase> <phrase role="identifier">Rep</phrase><phrase role="special">,</phrase> <phrase role="identifier">Period</phrase> <phrase role="special">></phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">timeout_duration</phrase><phrase role="special">);</phrase> 8004 <phrase role="identifier">channel_op_status</phrase> <phrase role="identifier">push_wait_for</phrase><phrase role="special">(</phrase> <phrase role="identifier">value_type</phrase> <phrase role="special">&&</phrase> <phrase role="identifier">va</phrase><phrase role="special">,</phrase> 8005 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">duration</phrase><phrase role="special"><</phrase> <phrase role="identifier">Rep</phrase><phrase role="special">,</phrase> <phrase role="identifier">Period</phrase> <phrase role="special">></phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">timeout_duration</phrase><phrase role="special">);</phrase> 8006 <phrase role="keyword">template</phrase><phrase role="special"><</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Clock</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Duration</phrase> <phrase role="special">></phrase> 8007 <phrase role="identifier">channel_op_status</phrase> <phrase role="identifier">push_wait_until</phrase><phrase role="special">(</phrase> 8008 <phrase role="identifier">value_type</phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">va</phrase><phrase role="special">,</phrase> 8009 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">time_point</phrase><phrase role="special"><</phrase> <phrase role="identifier">Clock</phrase><phrase role="special">,</phrase> <phrase role="identifier">Duration</phrase> <phrase role="special">></phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">timeout_time</phrase><phrase role="special">);</phrase> 8010 <phrase role="keyword">template</phrase><phrase role="special"><</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Clock</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Duration</phrase> <phrase role="special">></phrase> 8011 <phrase role="identifier">channel_op_status</phrase> <phrase role="identifier">push_wait_until</phrase><phrase role="special">(</phrase> 8012 <phrase role="identifier">value_type</phrase> <phrase role="special">&&</phrase> <phrase role="identifier">va</phrase><phrase role="special">,</phrase> 8013 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">time_point</phrase><phrase role="special"><</phrase> <phrase role="identifier">Clock</phrase><phrase role="special">,</phrase> <phrase role="identifier">Duration</phrase> <phrase role="special">></phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">timeout_time</phrase><phrase role="special">);</phrase> 8014 8015 <phrase role="identifier">channel_op_status</phrase> <phrase role="identifier">pop</phrase><phrase role="special">(</phrase> <phrase role="identifier">value_type</phrase> <phrase role="special">&</phrase> <phrase role="identifier">va</phrase><phrase role="special">);</phrase> 8016 <phrase role="identifier">value_type</phrase> <phrase role="identifier">value_pop</phrase><phrase role="special">();</phrase> 8017 <phrase role="keyword">template</phrase><phrase role="special"><</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Rep</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Period</phrase> <phrase role="special">></phrase> 8018 <phrase role="identifier">channel_op_status</phrase> <phrase role="identifier">pop_wait_for</phrase><phrase role="special">(</phrase> 8019 <phrase role="identifier">value_type</phrase> <phrase role="special">&</phrase> <phrase role="identifier">va</phrase><phrase role="special">,</phrase> 8020 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">duration</phrase><phrase role="special"><</phrase> <phrase role="identifier">Rep</phrase><phrase role="special">,</phrase> <phrase role="identifier">Period</phrase> <phrase role="special">></phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">timeout_duration</phrase><phrase role="special">);</phrase> 8021 <phrase role="keyword">template</phrase><phrase role="special"><</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Clock</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Duration</phrase> <phrase role="special">></phrase> 8022 <phrase role="identifier">channel_op_status</phrase> <phrase role="identifier">pop_wait_until</phrase><phrase role="special">(</phrase> 8023 <phrase role="identifier">value_type</phrase> <phrase role="special">&</phrase> <phrase role="identifier">va</phrase><phrase role="special">,</phrase> 8024 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">time_point</phrase><phrase role="special"><</phrase> <phrase role="identifier">Clock</phrase><phrase role="special">,</phrase> <phrase role="identifier">Duration</phrase> <phrase role="special">></phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">timeout_time</phrase><phrase role="special">);</phrase> 8025<phrase role="special">};</phrase> 8026 8027<phrase role="keyword">template</phrase><phrase role="special"><</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">T</phrase> <phrase role="special">></phrase> 8028<phrase role="identifier">unbuffered_channel</phrase><phrase role="special"><</phrase> <phrase role="identifier">T</phrase> <phrase role="special">>::</phrase><phrase role="identifier">iterator</phrase> <phrase role="identifier">begin</phrase><phrase role="special">(</phrase> <phrase role="identifier">unbuffered_channel</phrase><phrase role="special"><</phrase> <phrase role="identifier">T</phrase> <phrase role="special">></phrase> <phrase role="special">&</phrase> <phrase role="identifier">chan</phrase><phrase role="special">);</phrase> 8029 8030<phrase role="keyword">template</phrase><phrase role="special"><</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">T</phrase> <phrase role="special">></phrase> 8031<phrase role="identifier">unbuffered_channel</phrase><phrase role="special"><</phrase> <phrase role="identifier">T</phrase> <phrase role="special">>::</phrase><phrase role="identifier">iterator</phrase> <phrase role="identifier">end</phrase><phrase role="special">(</phrase> <phrase role="identifier">unbuffered_channel</phrase><phrase role="special"><</phrase> <phrase role="identifier">T</phrase> <phrase role="special">></phrase> <phrase role="special">&</phrase> <phrase role="identifier">chan</phrase><phrase role="special">);</phrase> 8032 8033<phrase role="special">}}</phrase> 8034</programlisting> 8035 <bridgehead renderas="sect5" id="fiber.synchronization.channels.unbuffered_channel.h0"> 8036 <phrase id="fiber.synchronization.channels.unbuffered_channel.constructor"/><link 8037 linkend="fiber.synchronization.channels.unbuffered_channel.constructor">Constructor</link> 8038 </bridgehead> 8039<programlisting><phrase role="identifier">unbuffered_channel</phrase><phrase role="special">();</phrase> 8040</programlisting> 8041 <variablelist> 8042 <title></title> 8043 <varlistentry> 8044 <term>Effects:</term> 8045 <listitem> 8046 <para> 8047 The constructor constructs an object of class <code><phrase role="identifier">unbuffered_channel</phrase></code>. 8048 </para> 8049 </listitem> 8050 </varlistentry> 8051 </variablelist> 8052 <para> 8053 <bridgehead renderas="sect4" id="unbuffered_channel_close_bridgehead"> 8054 <phrase id="unbuffered_channel_close"/> 8055 <link linkend="unbuffered_channel_close">Member 8056 function <code>close</code>()</link> 8057</bridgehead> 8058 </para> 8059<programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">close</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 8060</programlisting> 8061 <variablelist> 8062 <title></title> 8063 <varlistentry> 8064 <term>Effects:</term> 8065 <listitem> 8066 <para> 8067 Deactivates the channel. No values can be put after calling <code><phrase 8068 role="keyword">this</phrase><phrase role="special">-></phrase><phrase 8069 role="identifier">close</phrase><phrase role="special">()</phrase></code>. 8070 Fibers blocked in <code><phrase role="keyword">this</phrase><phrase 8071 role="special">-></phrase><phrase role="identifier">pop</phrase><phrase 8072 role="special">()</phrase></code>, <code><phrase role="keyword">this</phrase><phrase 8073 role="special">-></phrase><phrase role="identifier">pop_wait_for</phrase><phrase 8074 role="special">()</phrase></code> or <code><phrase role="keyword">this</phrase><phrase 8075 role="special">-></phrase><phrase role="identifier">pop_wait_until</phrase><phrase 8076 role="special">()</phrase></code> will return <code><phrase role="identifier">closed</phrase></code>. 8077 Fibers blocked in <code><phrase role="keyword">this</phrase><phrase 8078 role="special">-></phrase><phrase role="identifier">value_pop</phrase><phrase 8079 role="special">()</phrase></code> will receive an exception. 8080 </para> 8081 </listitem> 8082 </varlistentry> 8083 <varlistentry> 8084 <term>Throws:</term> 8085 <listitem> 8086 <para> 8087 Nothing. 8088 </para> 8089 </listitem> 8090 </varlistentry> 8091 <varlistentry> 8092 <term>Note:</term> 8093 <listitem> 8094 <para> 8095 <code><phrase role="identifier">close</phrase><phrase role="special">()</phrase></code> 8096 is like closing a pipe. It informs waiting consumers that no more 8097 values will arrive. 8098 </para> 8099 </listitem> 8100 </varlistentry> 8101 </variablelist> 8102 <para> 8103 <bridgehead renderas="sect4" id="unbuffered_channel_push_bridgehead"> 8104 <phrase id="unbuffered_channel_push"/> 8105 <link linkend="unbuffered_channel_push">Member 8106 function <code>push</code>()</link> 8107</bridgehead> 8108 </para> 8109<programlisting><phrase role="identifier">channel_op_status</phrase> <phrase role="identifier">push</phrase><phrase role="special">(</phrase> <phrase role="identifier">value_type</phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">va</phrase><phrase role="special">);</phrase> 8110<phrase role="identifier">channel_op_status</phrase> <phrase role="identifier">push</phrase><phrase role="special">(</phrase> <phrase role="identifier">value_type</phrase> <phrase role="special">&&</phrase> <phrase role="identifier">va</phrase><phrase role="special">);</phrase> 8111</programlisting> 8112 <variablelist> 8113 <title></title> 8114 <varlistentry> 8115 <term>Effects:</term> 8116 <listitem> 8117 <para> 8118 If channel is closed, returns <code><phrase role="identifier">closed</phrase></code>. 8119 Otherwise enqueues the value in the channel, wakes up a fiber blocked 8120 on <code><phrase role="keyword">this</phrase><phrase role="special">-></phrase><phrase 8121 role="identifier">pop</phrase><phrase role="special">()</phrase></code>, 8122 <code><phrase role="keyword">this</phrase><phrase role="special">-></phrase><phrase 8123 role="identifier">value_pop</phrase><phrase role="special">()</phrase></code>, 8124 <code><phrase role="keyword">this</phrase><phrase role="special">-></phrase><phrase 8125 role="identifier">pop_wait_for</phrase><phrase role="special">()</phrase></code> 8126 or <code><phrase role="keyword">this</phrase><phrase role="special">-></phrase><phrase 8127 role="identifier">pop_wait_until</phrase><phrase role="special">()</phrase></code> 8128 and returns <code><phrase role="identifier">success</phrase></code>. 8129 </para> 8130 </listitem> 8131 </varlistentry> 8132 <varlistentry> 8133 <term>Throws:</term> 8134 <listitem> 8135 <para> 8136 Exceptions thrown by copy- or move-operations. 8137 </para> 8138 </listitem> 8139 </varlistentry> 8140 </variablelist> 8141 <para> 8142 <bridgehead renderas="sect4" id="unbuffered_channel_pop_bridgehead"> 8143 <phrase id="unbuffered_channel_pop"/> 8144 <link linkend="unbuffered_channel_pop">Member 8145 function <code>pop</code>()</link> 8146</bridgehead> 8147 </para> 8148<programlisting><phrase role="identifier">channel_op_status</phrase> <phrase role="identifier">pop</phrase><phrase role="special">(</phrase> <phrase role="identifier">value_type</phrase> <phrase role="special">&</phrase> <phrase role="identifier">va</phrase><phrase role="special">);</phrase> 8149</programlisting> 8150 <variablelist> 8151 <title></title> 8152 <varlistentry> 8153 <term>Effects:</term> 8154 <listitem> 8155 <para> 8156 Dequeues a value from the channel. If the channel is empty, the fiber 8157 gets suspended until at least one new item is <code><phrase role="identifier">push</phrase><phrase 8158 role="special">()</phrase></code>ed (return value <code><phrase role="identifier">success</phrase></code> 8159 and <code><phrase role="identifier">va</phrase></code> contains dequeued 8160 value) or the channel gets <code><phrase role="identifier">close</phrase><phrase 8161 role="special">()</phrase></code>d (return value <code><phrase role="identifier">closed</phrase></code>). 8162 </para> 8163 </listitem> 8164 </varlistentry> 8165 <varlistentry> 8166 <term>Throws:</term> 8167 <listitem> 8168 <para> 8169 Exceptions thrown by copy- or move-operations. 8170 </para> 8171 </listitem> 8172 </varlistentry> 8173 </variablelist> 8174 <para> 8175 <bridgehead renderas="sect4" id="unbuffered_channel_value_pop_bridgehead"> 8176 <phrase id="unbuffered_channel_value_pop"/> 8177 <link linkend="unbuffered_channel_value_pop">Member 8178 function <code>value_pop</code>()</link> 8179</bridgehead> 8180 </para> 8181<programlisting><phrase role="identifier">value_type</phrase> <phrase role="identifier">value_pop</phrase><phrase role="special">();</phrase> 8182</programlisting> 8183 <variablelist> 8184 <title></title> 8185 <varlistentry> 8186 <term>Effects:</term> 8187 <listitem> 8188 <para> 8189 Dequeues a value from the channel. If the channel is empty, the fiber 8190 gets suspended until at least one new item is <code><phrase role="identifier">push</phrase><phrase 8191 role="special">()</phrase></code>ed or the channel gets <code><phrase 8192 role="identifier">close</phrase><phrase role="special">()</phrase></code>d 8193 (which throws an exception). 8194 </para> 8195 </listitem> 8196 </varlistentry> 8197 <varlistentry> 8198 <term>Throws:</term> 8199 <listitem> 8200 <para> 8201 <code><phrase role="identifier">fiber_error</phrase></code> if <code><phrase 8202 role="special">*</phrase><phrase role="keyword">this</phrase></code> 8203 is closed or by copy- or move-operations. 8204 </para> 8205 </listitem> 8206 </varlistentry> 8207 <varlistentry> 8208 <term>Error conditions:</term> 8209 <listitem> 8210 <para> 8211 <code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase 8212 role="identifier">errc</phrase><phrase role="special">::</phrase><phrase 8213 role="identifier">operation_not_permitted</phrase></code> 8214 </para> 8215 </listitem> 8216 </varlistentry> 8217 </variablelist> 8218 <para> 8219 <bridgehead renderas="sect4" id="unbuffered_channel_pop_wait_for_bridgehead"> 8220 <phrase id="unbuffered_channel_pop_wait_for"/> 8221 <link linkend="unbuffered_channel_pop_wait_for">Member 8222 function <code>pop_wait_for</code>()</link> 8223</bridgehead> 8224 </para> 8225<programlisting><phrase role="keyword">template</phrase><phrase role="special"><</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Rep</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Period</phrase> <phrase role="special">></phrase> 8226<phrase role="identifier">channel_op_status</phrase> <phrase role="identifier">pop_wait_for</phrase><phrase role="special">(</phrase> 8227 <phrase role="identifier">value_type</phrase> <phrase role="special">&</phrase> <phrase role="identifier">va</phrase><phrase role="special">,</phrase> 8228 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">duration</phrase><phrase role="special"><</phrase> <phrase role="identifier">Rep</phrase><phrase role="special">,</phrase> <phrase role="identifier">Period</phrase> <phrase role="special">></phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">timeout_duration</phrase><phrase role="special">)</phrase> 8229</programlisting> 8230 <variablelist> 8231 <title></title> 8232 <varlistentry> 8233 <term>Effects:</term> 8234 <listitem> 8235 <para> 8236 Accepts <code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase 8237 role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase 8238 role="identifier">duration</phrase></code> and internally computes 8239 a timeout time as (system time + <code><phrase role="identifier">timeout_duration</phrase></code>). 8240 If channel is not empty, immediately dequeues a value from the channel. 8241 Otherwise the fiber gets suspended until at least one new item is 8242 <code><phrase role="identifier">push</phrase><phrase role="special">()</phrase></code>ed 8243 (return value <code><phrase role="identifier">success</phrase></code> 8244 and <code><phrase role="identifier">va</phrase></code> contains dequeued 8245 value), or the channel gets <code><phrase role="identifier">close</phrase><phrase 8246 role="special">()</phrase></code>d (return value <code><phrase role="identifier">closed</phrase></code>), 8247 or the system time reaches the computed timeout time (return value 8248 <code><phrase role="identifier">timeout</phrase></code>). 8249 </para> 8250 </listitem> 8251 </varlistentry> 8252 <varlistentry> 8253 <term>Throws:</term> 8254 <listitem> 8255 <para> 8256 timeout-related exceptions or by copy- or move-operations. 8257 </para> 8258 </listitem> 8259 </varlistentry> 8260 </variablelist> 8261 <para> 8262 <bridgehead renderas="sect4" id="unbuffered_channel_pop_wait_until_bridgehead"> 8263 <phrase id="unbuffered_channel_pop_wait_until"/> 8264 <link linkend="unbuffered_channel_pop_wait_until">Member 8265 function <code>pop_wait_until</code>()</link> 8266</bridgehead> 8267 </para> 8268<programlisting><phrase role="keyword">template</phrase><phrase role="special"><</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Clock</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Duration</phrase> <phrase role="special">></phrase> 8269<phrase role="identifier">channel_op_status</phrase> <phrase role="identifier">pop_wait_until</phrase><phrase role="special">(</phrase> 8270 <phrase role="identifier">value_type</phrase> <phrase role="special">&</phrase> <phrase role="identifier">va</phrase><phrase role="special">,</phrase> 8271 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">time_point</phrase><phrase role="special"><</phrase> <phrase role="identifier">Clock</phrase><phrase role="special">,</phrase> <phrase role="identifier">Duration</phrase> <phrase role="special">></phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">timeout_time</phrase><phrase role="special">)</phrase> 8272</programlisting> 8273 <variablelist> 8274 <title></title> 8275 <varlistentry> 8276 <term>Effects:</term> 8277 <listitem> 8278 <para> 8279 Accepts a <code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase 8280 role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase 8281 role="identifier">time_point</phrase><phrase role="special"><</phrase> 8282 <phrase role="identifier">Clock</phrase><phrase role="special">,</phrase> 8283 <phrase role="identifier">Duration</phrase> <phrase role="special">></phrase></code>. 8284 If channel is not empty, immediately dequeues a value from the channel. 8285 Otherwise the fiber gets suspended until at least one new item is 8286 <code><phrase role="identifier">push</phrase><phrase role="special">()</phrase></code>ed 8287 (return value <code><phrase role="identifier">success</phrase></code> 8288 and <code><phrase role="identifier">va</phrase></code> contains dequeued 8289 value), or the channel gets <code><phrase role="identifier">close</phrase><phrase 8290 role="special">()</phrase></code>d (return value <code><phrase role="identifier">closed</phrase></code>), 8291 or the system time reaches the passed <code><phrase role="identifier">time_point</phrase></code> 8292 (return value <code><phrase role="identifier">timeout</phrase></code>). 8293 </para> 8294 </listitem> 8295 </varlistentry> 8296 <varlistentry> 8297 <term>Throws:</term> 8298 <listitem> 8299 <para> 8300 timeout-related exceptions or by copy- or move-operations. 8301 </para> 8302 </listitem> 8303 </varlistentry> 8304 </variablelist> 8305 <bridgehead renderas="sect5" id="fiber.synchronization.channels.unbuffered_channel.h1"> 8306 <phrase id="fiber.synchronization.channels.unbuffered_channel.non_member_function__code__phrase_role__identifier__begin__phrase__phrase_role__special_____phrase___phrase_role__identifier__unbuffered_channel__phrase__phrase_role__special___lt___phrase___phrase_role__identifier__t__phrase___phrase_role__special___gt___phrase___phrase_role__special___amp____phrase___code_"/><link 8307 linkend="fiber.synchronization.channels.unbuffered_channel.non_member_function__code__phrase_role__identifier__begin__phrase__phrase_role__special_____phrase___phrase_role__identifier__unbuffered_channel__phrase__phrase_role__special___lt___phrase___phrase_role__identifier__t__phrase___phrase_role__special___gt___phrase___phrase_role__special___amp____phrase___code_">Non-member 8308 function <code><phrase role="identifier">begin</phrase><phrase role="special">(</phrase> 8309 <phrase role="identifier">unbuffered_channel</phrase><phrase role="special"><</phrase> 8310 <phrase role="identifier">T</phrase> <phrase role="special">></phrase> 8311 <phrase role="special">&)</phrase></code></link> 8312 </bridgehead> 8313<programlisting><phrase role="keyword">template</phrase><phrase role="special"><</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">T</phrase> <phrase role="special">></phrase> 8314<phrase role="identifier">unbuffered_channel</phrase><phrase role="special"><</phrase> <phrase role="identifier">T</phrase> <phrase role="special">>::</phrase><phrase role="identifier">iterator</phrase> <phrase role="identifier">begin</phrase><phrase role="special">(</phrase> <phrase role="identifier">unbuffered_channel</phrase><phrase role="special"><</phrase> <phrase role="identifier">T</phrase> <phrase role="special">></phrase> <phrase role="special">&);</phrase> 8315</programlisting> 8316 <variablelist> 8317 <title></title> 8318 <varlistentry> 8319 <term>Returns:</term> 8320 <listitem> 8321 <para> 8322 Returns a range-iterator (input-iterator). 8323 </para> 8324 </listitem> 8325 </varlistentry> 8326 </variablelist> 8327 <bridgehead renderas="sect5" id="fiber.synchronization.channels.unbuffered_channel.h2"> 8328 <phrase id="fiber.synchronization.channels.unbuffered_channel.non_member_function__code__phrase_role__identifier__end__phrase__phrase_role__special_____phrase___phrase_role__identifier__unbuffered_channel__phrase__phrase_role__special___lt___phrase___phrase_role__identifier__t__phrase___phrase_role__special___gt___phrase___phrase_role__special___amp____phrase___code_"/><link 8329 linkend="fiber.synchronization.channels.unbuffered_channel.non_member_function__code__phrase_role__identifier__end__phrase__phrase_role__special_____phrase___phrase_role__identifier__unbuffered_channel__phrase__phrase_role__special___lt___phrase___phrase_role__identifier__t__phrase___phrase_role__special___gt___phrase___phrase_role__special___amp____phrase___code_">Non-member 8330 function <code><phrase role="identifier">end</phrase><phrase role="special">(</phrase> 8331 <phrase role="identifier">unbuffered_channel</phrase><phrase role="special"><</phrase> 8332 <phrase role="identifier">T</phrase> <phrase role="special">></phrase> 8333 <phrase role="special">&)</phrase></code></link> 8334 </bridgehead> 8335<programlisting><phrase role="keyword">template</phrase><phrase role="special"><</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">T</phrase> <phrase role="special">></phrase> 8336<phrase role="identifier">unbuffered_channel</phrase><phrase role="special"><</phrase> <phrase role="identifier">R</phrase> <phrase role="special">>::</phrase><phrase role="identifier">iterator</phrase> <phrase role="identifier">end</phrase><phrase role="special">(</phrase> <phrase role="identifier">unbuffered_channel</phrase><phrase role="special"><</phrase> <phrase role="identifier">T</phrase> <phrase role="special">></phrase> <phrase role="special">&);</phrase> 8337</programlisting> 8338 <variablelist> 8339 <title></title> 8340 <varlistentry> 8341 <term>Returns:</term> 8342 <listitem> 8343 <para> 8344 Returns an end range-iterator (input-iterator). 8345 </para> 8346 </listitem> 8347 </varlistentry> 8348 </variablelist> 8349 </section> 8350 </section> 8351 <section id="fiber.synchronization.futures"> 8352 <title><link linkend="fiber.synchronization.futures">Futures</link></title> 8353 <bridgehead renderas="sect4" id="fiber.synchronization.futures.h0"> 8354 <phrase id="fiber.synchronization.futures.overview"/><link linkend="fiber.synchronization.futures.overview">Overview</link> 8355 </bridgehead> 8356 <para> 8357 The futures library provides a means of handling asynchronous future values, 8358 whether those values are generated by another fiber, or on a single fiber 8359 in response to external stimuli, or on-demand. 8360 </para> 8361 <para> 8362 This is done through the provision of four class templates: <link linkend="class_future"><code>future<></code></link> and 8363 <link linkend="class_shared_future"><code>shared_future<></code></link> which are used to retrieve the asynchronous 8364 results, and <link linkend="class_promise"><code>promise<></code></link> and <link linkend="class_packaged_task"><code>packaged_task<></code></link> which 8365 are used to generate the asynchronous results. 8366 </para> 8367 <para> 8368 An instance of <link linkend="class_future"><code>future<></code></link> holds the one and only reference 8369 to a result. Ownership can be transferred between instances using the move 8370 constructor or move-assignment operator, but at most one instance holds a 8371 reference to a given asynchronous result. When the result is ready, it is 8372 returned from <link linkend="future_get"><code>future::get()</code></link> by rvalue-reference to allow the result 8373 to be moved or copied as appropriate for the type. 8374 </para> 8375 <para> 8376 On the other hand, many instances of <link linkend="class_shared_future"><code>shared_future<></code></link> may 8377 reference the same result. Instances can be freely copied and assigned, and 8378 <link linkend="shared_future_get"><code>shared_future::get()</code></link> 8379returns a <code><phrase role="keyword">const</phrase></code> 8380 reference so that multiple calls to <link linkend="shared_future_get"><code>shared_future::get()</code></link> 8381are 8382 safe. You can move an instance of <link linkend="class_future"><code>future<></code></link> into an instance 8383 of <link linkend="class_shared_future"><code>shared_future<></code></link>, thus transferring ownership 8384 of the associated asynchronous result, but not vice-versa. 8385 </para> 8386 <para> 8387 <link linkend="fibers_async"><code>fibers::async()</code></link> is a simple way of running asynchronous tasks. 8388 A call to <code><phrase role="identifier">async</phrase><phrase role="special">()</phrase></code> 8389 spawns a fiber and returns a <link linkend="class_future"><code>future<></code></link> that will deliver 8390 the result of the fiber function. 8391 </para> 8392 <bridgehead renderas="sect4" id="fiber.synchronization.futures.h1"> 8393 <phrase id="fiber.synchronization.futures.creating_asynchronous_values"/><link 8394 linkend="fiber.synchronization.futures.creating_asynchronous_values">Creating 8395 asynchronous values</link> 8396 </bridgehead> 8397 <para> 8398 You can set the value in a future with either a <link linkend="class_promise"><code>promise<></code></link> or 8399 a <link linkend="class_packaged_task"><code>packaged_task<></code></link>. A <link linkend="class_packaged_task"><code>packaged_task<></code></link> is 8400 a callable object with <code><phrase role="keyword">void</phrase></code> 8401 return that wraps a function or callable object returning the specified type. 8402 When the <link linkend="class_packaged_task"><code>packaged_task<></code></link> is invoked, it invokes the 8403 contained function in turn, and populates a future with the contained function's 8404 return value. This is an answer to the perennial question: <quote>How do 8405 I return a value from a fiber?</quote> Package the function you wish to run 8406 as a <link linkend="class_packaged_task"><code>packaged_task<></code></link> and pass the packaged task to 8407 the fiber constructor. The future retrieved from the packaged task can then 8408 be used to obtain the return value. If the function throws an exception, 8409 that is stored in the future in place of the return value. 8410 </para> 8411<programlisting><phrase role="keyword">int</phrase> <phrase role="identifier">calculate_the_answer_to_life_the_universe_and_everything</phrase><phrase role="special">()</phrase> <phrase role="special">{</phrase> 8412 <phrase role="keyword">return</phrase> <phrase role="number">42</phrase><phrase role="special">;</phrase> 8413<phrase role="special">}</phrase> 8414 8415<phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">packaged_task</phrase><phrase role="special"><</phrase><phrase role="keyword">int</phrase><phrase role="special">()></phrase> <phrase role="identifier">pt</phrase><phrase role="special">(</phrase><phrase role="identifier">calculate_the_answer_to_life_the_universe_and_everything</phrase><phrase role="special">);</phrase> 8416<phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">future</phrase><phrase role="special"><</phrase><phrase role="keyword">int</phrase><phrase role="special">></phrase> <phrase role="identifier">fi</phrase><phrase role="special">=</phrase><phrase role="identifier">pt</phrase><phrase role="special">.</phrase><phrase role="identifier">get_future</phrase><phrase role="special">();</phrase> 8417<phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">fiber</phrase><phrase role="special">(</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">move</phrase><phrase role="special">(</phrase><phrase role="identifier">pt</phrase><phrase role="special">)).</phrase><phrase role="identifier">detach</phrase><phrase role="special">();</phrase> <phrase role="comment">// launch task on a fiber</phrase> 8418 8419<phrase role="identifier">fi</phrase><phrase role="special">.</phrase><phrase role="identifier">wait</phrase><phrase role="special">();</phrase> <phrase role="comment">// wait for it to finish</phrase> 8420 8421<phrase role="identifier">assert</phrase><phrase role="special">(</phrase><phrase role="identifier">fi</phrase><phrase role="special">.</phrase><phrase role="identifier">is_ready</phrase><phrase role="special">());</phrase> 8422<phrase role="identifier">assert</phrase><phrase role="special">(</phrase><phrase role="identifier">fi</phrase><phrase role="special">.</phrase><phrase role="identifier">has_value</phrase><phrase role="special">());</phrase> 8423<phrase role="identifier">assert</phrase><phrase role="special">(!</phrase><phrase role="identifier">fi</phrase><phrase role="special">.</phrase><phrase role="identifier">has_exception</phrase><phrase role="special">());</phrase> 8424<phrase role="identifier">assert</phrase><phrase role="special">(</phrase><phrase role="identifier">fi</phrase><phrase role="special">.</phrase><phrase role="identifier">get</phrase><phrase role="special">()==</phrase><phrase role="number">42</phrase><phrase role="special">);</phrase> 8425</programlisting> 8426 <para> 8427 A <link linkend="class_promise"><code>promise<></code></link> is a bit more low level: it just provides explicit 8428 functions to store a value or an exception in the associated future. A promise 8429 can therefore be used where the value might come from more than one possible 8430 source. 8431 </para> 8432<programlisting><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">promise</phrase><phrase role="special"><</phrase><phrase role="keyword">int</phrase><phrase role="special">></phrase> <phrase role="identifier">pi</phrase><phrase role="special">;</phrase> 8433<phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">future</phrase><phrase role="special"><</phrase><phrase role="keyword">int</phrase><phrase role="special">></phrase> <phrase role="identifier">fi</phrase><phrase role="special">;</phrase> 8434<phrase role="identifier">fi</phrase><phrase role="special">=</phrase><phrase role="identifier">pi</phrase><phrase role="special">.</phrase><phrase role="identifier">get_future</phrase><phrase role="special">();</phrase> 8435 8436<phrase role="identifier">pi</phrase><phrase role="special">.</phrase><phrase role="identifier">set_value</phrase><phrase role="special">(</phrase><phrase role="number">42</phrase><phrase role="special">);</phrase> 8437 8438<phrase role="identifier">assert</phrase><phrase role="special">(</phrase><phrase role="identifier">fi</phrase><phrase role="special">.</phrase><phrase role="identifier">is_ready</phrase><phrase role="special">());</phrase> 8439<phrase role="identifier">assert</phrase><phrase role="special">(</phrase><phrase role="identifier">fi</phrase><phrase role="special">.</phrase><phrase role="identifier">has_value</phrase><phrase role="special">());</phrase> 8440<phrase role="identifier">assert</phrase><phrase role="special">(!</phrase><phrase role="identifier">fi</phrase><phrase role="special">.</phrase><phrase role="identifier">has_exception</phrase><phrase role="special">());</phrase> 8441<phrase role="identifier">assert</phrase><phrase role="special">(</phrase><phrase role="identifier">fi</phrase><phrase role="special">.</phrase><phrase role="identifier">get</phrase><phrase role="special">()==</phrase><phrase role="number">42</phrase><phrase role="special">);</phrase> 8442</programlisting> 8443 <section id="fiber.synchronization.futures.future"> 8444 <title><link linkend="fiber.synchronization.futures.future">Future</link></title> 8445 <para> 8446 A future provides a mechanism to access the result of an asynchronous operation. 8447 </para> 8448 <anchor id="shared_state"/> 8449 <bridgehead renderas="sect5" id="fiber.synchronization.futures.future.h0"> 8450 <phrase id="fiber.synchronization.futures.future.shared_state"/><link linkend="fiber.synchronization.futures.future.shared_state">shared 8451 state</link> 8452 </bridgehead> 8453 <para> 8454 Behind a <link linkend="class_promise"><code>promise<></code></link> and its <link linkend="class_future"><code>future<></code></link> lies 8455 an unspecified object called their <emphasis>shared state</emphasis>. The 8456 shared state is what will actually hold the async result (or the exception). 8457 </para> 8458 <para> 8459 The shared state is instantiated along with the <link linkend="class_promise"><code>promise<></code></link>. 8460 </para> 8461 <para> 8462 Aside from its originating <code><phrase role="identifier">promise</phrase><phrase 8463 role="special"><></phrase></code>, a <link linkend="class_future"><code>future<></code></link> holds 8464 a unique reference to a particular shared state. However, multiple <link linkend="class_shared_future"><code>shared_future<></code></link> instances 8465 can reference the same underlying shared state. 8466 </para> 8467 <para> 8468 As <link linkend="class_packaged_task"><code>packaged_task<></code></link> and <link linkend="fibers_async"><code>fibers::async()</code></link> are 8469 implemented using <link linkend="class_promise"><code>promise<></code></link>, discussions of shared state 8470 apply to them as well. 8471 </para> 8472 <anchor id="class_future_status"/> 8473 <bridgehead renderas="sect5" id="fiber.synchronization.futures.future.h1"> 8474 <phrase id="fiber.synchronization.futures.future.enumeration__code__phrase_role__identifier__future_status__phrase___code_"/><link 8475 linkend="fiber.synchronization.futures.future.enumeration__code__phrase_role__identifier__future_status__phrase___code_">Enumeration 8476 <code><phrase role="identifier">future_status</phrase></code></link> 8477 </bridgehead> 8478 <para> 8479 Timed wait-operations (<link linkend="future_wait_for"><code>future::wait_for()</code></link> and <link linkend="future_wait_until"><code>future::wait_until()</code></link>) 8480 return the state of the future. 8481 </para> 8482<programlisting><phrase role="keyword">enum</phrase> <phrase role="keyword">class</phrase> <phrase role="identifier">future_status</phrase> <phrase role="special">{</phrase> 8483 <phrase role="identifier">ready</phrase><phrase role="special">,</phrase> 8484 <phrase role="identifier">timeout</phrase><phrase role="special">,</phrase> 8485 <phrase role="identifier">deferred</phrase> <phrase role="comment">// not supported yet</phrase> 8486<phrase role="special">};</phrase> 8487</programlisting> 8488 <bridgehead renderas="sect5" id="fiber.synchronization.futures.future.h2"> 8489 <phrase id="fiber.synchronization.futures.future._code__phrase_role__identifier__ready__phrase___code_"/><link 8490 linkend="fiber.synchronization.futures.future._code__phrase_role__identifier__ready__phrase___code_"><code><phrase 8491 role="identifier">ready</phrase></code></link> 8492 </bridgehead> 8493 <variablelist> 8494 <title></title> 8495 <varlistentry> 8496 <term>Effects:</term> 8497 <listitem> 8498 <para> 8499 The <link linkend="shared_state">shared state</link> is ready. 8500 </para> 8501 </listitem> 8502 </varlistentry> 8503 </variablelist> 8504 <bridgehead renderas="sect5" id="fiber.synchronization.futures.future.h3"> 8505 <phrase id="fiber.synchronization.futures.future._code__phrase_role__identifier__timeout__phrase___code_"/><link 8506 linkend="fiber.synchronization.futures.future._code__phrase_role__identifier__timeout__phrase___code_"><code><phrase 8507 role="identifier">timeout</phrase></code></link> 8508 </bridgehead> 8509 <variablelist> 8510 <title></title> 8511 <varlistentry> 8512 <term>Effects:</term> 8513 <listitem> 8514 <para> 8515 The <link linkend="shared_state">shared state</link> did not become 8516 ready before timeout has passed. 8517 </para> 8518 </listitem> 8519 </varlistentry> 8520 </variablelist> 8521 <note> 8522 <para> 8523 Deferred futures are not supported. 8524 </para> 8525 </note> 8526 <para> 8527 <bridgehead renderas="sect4" id="class_future_bridgehead"> 8528 <phrase id="class_future"/> 8529 <link linkend="class_future">Template <code>future<></code></link> 8530</bridgehead> 8531 </para> 8532 <para> 8533 A <link linkend="class_future"><code>future<></code></link> contains a <link linkend="shared_state">shared 8534 state</link> which is not shared with any other future. 8535 </para> 8536<programlisting><phrase role="preprocessor">#include</phrase> <phrase role="special"><</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">></phrase> 8537 8538<phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase> 8539<phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase> 8540 8541<phrase role="keyword">template</phrase><phrase role="special"><</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">R</phrase> <phrase role="special">></phrase> 8542<phrase role="keyword">class</phrase> <phrase role="identifier">future</phrase> <phrase role="special">{</phrase> 8543<phrase role="keyword">public</phrase><phrase role="special">:</phrase> 8544 <phrase role="identifier">future</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 8545 8546 <phrase role="identifier">future</phrase><phrase role="special">(</phrase> <phrase role="identifier">future</phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="special">=</phrase> <phrase role="keyword">delete</phrase><phrase role="special">;</phrase> 8547 8548 <phrase role="identifier">future</phrase> <phrase role="special">&</phrase> <phrase role="keyword">operator</phrase><phrase role="special">=(</phrase> <phrase role="identifier">future</phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="special">=</phrase> <phrase role="keyword">delete</phrase><phrase role="special">;</phrase> 8549 8550 <phrase role="identifier">future</phrase><phrase role="special">(</phrase> <phrase role="identifier">future</phrase> <phrase role="special">&&</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 8551 8552 <phrase role="identifier">future</phrase> <phrase role="special">&</phrase> <phrase role="keyword">operator</phrase><phrase role="special">=(</phrase> <phrase role="identifier">future</phrase> <phrase role="special">&&</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 8553 8554 <phrase role="special">~</phrase><phrase role="identifier">future</phrase><phrase role="special">();</phrase> 8555 8556 <phrase role="keyword">bool</phrase> <phrase role="identifier">valid</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 8557 8558 <phrase role="identifier">shared_future</phrase><phrase role="special"><</phrase> <phrase role="identifier">R</phrase> <phrase role="special">></phrase> <phrase role="identifier">share</phrase><phrase role="special">();</phrase> 8559 8560 <phrase role="identifier">R</phrase> <phrase role="identifier">get</phrase><phrase role="special">();</phrase> <phrase role="comment">// member only of generic future template</phrase> 8561 <phrase role="identifier">R</phrase> <phrase role="special">&</phrase> <phrase role="identifier">get</phrase><phrase role="special">();</phrase> <phrase role="comment">// member only of future< R & > template specialization</phrase> 8562 <phrase role="keyword">void</phrase> <phrase role="identifier">get</phrase><phrase role="special">();</phrase> <phrase role="comment">// member only of future< void > template specialization</phrase> 8563 8564 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">exception_ptr</phrase> <phrase role="identifier">get_exception_ptr</phrase><phrase role="special">();</phrase> 8565 8566 <phrase role="keyword">void</phrase> <phrase role="identifier">wait</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase> 8567 8568 <phrase role="keyword">template</phrase><phrase role="special"><</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">></phrase> 8569 <phrase role="identifier">future_status</phrase> <phrase role="identifier">wait_for</phrase><phrase role="special">(</phrase> 8570 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">duration</phrase><phrase role="special"><</phrase> <phrase role="identifier">Rep</phrase><phrase role="special">,</phrase> <phrase role="identifier">Period</phrase> <phrase role="special">></phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">timeout_duration</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase> 8571 8572 <phrase role="keyword">template</phrase><phrase role="special"><</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Clock</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Duration</phrase> <phrase role="special">></phrase> 8573 <phrase role="identifier">future_status</phrase> <phrase role="identifier">wait_until</phrase><phrase role="special">(</phrase> 8574 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">time_point</phrase><phrase role="special"><</phrase> <phrase role="identifier">Clock</phrase><phrase role="special">,</phrase> <phrase role="identifier">Duration</phrase> <phrase role="special">></phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">timeout_time</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase> 8575<phrase role="special">};</phrase> 8576 8577<phrase role="special">}}</phrase> 8578</programlisting> 8579 <bridgehead renderas="sect5" id="fiber.synchronization.futures.future.h4"> 8580 <phrase id="fiber.synchronization.futures.future.default_constructor"/><link 8581 linkend="fiber.synchronization.futures.future.default_constructor">Default 8582 constructor</link> 8583 </bridgehead> 8584<programlisting><phrase role="identifier">future</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 8585</programlisting> 8586 <variablelist> 8587 <title></title> 8588 <varlistentry> 8589 <term>Effects:</term> 8590 <listitem> 8591 <para> 8592 Creates a future with no <link linkend="shared_state">shared state</link>. 8593 After construction <code><phrase role="keyword">false</phrase> <phrase 8594 role="special">==</phrase> <phrase role="identifier">valid</phrase><phrase 8595 role="special">()</phrase></code>. 8596 </para> 8597 </listitem> 8598 </varlistentry> 8599 <varlistentry> 8600 <term>Throws:</term> 8601 <listitem> 8602 <para> 8603 Nothing. 8604 </para> 8605 </listitem> 8606 </varlistentry> 8607 </variablelist> 8608 <bridgehead renderas="sect5" id="fiber.synchronization.futures.future.h5"> 8609 <phrase id="fiber.synchronization.futures.future.move_constructor"/><link 8610 linkend="fiber.synchronization.futures.future.move_constructor">Move constructor</link> 8611 </bridgehead> 8612<programlisting><phrase role="identifier">future</phrase><phrase role="special">(</phrase> <phrase role="identifier">future</phrase> <phrase role="special">&&</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 8613</programlisting> 8614 <variablelist> 8615 <title></title> 8616 <varlistentry> 8617 <term>Effects:</term> 8618 <listitem> 8619 <para> 8620 Constructs a future with the <link linkend="shared_state">shared 8621 state</link> of other. After construction <code><phrase role="keyword">false</phrase> 8622 <phrase role="special">==</phrase> <phrase role="identifier">other</phrase><phrase 8623 role="special">.</phrase><phrase role="identifier">valid</phrase><phrase 8624 role="special">()</phrase></code>. 8625 </para> 8626 </listitem> 8627 </varlistentry> 8628 <varlistentry> 8629 <term>Throws:</term> 8630 <listitem> 8631 <para> 8632 Nothing. 8633 </para> 8634 </listitem> 8635 </varlistentry> 8636 </variablelist> 8637 <bridgehead renderas="sect5" id="fiber.synchronization.futures.future.h6"> 8638 <phrase id="fiber.synchronization.futures.future.destructor"/><link linkend="fiber.synchronization.futures.future.destructor">Destructor</link> 8639 </bridgehead> 8640<programlisting><phrase role="special">~</phrase><phrase role="identifier">future</phrase><phrase role="special">();</phrase> 8641</programlisting> 8642 <variablelist> 8643 <title></title> 8644 <varlistentry> 8645 <term>Effects:</term> 8646 <listitem> 8647 <para> 8648 Destroys the future; ownership is abandoned. 8649 </para> 8650 </listitem> 8651 </varlistentry> 8652 <varlistentry> 8653 <term>Note:</term> 8654 <listitem> 8655 <para> 8656 <code>~future()</code> does <emphasis>not</emphasis> block the calling fiber. 8657 </para> 8658 </listitem> 8659 </varlistentry> 8660 </variablelist> 8661 <para> 8662 Consider a sequence such as: 8663 </para> 8664 <orderedlist> 8665 <listitem> 8666 <simpara> 8667 instantiate <link linkend="class_promise"><code>promise<></code></link> 8668 </simpara> 8669 </listitem> 8670 <listitem> 8671 <simpara> 8672 obtain its <code><phrase role="identifier">future</phrase><phrase role="special"><></phrase></code> 8673 via <link linkend="promise_get_future"><code>promise::get_future()</code></link> 8674 </simpara> 8675 </listitem> 8676 <listitem> 8677 <simpara> 8678 launch <link linkend="class_fiber"><code>fiber</code></link>, capturing <code><phrase role="identifier">promise</phrase><phrase 8679 role="special"><></phrase></code> 8680 </simpara> 8681 </listitem> 8682 <listitem> 8683 <simpara> 8684 destroy <code><phrase role="identifier">future</phrase><phrase role="special"><></phrase></code> 8685 </simpara> 8686 </listitem> 8687 <listitem> 8688 <simpara> 8689 call <link linkend="promise_set_value"><code>promise::set_value()</code></link> 8690 </simpara> 8691 </listitem> 8692 </orderedlist> 8693 <para> 8694 The final <code><phrase role="identifier">set_value</phrase><phrase role="special">()</phrase></code> 8695 call succeeds, but the value is silently discarded: no additional <code><phrase 8696 role="identifier">future</phrase><phrase role="special"><></phrase></code> 8697 can be obtained from that <code><phrase role="identifier">promise</phrase><phrase 8698 role="special"><></phrase></code>. 8699 </para> 8700 <para> 8701 <bridgehead renderas="sect4" id="future_operator_assign_bridgehead"> 8702 <phrase id="future_operator_assign"/> 8703 <link linkend="future_operator_assign">Member 8704 function <code>operator=</code>()</link> 8705</bridgehead> 8706 </para> 8707<programlisting><phrase role="identifier">future</phrase> <phrase role="special">&</phrase> <phrase role="keyword">operator</phrase><phrase role="special">=(</phrase> <phrase role="identifier">future</phrase> <phrase role="special">&&</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 8708</programlisting> 8709 <variablelist> 8710 <title></title> 8711 <varlistentry> 8712 <term>Effects:</term> 8713 <listitem> 8714 <para> 8715 Moves the <link linkend="shared_state">shared state</link> of other 8716 to <code><phrase role="keyword">this</phrase></code>. After the assignment, 8717 <code><phrase role="keyword">false</phrase> <phrase role="special">==</phrase> 8718 <phrase role="identifier">other</phrase><phrase role="special">.</phrase><phrase 8719 role="identifier">valid</phrase><phrase role="special">()</phrase></code>. 8720 </para> 8721 </listitem> 8722 </varlistentry> 8723 <varlistentry> 8724 <term>Throws:</term> 8725 <listitem> 8726 <para> 8727 Nothing. 8728 </para> 8729 </listitem> 8730 </varlistentry> 8731 </variablelist> 8732 <para> 8733 <bridgehead renderas="sect4" id="future_valid_bridgehead"> 8734 <phrase id="future_valid"/> 8735 <link linkend="future_valid">Member function <code>valid</code>()</link> 8736</bridgehead> 8737 </para> 8738<programlisting><phrase role="keyword">bool</phrase> <phrase role="identifier">valid</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 8739</programlisting> 8740 <variablelist> 8741 <title></title> 8742 <varlistentry> 8743 <term>Effects:</term> 8744 <listitem> 8745 <para> 8746 Returns <code><phrase role="keyword">true</phrase></code> if future 8747 contains a <link linkend="shared_state">shared state</link>. 8748 </para> 8749 </listitem> 8750 </varlistentry> 8751 <varlistentry> 8752 <term>Throws:</term> 8753 <listitem> 8754 <para> 8755 Nothing. 8756 </para> 8757 </listitem> 8758 </varlistentry> 8759 </variablelist> 8760 <para> 8761 <bridgehead renderas="sect4" id="future_share_bridgehead"> 8762 <phrase id="future_share"/> 8763 <link linkend="future_share">Member function <code>share</code>()</link> 8764</bridgehead> 8765 </para> 8766<programlisting><phrase role="identifier">shared_future</phrase><phrase role="special"><</phrase> <phrase role="identifier">R</phrase> <phrase role="special">></phrase> <phrase role="identifier">share</phrase><phrase role="special">();</phrase> 8767</programlisting> 8768 <variablelist> 8769 <title></title> 8770 <varlistentry> 8771 <term>Effects:</term> 8772 <listitem> 8773 <para> 8774 Move the state to a <link linkend="class_shared_future"><code>shared_future<></code></link>. 8775 </para> 8776 </listitem> 8777 </varlistentry> 8778 <varlistentry> 8779 <term>Returns:</term> 8780 <listitem> 8781 <para> 8782 a <link linkend="class_shared_future"><code>shared_future<></code></link> containing the <link linkend="shared_state">shared 8783 state</link> formerly belonging to <code><phrase role="special">*</phrase><phrase 8784 role="keyword">this</phrase></code>. 8785 </para> 8786 </listitem> 8787 </varlistentry> 8788 <varlistentry> 8789 <term>Postcondition:</term> 8790 <listitem> 8791 <para> 8792 <code><phrase role="keyword">false</phrase> <phrase role="special">==</phrase> 8793 <phrase role="identifier">valid</phrase><phrase role="special">()</phrase></code> 8794 </para> 8795 </listitem> 8796 </varlistentry> 8797 <varlistentry> 8798 <term>Throws:</term> 8799 <listitem> 8800 <para> 8801 <code><phrase role="identifier">future_error</phrase></code> with 8802 error condition <code><phrase role="identifier">future_errc</phrase><phrase 8803 role="special">::</phrase><phrase role="identifier">no_state</phrase></code>. 8804 </para> 8805 </listitem> 8806 </varlistentry> 8807 </variablelist> 8808 <para> 8809 <bridgehead renderas="sect4" id="future_get_bridgehead"> 8810 <phrase id="future_get"/> 8811 <link linkend="future_get">Member function <code>get</code>()</link> 8812</bridgehead> 8813 </para> 8814<programlisting><phrase role="identifier">R</phrase> <phrase role="identifier">get</phrase><phrase role="special">();</phrase> <phrase role="comment">// member only of generic future template</phrase> 8815<phrase role="identifier">R</phrase> <phrase role="special">&</phrase> <phrase role="identifier">get</phrase><phrase role="special">();</phrase> <phrase role="comment">// member only of future< R & > template specialization</phrase> 8816<phrase role="keyword">void</phrase> <phrase role="identifier">get</phrase><phrase role="special">();</phrase> <phrase role="comment">// member only of future< void > template specialization</phrase> 8817</programlisting> 8818 <variablelist> 8819 <title></title> 8820 <varlistentry> 8821 <term>Precondition:</term> 8822 <listitem> 8823 <para> 8824 <code><phrase role="keyword">true</phrase> <phrase role="special">==</phrase> 8825 <phrase role="identifier">valid</phrase><phrase role="special">()</phrase></code> 8826 </para> 8827 </listitem> 8828 </varlistentry> 8829 <varlistentry> 8830 <term>Returns:</term> 8831 <listitem> 8832 <para> 8833 Waits until <link linkend="promise_set_value"><code>promise::set_value()</code></link> or <link linkend="promise_set_exception"><code>promise::set_exception()</code></link> is 8834 called. If <link linkend="promise_set_value"><code>promise::set_value()</code></link> is called, returns 8835 the value. If <link linkend="promise_set_exception"><code>promise::set_exception()</code></link> is called, 8836 throws the indicated exception. 8837 </para> 8838 </listitem> 8839 </varlistentry> 8840 <varlistentry> 8841 <term>Postcondition:</term> 8842 <listitem> 8843 <para> 8844 <code><phrase role="keyword">false</phrase> <phrase role="special">==</phrase> 8845 <phrase role="identifier">valid</phrase><phrase role="special">()</phrase></code> 8846 </para> 8847 </listitem> 8848 </varlistentry> 8849 <varlistentry> 8850 <term>Throws:</term> 8851 <listitem> 8852 <para> 8853 <code><phrase role="identifier">future_error</phrase></code> with 8854 error condition <code><phrase role="identifier">future_errc</phrase><phrase 8855 role="special">::</phrase><phrase role="identifier">no_state</phrase></code>, 8856 <code><phrase role="identifier">future_errc</phrase><phrase role="special">::</phrase><phrase 8857 role="identifier">broken_promise</phrase></code>. Any exception passed 8858 to <code><phrase role="identifier">promise</phrase><phrase role="special">::</phrase><phrase 8859 role="identifier">set_exception</phrase><phrase role="special">()</phrase></code>. 8860 </para> 8861 </listitem> 8862 </varlistentry> 8863 </variablelist> 8864 <para> 8865 <bridgehead renderas="sect4" id="future_get_exception_ptr_bridgehead"> 8866 <phrase id="future_get_exception_ptr"/> 8867 <link linkend="future_get_exception_ptr">Member 8868 function <code>get_exception_ptr</code>()</link> 8869</bridgehead> 8870 </para> 8871<programlisting><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">exception_ptr</phrase> <phrase role="identifier">get_exception_ptr</phrase><phrase role="special">();</phrase> 8872</programlisting> 8873 <variablelist> 8874 <title></title> 8875 <varlistentry> 8876 <term>Precondition:</term> 8877 <listitem> 8878 <para> 8879 <code><phrase role="keyword">true</phrase> <phrase role="special">==</phrase> 8880 <phrase role="identifier">valid</phrase><phrase role="special">()</phrase></code> 8881 </para> 8882 </listitem> 8883 </varlistentry> 8884 <varlistentry> 8885 <term>Returns:</term> 8886 <listitem> 8887 <para> 8888 Waits until <link linkend="promise_set_value"><code>promise::set_value()</code></link> or <link linkend="promise_set_exception"><code>promise::set_exception()</code></link> is 8889 called. If <code><phrase role="identifier">set_value</phrase><phrase 8890 role="special">()</phrase></code> is called, returns a default-constructed 8891 <code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase 8892 role="identifier">exception_ptr</phrase></code>. If <code><phrase 8893 role="identifier">set_exception</phrase><phrase role="special">()</phrase></code> 8894 is called, returns the passed <code><phrase role="identifier">std</phrase><phrase 8895 role="special">::</phrase><phrase role="identifier">exception_ptr</phrase></code>. 8896 </para> 8897 </listitem> 8898 </varlistentry> 8899 <varlistentry> 8900 <term>Throws:</term> 8901 <listitem> 8902 <para> 8903 <code><phrase role="identifier">future_error</phrase></code> with 8904 error condition <code><phrase role="identifier">future_errc</phrase><phrase 8905 role="special">::</phrase><phrase role="identifier">no_state</phrase></code>. 8906 </para> 8907 </listitem> 8908 </varlistentry> 8909 <varlistentry> 8910 <term>Note:</term> 8911 <listitem> 8912 <para> 8913 <code><phrase role="identifier">get_exception_ptr</phrase><phrase 8914 role="special">()</phrase></code> does <emphasis>not</emphasis> invalidate 8915 the <code>future</code>. After calling <code><phrase role="identifier">get_exception_ptr</phrase><phrase 8916 role="special">()</phrase></code>, you may still call <link linkend="future_get"><code>future::get()</code></link>. 8917 </para> 8918 </listitem> 8919 </varlistentry> 8920 </variablelist> 8921 <para> 8922 <bridgehead renderas="sect4" id="future_wait_bridgehead"> 8923 <phrase id="future_wait"/> 8924 <link linkend="future_wait">Member function <code>wait</code>()</link> 8925</bridgehead> 8926 </para> 8927<programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">wait</phrase><phrase role="special">();</phrase> 8928</programlisting> 8929 <variablelist> 8930 <title></title> 8931 <varlistentry> 8932 <term>Effects:</term> 8933 <listitem> 8934 <para> 8935 Waits until <link linkend="promise_set_value"><code>promise::set_value()</code></link> or <link linkend="promise_set_exception"><code>promise::set_exception()</code></link> is 8936 called. 8937 </para> 8938 </listitem> 8939 </varlistentry> 8940 <varlistentry> 8941 <term>Throws:</term> 8942 <listitem> 8943 <para> 8944 <code><phrase role="identifier">future_error</phrase></code> with 8945 error condition <code><phrase role="identifier">future_errc</phrase><phrase 8946 role="special">::</phrase><phrase role="identifier">no_state</phrase></code>. 8947 </para> 8948 </listitem> 8949 </varlistentry> 8950 </variablelist> 8951 <para> 8952 <bridgehead renderas="sect4" id="future_wait_for_bridgehead"> 8953 <phrase id="future_wait_for"/> 8954 <link linkend="future_wait_for">Templated member 8955 function <code>wait_for</code>()</link> 8956</bridgehead> 8957 </para> 8958<programlisting><phrase role="keyword">template</phrase><phrase role="special"><</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">></phrase> 8959<phrase role="identifier">future_status</phrase> <phrase role="identifier">wait_for</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">duration</phrase><phrase role="special"><</phrase> <phrase role="identifier">Rep</phrase><phrase role="special">,</phrase> <phrase role="identifier">Period</phrase> <phrase role="special">></phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">timeout_duration</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase> 8960</programlisting> 8961 <variablelist> 8962 <title></title> 8963 <varlistentry> 8964 <term>Effects:</term> 8965 <listitem> 8966 <para> 8967 Waits until <link linkend="promise_set_value"><code>promise::set_value()</code></link> or <link linkend="promise_set_exception"><code>promise::set_exception()</code></link> is 8968 called, or <code><phrase role="identifier">timeout_duration</phrase></code> 8969 has passed. 8970 </para> 8971 </listitem> 8972 </varlistentry> 8973 <varlistentry> 8974 <term>Result:</term> 8975 <listitem> 8976 <para> 8977 A <code><phrase role="identifier">future_status</phrase></code> is 8978 returned indicating the reason for returning. 8979 </para> 8980 </listitem> 8981 </varlistentry> 8982 <varlistentry> 8983 <term>Throws:</term> 8984 <listitem> 8985 <para> 8986 <code><phrase role="identifier">future_error</phrase></code> with 8987 error condition <code><phrase role="identifier">future_errc</phrase><phrase 8988 role="special">::</phrase><phrase role="identifier">no_state</phrase></code> 8989 or timeout-related exceptions. 8990 </para> 8991 </listitem> 8992 </varlistentry> 8993 </variablelist> 8994 <para> 8995 <bridgehead renderas="sect4" id="future_wait_until_bridgehead"> 8996 <phrase id="future_wait_until"/> 8997 <link linkend="future_wait_until">Templated 8998 member function <code>wait_until</code>()</link> 8999</bridgehead> 9000 </para> 9001<programlisting><phrase role="keyword">template</phrase><phrase role="special"><</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Clock</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Duration</phrase> <phrase role="special">></phrase> 9002<phrase role="identifier">future_status</phrase> <phrase role="identifier">wait_until</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">time_point</phrase><phrase role="special"><</phrase> <phrase role="identifier">Clock</phrase><phrase role="special">,</phrase> <phrase role="identifier">Duration</phrase> <phrase role="special">></phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">timeout_time</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase> 9003</programlisting> 9004 <variablelist> 9005 <title></title> 9006 <varlistentry> 9007 <term>Effects:</term> 9008 <listitem> 9009 <para> 9010 Waits until <link linkend="promise_set_value"><code>promise::set_value()</code></link> or <link linkend="promise_set_exception"><code>promise::set_exception()</code></link> is 9011 called, or <code><phrase role="identifier">timeout_time</phrase></code> 9012 has passed. 9013 </para> 9014 </listitem> 9015 </varlistentry> 9016 <varlistentry> 9017 <term>Result:</term> 9018 <listitem> 9019 <para> 9020 A <code><phrase role="identifier">future_status</phrase></code> is 9021 returned indicating the reason for returning. 9022 </para> 9023 </listitem> 9024 </varlistentry> 9025 <varlistentry> 9026 <term>Throws:</term> 9027 <listitem> 9028 <para> 9029 <code><phrase role="identifier">future_error</phrase></code> with 9030 error condition <code><phrase role="identifier">future_errc</phrase><phrase 9031 role="special">::</phrase><phrase role="identifier">no_state</phrase></code> 9032 or timeout-related exceptions. 9033 </para> 9034 </listitem> 9035 </varlistentry> 9036 </variablelist> 9037 <para> 9038 <bridgehead renderas="sect4" id="class_shared_future_bridgehead"> 9039 <phrase id="class_shared_future"/> 9040 <link linkend="class_shared_future">Template 9041 <code>shared_future<></code></link> 9042</bridgehead> 9043 </para> 9044 <para> 9045 A <link linkend="class_shared_future"><code>shared_future<></code></link> contains a <link linkend="shared_state">shared 9046 state</link> which might be shared with other <link linkend="class_shared_future"><code>shared_future<></code></link> instances. 9047 </para> 9048<programlisting><phrase role="preprocessor">#include</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">future</phrase><phrase role="special">/</phrase><phrase role="identifier">future</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">></phrase> 9049 9050<phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase> 9051<phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase> 9052 9053<phrase role="keyword">template</phrase><phrase role="special"><</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">R</phrase> <phrase role="special">></phrase> 9054<phrase role="keyword">class</phrase> <phrase role="identifier">shared_future</phrase> <phrase role="special">{</phrase> 9055<phrase role="keyword">public</phrase><phrase role="special">:</phrase> 9056 <phrase role="identifier">shared_future</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 9057 9058 <phrase role="special">~</phrase><phrase role="identifier">shared_future</phrase><phrase role="special">();</phrase> 9059 9060 <phrase role="identifier">shared_future</phrase><phrase role="special">(</phrase> <phrase role="identifier">shared_future</phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">other</phrase><phrase role="special">);</phrase> 9061 9062 <phrase role="identifier">shared_future</phrase><phrase role="special">(</phrase> <phrase role="identifier">future</phrase><phrase role="special"><</phrase> <phrase role="identifier">R</phrase> <phrase role="special">></phrase> <phrase role="special">&&</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 9063 9064 <phrase role="identifier">shared_future</phrase><phrase role="special">(</phrase> <phrase role="identifier">shared_future</phrase> <phrase role="special">&&</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 9065 9066 <phrase role="identifier">shared_future</phrase> <phrase role="special">&</phrase> <phrase role="keyword">operator</phrase><phrase role="special">=(</phrase> <phrase role="identifier">shared_future</phrase> <phrase role="special">&&</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 9067 9068 <phrase role="identifier">shared_future</phrase> <phrase role="special">&</phrase> <phrase role="keyword">operator</phrase><phrase role="special">=(</phrase> <phrase role="identifier">future</phrase><phrase role="special"><</phrase> <phrase role="identifier">R</phrase> <phrase role="special">></phrase> <phrase role="special">&&</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 9069 9070 <phrase role="identifier">shared_future</phrase> <phrase role="special">&</phrase> <phrase role="keyword">operator</phrase><phrase role="special">=(</phrase> <phrase role="identifier">shared_future</phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 9071 9072 <phrase role="keyword">bool</phrase> <phrase role="identifier">valid</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 9073 9074 <phrase role="identifier">R</phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">get</phrase><phrase role="special">();</phrase> <phrase role="comment">// member only of generic shared_future template</phrase> 9075 <phrase role="identifier">R</phrase> <phrase role="special">&</phrase> <phrase role="identifier">get</phrase><phrase role="special">();</phrase> <phrase role="comment">// member only of shared_future< R & > template specialization</phrase> 9076 <phrase role="keyword">void</phrase> <phrase role="identifier">get</phrase><phrase role="special">();</phrase> <phrase role="comment">// member only of shared_future< void > template specialization</phrase> 9077 9078 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">exception_ptr</phrase> <phrase role="identifier">get_exception_ptr</phrase><phrase role="special">();</phrase> 9079 9080 <phrase role="keyword">void</phrase> <phrase role="identifier">wait</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase> 9081 9082 <phrase role="keyword">template</phrase><phrase role="special"><</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">></phrase> 9083 <phrase role="identifier">future_status</phrase> <phrase role="identifier">wait_for</phrase><phrase role="special">(</phrase> 9084 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">duration</phrase><phrase role="special"><</phrase> <phrase role="identifier">Rep</phrase><phrase role="special">,</phrase> <phrase role="identifier">Period</phrase> <phrase role="special">></phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">timeout_duration</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase> 9085 9086 <phrase role="keyword">template</phrase><phrase role="special"><</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Clock</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Duration</phrase> <phrase role="special">></phrase> 9087 <phrase role="identifier">future_status</phrase> <phrase role="identifier">wait_until</phrase><phrase role="special">(</phrase> 9088 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">time_point</phrase><phrase role="special"><</phrase> <phrase role="identifier">Clock</phrase><phrase role="special">,</phrase> <phrase role="identifier">Duration</phrase> <phrase role="special">></phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">timeout_time</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase> 9089<phrase role="special">};</phrase> 9090 9091<phrase role="special">}}</phrase> 9092</programlisting> 9093 <bridgehead renderas="sect5" id="fiber.synchronization.futures.future.h7"> 9094 <phrase id="fiber.synchronization.futures.future.default_constructor0"/><link 9095 linkend="fiber.synchronization.futures.future.default_constructor0">Default 9096 constructor</link> 9097 </bridgehead> 9098<programlisting><phrase role="identifier">shared_future</phrase><phrase role="special">();</phrase> 9099</programlisting> 9100 <variablelist> 9101 <title></title> 9102 <varlistentry> 9103 <term>Effects:</term> 9104 <listitem> 9105 <para> 9106 Creates a shared_future with no <link linkend="shared_state">shared 9107 state</link>. After construction <code><phrase role="keyword">false</phrase> 9108 <phrase role="special">==</phrase> <phrase role="identifier">valid</phrase><phrase 9109 role="special">()</phrase></code>. 9110 </para> 9111 </listitem> 9112 </varlistentry> 9113 <varlistentry> 9114 <term>Throws:</term> 9115 <listitem> 9116 <para> 9117 Nothing. 9118 </para> 9119 </listitem> 9120 </varlistentry> 9121 </variablelist> 9122 <bridgehead renderas="sect5" id="fiber.synchronization.futures.future.h8"> 9123 <phrase id="fiber.synchronization.futures.future.move_constructor0"/><link 9124 linkend="fiber.synchronization.futures.future.move_constructor0">Move constructor</link> 9125 </bridgehead> 9126<programlisting><phrase role="identifier">shared_future</phrase><phrase role="special">(</phrase> <phrase role="identifier">future</phrase><phrase role="special"><</phrase> <phrase role="identifier">R</phrase> <phrase role="special">></phrase> <phrase role="special">&&</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 9127<phrase role="identifier">shared_future</phrase><phrase role="special">(</phrase> <phrase role="identifier">shared_future</phrase> <phrase role="special">&&</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 9128</programlisting> 9129 <variablelist> 9130 <title></title> 9131 <varlistentry> 9132 <term>Effects:</term> 9133 <listitem> 9134 <para> 9135 Constructs a shared_future with the <link linkend="shared_state">shared 9136 state</link> of other. After construction <code><phrase role="keyword">false</phrase> 9137 <phrase role="special">==</phrase> <phrase role="identifier">other</phrase><phrase 9138 role="special">.</phrase><phrase role="identifier">valid</phrase><phrase 9139 role="special">()</phrase></code>. 9140 </para> 9141 </listitem> 9142 </varlistentry> 9143 <varlistentry> 9144 <term>Throws:</term> 9145 <listitem> 9146 <para> 9147 Nothing. 9148 </para> 9149 </listitem> 9150 </varlistentry> 9151 </variablelist> 9152 <bridgehead renderas="sect5" id="fiber.synchronization.futures.future.h9"> 9153 <phrase id="fiber.synchronization.futures.future.copy_constructor"/><link 9154 linkend="fiber.synchronization.futures.future.copy_constructor">Copy constructor</link> 9155 </bridgehead> 9156<programlisting><phrase role="identifier">shared_future</phrase><phrase role="special">(</phrase> <phrase role="identifier">shared_future</phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 9157</programlisting> 9158 <variablelist> 9159 <title></title> 9160 <varlistentry> 9161 <term>Effects:</term> 9162 <listitem> 9163 <para> 9164 Constructs a shared_future with the <link linkend="shared_state">shared 9165 state</link> of other. After construction <code><phrase role="identifier">other</phrase><phrase 9166 role="special">.</phrase><phrase role="identifier">valid</phrase><phrase 9167 role="special">()</phrase></code> is unchanged. 9168 </para> 9169 </listitem> 9170 </varlistentry> 9171 <varlistentry> 9172 <term>Throws:</term> 9173 <listitem> 9174 <para> 9175 Nothing. 9176 </para> 9177 </listitem> 9178 </varlistentry> 9179 </variablelist> 9180 <bridgehead renderas="sect5" id="fiber.synchronization.futures.future.h10"> 9181 <phrase id="fiber.synchronization.futures.future.destructor0"/><link linkend="fiber.synchronization.futures.future.destructor0">Destructor</link> 9182 </bridgehead> 9183<programlisting><phrase role="special">~</phrase><phrase role="identifier">shared_future</phrase><phrase role="special">();</phrase> 9184</programlisting> 9185 <variablelist> 9186 <title></title> 9187 <varlistentry> 9188 <term>Effects:</term> 9189 <listitem> 9190 <para> 9191 Destroys the shared_future; ownership is abandoned if not shared. 9192 </para> 9193 </listitem> 9194 </varlistentry> 9195 <varlistentry> 9196 <term>Note:</term> 9197 <listitem> 9198 <para> 9199 <code>~shared_future()</code> does <emphasis>not</emphasis> block the calling fiber. 9200 </para> 9201 </listitem> 9202 </varlistentry> 9203 </variablelist> 9204 <para> 9205 <bridgehead renderas="sect4" id="shared_future_operator_assign_bridgehead"> 9206 <phrase id="shared_future_operator_assign"/> 9207 <link linkend="shared_future_operator_assign">Member 9208 function <code>operator=</code>()</link> 9209</bridgehead> 9210 </para> 9211<programlisting><phrase role="identifier">shared_future</phrase> <phrase role="special">&</phrase> <phrase role="keyword">operator</phrase><phrase role="special">=(</phrase> <phrase role="identifier">future</phrase><phrase role="special"><</phrase> <phrase role="identifier">R</phrase> <phrase role="special">></phrase> <phrase role="special">&&</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 9212<phrase role="identifier">shared_future</phrase> <phrase role="special">&</phrase> <phrase role="keyword">operator</phrase><phrase role="special">=(</phrase> <phrase role="identifier">shared_future</phrase> <phrase role="special">&&</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 9213<phrase role="identifier">shared_future</phrase> <phrase role="special">&</phrase> <phrase role="keyword">operator</phrase><phrase role="special">=(</phrase> <phrase role="identifier">shared_future</phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 9214</programlisting> 9215 <variablelist> 9216 <title></title> 9217 <varlistentry> 9218 <term>Effects:</term> 9219 <listitem> 9220 <para> 9221 Moves or copies the <link linkend="shared_state">shared state</link> 9222 of other to <code><phrase role="keyword">this</phrase></code>. After 9223 the assignment, the state of <code><phrase role="identifier">other</phrase><phrase 9224 role="special">.</phrase><phrase role="identifier">valid</phrase><phrase 9225 role="special">()</phrase></code> depends on which overload was invoked: 9226 unchanged for the overload accepting <code><phrase role="identifier">shared_future</phrase> 9227 <phrase role="keyword">const</phrase><phrase role="special">&</phrase></code>, 9228 otherwise <code><phrase role="keyword">false</phrase></code>. 9229 </para> 9230 </listitem> 9231 </varlistentry> 9232 <varlistentry> 9233 <term>Throws:</term> 9234 <listitem> 9235 <para> 9236 Nothing. 9237 </para> 9238 </listitem> 9239 </varlistentry> 9240 </variablelist> 9241 <para> 9242 <bridgehead renderas="sect4" id="shared_future_valid_bridgehead"> 9243 <phrase id="shared_future_valid"/> 9244 <link linkend="shared_future_valid">Member 9245 function <code>valid</code>()</link> 9246</bridgehead> 9247 </para> 9248<programlisting><phrase role="keyword">bool</phrase> <phrase role="identifier">valid</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 9249</programlisting> 9250 <variablelist> 9251 <title></title> 9252 <varlistentry> 9253 <term>Effects:</term> 9254 <listitem> 9255 <para> 9256 Returns <code><phrase role="keyword">true</phrase></code> if shared_future 9257 contains a <link linkend="shared_state">shared state</link>. 9258 </para> 9259 </listitem> 9260 </varlistentry> 9261 <varlistentry> 9262 <term>Throws:</term> 9263 <listitem> 9264 <para> 9265 Nothing. 9266 </para> 9267 </listitem> 9268 </varlistentry> 9269 </variablelist> 9270 <para> 9271 <bridgehead renderas="sect4" id="shared_future_get_bridgehead"> 9272 <phrase id="shared_future_get"/> 9273 <link linkend="shared_future_get">Member function 9274 <code>get</code>()</link> 9275</bridgehead> 9276 </para> 9277<programlisting><phrase role="identifier">R</phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">get</phrase><phrase role="special">();</phrase> <phrase role="comment">// member only of generic shared_future template</phrase> 9278<phrase role="identifier">R</phrase> <phrase role="special">&</phrase> <phrase role="identifier">get</phrase><phrase role="special">();</phrase> <phrase role="comment">// member only of shared_future< R & > template specialization</phrase> 9279<phrase role="keyword">void</phrase> <phrase role="identifier">get</phrase><phrase role="special">();</phrase> <phrase role="comment">// member only of shared_future< void > template specialization</phrase> 9280</programlisting> 9281 <variablelist> 9282 <title></title> 9283 <varlistentry> 9284 <term>Precondition:</term> 9285 <listitem> 9286 <para> 9287 <code><phrase role="keyword">true</phrase> <phrase role="special">==</phrase> 9288 <phrase role="identifier">valid</phrase><phrase role="special">()</phrase></code> 9289 </para> 9290 </listitem> 9291 </varlistentry> 9292 <varlistentry> 9293 <term>Returns:</term> 9294 <listitem> 9295 <para> 9296 Waits until <link linkend="promise_set_value"><code>promise::set_value()</code></link> or <link linkend="promise_set_exception"><code>promise::set_exception()</code></link> is 9297 called. If <link linkend="promise_set_value"><code>promise::set_value()</code></link> is called, returns 9298 the value. If <link linkend="promise_set_exception"><code>promise::set_exception()</code></link> is called, 9299 throws the indicated exception. 9300 </para> 9301 </listitem> 9302 </varlistentry> 9303 <varlistentry> 9304 <term>Postcondition:</term> 9305 <listitem> 9306 <para> 9307 <code><phrase role="keyword">false</phrase> <phrase role="special">==</phrase> 9308 <phrase role="identifier">valid</phrase><phrase role="special">()</phrase></code> 9309 </para> 9310 </listitem> 9311 </varlistentry> 9312 <varlistentry> 9313 <term>Throws:</term> 9314 <listitem> 9315 <para> 9316 <code><phrase role="identifier">future_error</phrase></code> with 9317 error condition <code><phrase role="identifier">future_errc</phrase><phrase 9318 role="special">::</phrase><phrase role="identifier">no_state</phrase></code>, 9319 <code><phrase role="identifier">future_errc</phrase><phrase role="special">::</phrase><phrase 9320 role="identifier">broken_promise</phrase></code>. Any exception passed 9321 to <code><phrase role="identifier">promise</phrase><phrase role="special">::</phrase><phrase 9322 role="identifier">set_exception</phrase><phrase role="special">()</phrase></code>. 9323 </para> 9324 </listitem> 9325 </varlistentry> 9326 </variablelist> 9327 <para> 9328 <bridgehead renderas="sect4" id="shared_future_get_exception_ptr_bridgehead"> 9329 <phrase id="shared_future_get_exception_ptr"/> 9330 <link linkend="shared_future_get_exception_ptr">Member 9331 function <code>get_exception_ptr</code>()</link> 9332</bridgehead> 9333 </para> 9334<programlisting><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">exception_ptr</phrase> <phrase role="identifier">get_exception_ptr</phrase><phrase role="special">();</phrase> 9335</programlisting> 9336 <variablelist> 9337 <title></title> 9338 <varlistentry> 9339 <term>Precondition:</term> 9340 <listitem> 9341 <para> 9342 <code><phrase role="keyword">true</phrase> <phrase role="special">==</phrase> 9343 <phrase role="identifier">valid</phrase><phrase role="special">()</phrase></code> 9344 </para> 9345 </listitem> 9346 </varlistentry> 9347 <varlistentry> 9348 <term>Returns:</term> 9349 <listitem> 9350 <para> 9351 Waits until <link linkend="promise_set_value"><code>promise::set_value()</code></link> or <link linkend="promise_set_exception"><code>promise::set_exception()</code></link> is 9352 called. If <code><phrase role="identifier">set_value</phrase><phrase 9353 role="special">()</phrase></code> is called, returns a default-constructed 9354 <code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase 9355 role="identifier">exception_ptr</phrase></code>. If <code><phrase 9356 role="identifier">set_exception</phrase><phrase role="special">()</phrase></code> 9357 is called, returns the passed <code><phrase role="identifier">std</phrase><phrase 9358 role="special">::</phrase><phrase role="identifier">exception_ptr</phrase></code>. 9359 </para> 9360 </listitem> 9361 </varlistentry> 9362 <varlistentry> 9363 <term>Throws:</term> 9364 <listitem> 9365 <para> 9366 <code><phrase role="identifier">future_error</phrase></code> with 9367 error condition <code><phrase role="identifier">future_errc</phrase><phrase 9368 role="special">::</phrase><phrase role="identifier">no_state</phrase></code>. 9369 </para> 9370 </listitem> 9371 </varlistentry> 9372 <varlistentry> 9373 <term>Note:</term> 9374 <listitem> 9375 <para> 9376 <code><phrase role="identifier">get_exception_ptr</phrase><phrase 9377 role="special">()</phrase></code> does <emphasis>not</emphasis> invalidate 9378 the <code>shared_future</code>. After calling <code><phrase role="identifier">get_exception_ptr</phrase><phrase 9379 role="special">()</phrase></code>, you may still call <link linkend="shared_future_get"><code>shared_future::get()</code></link>. 9380 </para> 9381 </listitem> 9382 </varlistentry> 9383 </variablelist> 9384 <para> 9385 <bridgehead renderas="sect4" id="shared_future_wait_bridgehead"> 9386 <phrase id="shared_future_wait"/> 9387 <link linkend="shared_future_wait">Member 9388 function <code>wait</code>()</link> 9389</bridgehead> 9390 </para> 9391<programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">wait</phrase><phrase role="special">();</phrase> 9392</programlisting> 9393 <variablelist> 9394 <title></title> 9395 <varlistentry> 9396 <term>Effects:</term> 9397 <listitem> 9398 <para> 9399 Waits until <link linkend="promise_set_value"><code>promise::set_value()</code></link> or <link linkend="promise_set_exception"><code>promise::set_exception()</code></link> is 9400 called. 9401 </para> 9402 </listitem> 9403 </varlistentry> 9404 <varlistentry> 9405 <term>Throws:</term> 9406 <listitem> 9407 <para> 9408 <code><phrase role="identifier">future_error</phrase></code> with 9409 error condition <code><phrase role="identifier">future_errc</phrase><phrase 9410 role="special">::</phrase><phrase role="identifier">no_state</phrase></code>. 9411 </para> 9412 </listitem> 9413 </varlistentry> 9414 </variablelist> 9415 <para> 9416 <bridgehead renderas="sect4" id="shared_future_wait_for_bridgehead"> 9417 <phrase id="shared_future_wait_for"/> 9418 <link linkend="shared_future_wait_for">Templated 9419 member function <code>wait_for</code>()</link> 9420</bridgehead> 9421 </para> 9422<programlisting><phrase role="keyword">template</phrase><phrase role="special"><</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">></phrase> 9423<phrase role="identifier">future_status</phrase> <phrase role="identifier">wait_for</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">duration</phrase><phrase role="special"><</phrase> <phrase role="identifier">Rep</phrase><phrase role="special">,</phrase> <phrase role="identifier">Period</phrase> <phrase role="special">></phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">timeout_duration</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase> 9424</programlisting> 9425 <variablelist> 9426 <title></title> 9427 <varlistentry> 9428 <term>Effects:</term> 9429 <listitem> 9430 <para> 9431 Waits until <link linkend="promise_set_value"><code>promise::set_value()</code></link> or <link linkend="promise_set_exception"><code>promise::set_exception()</code></link> is 9432 called, or <code><phrase role="identifier">timeout_duration</phrase></code> 9433 has passed. 9434 </para> 9435 </listitem> 9436 </varlistentry> 9437 <varlistentry> 9438 <term>Result:</term> 9439 <listitem> 9440 <para> 9441 A <code><phrase role="identifier">future_status</phrase></code> is 9442 returned indicating the reason for returning. 9443 </para> 9444 </listitem> 9445 </varlistentry> 9446 <varlistentry> 9447 <term>Throws:</term> 9448 <listitem> 9449 <para> 9450 <code><phrase role="identifier">future_error</phrase></code> with 9451 error condition <code><phrase role="identifier">future_errc</phrase><phrase 9452 role="special">::</phrase><phrase role="identifier">no_state</phrase></code> 9453 or timeout-related exceptions. 9454 </para> 9455 </listitem> 9456 </varlistentry> 9457 </variablelist> 9458 <para> 9459 <bridgehead renderas="sect4" id="shared_future_wait_until_bridgehead"> 9460 <phrase id="shared_future_wait_until"/> 9461 <link linkend="shared_future_wait_until">Templated 9462 member function <code>wait_until</code>()</link> 9463</bridgehead> 9464 </para> 9465<programlisting><phrase role="keyword">template</phrase><phrase role="special"><</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Clock</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Duration</phrase> <phrase role="special">></phrase> 9466<phrase role="identifier">future_status</phrase> <phrase role="identifier">wait_until</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">time_point</phrase><phrase role="special"><</phrase> <phrase role="identifier">Clock</phrase><phrase role="special">,</phrase> <phrase role="identifier">Duration</phrase> <phrase role="special">></phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">timeout_time</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase> 9467</programlisting> 9468 <variablelist> 9469 <title></title> 9470 <varlistentry> 9471 <term>Effects:</term> 9472 <listitem> 9473 <para> 9474 Waits until <link linkend="promise_set_value"><code>promise::set_value()</code></link> or <link linkend="promise_set_exception"><code>promise::set_exception()</code></link> is 9475 called, or <code><phrase role="identifier">timeout_time</phrase></code> 9476 has passed. 9477 </para> 9478 </listitem> 9479 </varlistentry> 9480 <varlistentry> 9481 <term>Result:</term> 9482 <listitem> 9483 <para> 9484 A <code><phrase role="identifier">future_status</phrase></code> is 9485 returned indicating the reason for returning. 9486 </para> 9487 </listitem> 9488 </varlistentry> 9489 <varlistentry> 9490 <term>Throws:</term> 9491 <listitem> 9492 <para> 9493 <code><phrase role="identifier">future_error</phrase></code> with 9494 error condition <code><phrase role="identifier">future_errc</phrase><phrase 9495 role="special">::</phrase><phrase role="identifier">no_state</phrase></code> 9496 or timeout-related exceptions. 9497 </para> 9498 </listitem> 9499 </varlistentry> 9500 </variablelist> 9501 <para> 9502 <bridgehead renderas="sect4" id="fibers_async_bridgehead"> 9503 <phrase id="fibers_async"/> 9504 <link linkend="fibers_async">Non-member function <code>fibers::async()</code></link> 9505</bridgehead> 9506 </para> 9507<programlisting><phrase role="preprocessor">#include</phrase> <phrase role="special"><</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">></phrase> 9508 9509<phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase> 9510<phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase> 9511 9512<phrase role="keyword">template</phrase><phrase role="special"><</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">></phrase> 9513<phrase role="identifier">future</phrase><phrase role="special"><</phrase> 9514 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">result_of_t</phrase><phrase role="special"><</phrase> 9515 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">decay_t</phrase><phrase role="special"><</phrase> <phrase role="identifier">Function</phrase> <phrase role="special">>(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">decay_t</phrase><phrase role="special"><</phrase> <phrase role="identifier">Args</phrase> <phrase role="special">></phrase> <phrase role="special">...</phrase> <phrase role="special">)</phrase> 9516 <phrase role="special">></phrase> 9517<phrase role="special">></phrase> 9518<phrase role="identifier">async</phrase><phrase role="special">(</phrase> <phrase role="identifier">Function</phrase> <phrase role="special">&&</phrase> <phrase role="identifier">fn</phrase><phrase role="special">,</phrase> <phrase role="identifier">Args</phrase> <phrase role="special">&&</phrase> <phrase role="special">...</phrase> <phrase role="identifier">args</phrase><phrase role="special">);</phrase> 9519 9520<phrase role="keyword">template</phrase><phrase role="special"><</phrase> <phrase role="keyword">class</phrase> <phrase role="identifier">Function</phrase><phrase role="special">,</phrase> <phrase role="keyword">class</phrase> <phrase role="special">...</phrase> <phrase role="identifier">Args</phrase> <phrase role="special">></phrase> 9521<phrase role="identifier">future</phrase><phrase role="special"><</phrase> 9522 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">result_of_t</phrase><phrase role="special"><</phrase> 9523 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">decay_t</phrase><phrase role="special"><</phrase> <phrase role="identifier">Function</phrase> <phrase role="special">>(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">decay_t</phrase><phrase role="special"><</phrase> <phrase role="identifier">Args</phrase> <phrase role="special">></phrase> <phrase role="special">...</phrase> <phrase role="special">)</phrase> 9524 <phrase role="special">></phrase> 9525<phrase role="special">></phrase> 9526<phrase role="identifier">async</phrase><phrase role="special">(</phrase> <link linkend="class_launch"><code><phrase role="identifier">launch</phrase></code></link> <phrase role="identifier">policy</phrase><phrase role="special">,</phrase> <phrase role="identifier">Function</phrase> <phrase role="special">&&</phrase> <phrase role="identifier">fn</phrase><phrase role="special">,</phrase> <phrase role="identifier">Args</phrase> <phrase role="special">&&</phrase> <phrase role="special">...</phrase> <phrase role="identifier">args</phrase><phrase role="special">);</phrase> 9527 9528<phrase role="keyword">template</phrase><phrase role="special"><</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">></phrase> 9529<phrase role="identifier">future</phrase><phrase role="special"><</phrase> 9530 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">result_of_t</phrase><phrase role="special"><</phrase> 9531 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">decay_t</phrase><phrase role="special"><</phrase> <phrase role="identifier">Function</phrase> <phrase role="special">>(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">decay_t</phrase><phrase role="special"><</phrase> <phrase role="identifier">Args</phrase> <phrase role="special">></phrase> <phrase role="special">...</phrase> <phrase role="special">)</phrase> 9532 <phrase role="special">></phrase> 9533<phrase role="special">></phrase> 9534<phrase role="identifier">async</phrase><phrase role="special">(</phrase> <link linkend="class_launch"><code><phrase role="identifier">launch</phrase></code></link> <phrase role="identifier">policy</phrase><phrase role="special">,</phrase> <ulink url="http://en.cppreference.com/w/cpp/memory/allocator_arg_t"><code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">allocator_arg_t</phrase></code></ulink><phrase role="special">,</phrase> <link linkend="stack_allocator_concept"><code><phrase role="identifier">StackAllocator</phrase></code></link> <phrase role="identifier">salloc</phrase><phrase role="special">,</phrase> 9535 <phrase role="identifier">Function</phrase> <phrase role="special">&&</phrase> <phrase role="identifier">fn</phrase><phrase role="special">,</phrase> <phrase role="identifier">Args</phrase> <phrase role="special">&&</phrase> <phrase role="special">...</phrase> <phrase role="identifier">args</phrase><phrase role="special">);</phrase> 9536 9537<phrase role="keyword">template</phrase><phrase role="special"><</phrase> <phrase role="keyword">typename</phrase> <link linkend="stack_allocator_concept"><code><phrase role="identifier">StackAllocator</phrase></code></link><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Allocator</phrase><phrase role="special">,</phrase> <phrase role="keyword">class</phrase> <phrase role="identifier">Function</phrase><phrase role="special">,</phrase> <phrase role="keyword">class</phrase> <phrase role="special">...</phrase> <phrase role="identifier">Args</phrase> <phrase role="special">></phrase> 9538<phrase role="identifier">future</phrase><phrase role="special"><</phrase> 9539 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">result_of_t</phrase><phrase role="special"><</phrase> 9540 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">decay_t</phrase><phrase role="special"><</phrase> <phrase role="identifier">Function</phrase> <phrase role="special">>(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">decay_t</phrase><phrase role="special"><</phrase> <phrase role="identifier">Args</phrase> <phrase role="special">></phrase> <phrase role="special">...</phrase> <phrase role="special">)</phrase> 9541 <phrase role="special">></phrase> 9542<phrase role="special">></phrase> 9543<phrase role="identifier">async</phrase><phrase role="special">(</phrase> <link linkend="class_launch"><code><phrase role="identifier">launch</phrase></code></link> <phrase role="identifier">policy</phrase><phrase role="special">,</phrase> <ulink url="http://en.cppreference.com/w/cpp/memory/allocator_arg_t"><code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">allocator_arg_t</phrase></code></ulink><phrase role="special">,</phrase> <link linkend="stack_allocator_concept"><code><phrase role="identifier">StackAllocator</phrase></code></link> <phrase role="identifier">salloc</phrase><phrase role="special">,</phrase> 9544 <phrase role="identifier">Allocator</phrase> <phrase role="identifier">alloc</phrase><phrase role="special">,</phrase> <phrase role="identifier">Function</phrase> <phrase role="special">&&</phrase> <phrase role="identifier">fn</phrase><phrase role="special">,</phrase> <phrase role="identifier">Args</phrase> <phrase role="special">&&</phrase> <phrase role="special">...</phrase> <phrase role="identifier">args</phrase><phrase role="special">);</phrase> 9545 9546<phrase role="special">}}</phrase> 9547</programlisting> 9548 <variablelist> 9549 <title></title> 9550 <varlistentry> 9551 <term>Effects:</term> 9552 <listitem> 9553 <para> 9554 Executes <code><phrase role="identifier">fn</phrase></code> in a 9555 <link linkend="class_fiber"><code>fiber</code></link> and returns an associated <link linkend="class_future"><code>future<></code></link>. 9556 </para> 9557 </listitem> 9558 </varlistentry> 9559 <varlistentry> 9560 <term>Result:</term> 9561 <listitem> 9562 <para> 9563<programlisting><phrase role="identifier">future</phrase><phrase role="special"><</phrase> 9564 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">result_of_t</phrase><phrase role="special"><</phrase> 9565 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">decay_t</phrase><phrase role="special"><</phrase> <phrase role="identifier">Function</phrase> <phrase role="special">>(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">decay_t</phrase><phrase role="special"><</phrase> <phrase role="identifier">Args</phrase> <phrase role="special">></phrase> <phrase role="special">...</phrase> <phrase role="special">)</phrase> 9566 <phrase role="special">></phrase> 9567<phrase role="special">></phrase></programlisting> 9568 representing the <link linkend="shared_state">shared state</link> 9569 associated with the asynchronous execution of <code><phrase role="identifier">fn</phrase></code>. 9570 </para> 9571 </listitem> 9572 </varlistentry> 9573 <varlistentry> 9574 <term>Throws:</term> 9575 <listitem> 9576 <para> 9577 <code><phrase role="identifier">fiber_error</phrase></code> or <code><phrase 9578 role="identifier">future_error</phrase></code> if an error occurs. 9579 </para> 9580 </listitem> 9581 </varlistentry> 9582 <varlistentry> 9583 <term>Notes:</term> 9584 <listitem> 9585 <para> 9586 The overloads accepting <ulink url="http://en.cppreference.com/w/cpp/memory/allocator_arg_t"><code><phrase 9587 role="identifier">std</phrase><phrase role="special">::</phrase><phrase 9588 role="identifier">allocator_arg_t</phrase></code></ulink> use the 9589 passed <link linkend="stack_allocator_concept"><code><phrase role="identifier">StackAllocator</phrase></code></link> 9590 when constructing the launched <code><phrase role="identifier">fiber</phrase></code>. 9591 The overloads accepting <link linkend="class_launch"><code>launch</code></link> use the passed <code><phrase 9592 role="identifier">launch</phrase></code> when constructing the launched 9593 <code><phrase role="identifier">fiber</phrase></code>. The default 9594 <code><phrase role="identifier">launch</phrase></code> is <code><phrase 9595 role="identifier">post</phrase></code>, as for the <code><phrase 9596 role="identifier">fiber</phrase></code> constructor. 9597 </para> 9598 </listitem> 9599 </varlistentry> 9600 </variablelist> 9601 <note> 9602 <para> 9603 Deferred futures are not supported. 9604 </para> 9605 </note> 9606 </section> 9607 <section id="fiber.synchronization.futures.promise"> 9608 <title><anchor id="class_promise"/><link linkend="fiber.synchronization.futures.promise">Template 9609 <code><phrase role="identifier">promise</phrase><phrase role="special"><></phrase></code></link></title> 9610 <para> 9611 A <link linkend="class_promise"><code>promise<></code></link> provides a mechanism to store a value (or 9612 exception) that can later be retrieved from the corresponding <link linkend="class_future"><code>future<></code></link> object. 9613 <code><phrase role="identifier">promise</phrase><phrase role="special"><></phrase></code> 9614 and <code><phrase role="identifier">future</phrase><phrase role="special"><></phrase></code> 9615 communicate via their underlying <link linkend="shared_state">shared state</link>. 9616 </para> 9617<programlisting><phrase role="preprocessor">#include</phrase> <phrase role="special"><</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">></phrase> 9618 9619<phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase> 9620<phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase> 9621 9622<phrase role="keyword">template</phrase><phrase role="special"><</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">R</phrase> <phrase role="special">></phrase> 9623<phrase role="keyword">class</phrase> <phrase role="identifier">promise</phrase> <phrase role="special">{</phrase> 9624<phrase role="keyword">public</phrase><phrase role="special">:</phrase> 9625 <phrase role="identifier">promise</phrase><phrase role="special">();</phrase> 9626 9627 <phrase role="keyword">template</phrase><phrase role="special"><</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> 9628 <phrase role="identifier">promise</phrase><phrase role="special">(</phrase> <ulink url="http://en.cppreference.com/w/cpp/memory/allocator_arg_t"><code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">allocator_arg_t</phrase></code></ulink><phrase role="special">,</phrase> <phrase role="identifier">Allocator</phrase><phrase role="special">);</phrase> 9629 9630 <phrase role="identifier">promise</phrase><phrase role="special">(</phrase> <phrase role="identifier">promise</phrase> <phrase role="special">&&)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 9631 9632 <phrase role="identifier">promise</phrase> <phrase role="special">&</phrase> <phrase role="keyword">operator</phrase><phrase role="special">=(</phrase> <phrase role="identifier">promise</phrase> <phrase role="special">&&)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 9633 9634 <phrase role="identifier">promise</phrase><phrase role="special">(</phrase> <phrase role="identifier">promise</phrase> <phrase role="keyword">const</phrase><phrase role="special">&)</phrase> <phrase role="special">=</phrase> <phrase role="keyword">delete</phrase><phrase role="special">;</phrase> 9635 9636 <phrase role="identifier">promise</phrase> <phrase role="special">&</phrase> <phrase role="keyword">operator</phrase><phrase role="special">=(</phrase> <phrase role="identifier">promise</phrase> <phrase role="keyword">const</phrase><phrase role="special">&)</phrase> <phrase role="special">=</phrase> <phrase role="keyword">delete</phrase><phrase role="special">;</phrase> 9637 9638 <phrase role="special">~</phrase><phrase role="identifier">promise</phrase><phrase role="special">();</phrase> 9639 9640 <phrase role="keyword">void</phrase> <phrase role="identifier">swap</phrase><phrase role="special">(</phrase> <phrase role="identifier">promise</phrase> <phrase role="special">&)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 9641 9642 <phrase role="identifier">future</phrase><phrase role="special"><</phrase> <phrase role="identifier">R</phrase> <phrase role="special">></phrase> <phrase role="identifier">get_future</phrase><phrase role="special">();</phrase> 9643 9644 <phrase role="keyword">void</phrase> <phrase role="identifier">set_value</phrase><phrase role="special">(</phrase> <phrase role="identifier">R</phrase> <phrase role="keyword">const</phrase><phrase role="special">&);</phrase> <phrase role="comment">// member only of generic promise template</phrase> 9645 <phrase role="keyword">void</phrase> <phrase role="identifier">set_value</phrase><phrase role="special">(</phrase> <phrase role="identifier">R</phrase> <phrase role="special">&&);</phrase> <phrase role="comment">// member only of generic promise template</phrase> 9646 <phrase role="keyword">void</phrase> <phrase role="identifier">set_value</phrase><phrase role="special">(</phrase> <phrase role="identifier">R</phrase> <phrase role="special">&);</phrase> <phrase role="comment">// member only of promise< R & > template</phrase> 9647 <phrase role="keyword">void</phrase> <phrase role="identifier">set_value</phrase><phrase role="special">();</phrase> <phrase role="comment">// member only of promise< void > template</phrase> 9648 9649 <phrase role="keyword">void</phrase> <phrase role="identifier">set_exception</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">exception_ptr</phrase> <phrase role="identifier">p</phrase><phrase role="special">);</phrase> 9650<phrase role="special">};</phrase> 9651 9652<phrase role="keyword">template</phrase><phrase role="special"><</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">R</phrase> <phrase role="special">></phrase> 9653<phrase role="keyword">void</phrase> <phrase role="identifier">swap</phrase><phrase role="special">(</phrase> <phrase role="identifier">promise</phrase><phrase role="special"><</phrase> <phrase role="identifier">R</phrase> <phrase role="special">></phrase> <phrase role="special">&,</phrase> <phrase role="identifier">promise</phrase><phrase role="special"><</phrase> <phrase role="identifier">R</phrase> <phrase role="special">></phrase> <phrase role="special">&)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 9654 9655<phrase role="special">}</phrase> 9656</programlisting> 9657 <bridgehead renderas="sect5" id="fiber.synchronization.futures.promise.h0"> 9658 <phrase id="fiber.synchronization.futures.promise.default_constructor"/><link 9659 linkend="fiber.synchronization.futures.promise.default_constructor">Default 9660 constructor</link> 9661 </bridgehead> 9662<programlisting><phrase role="identifier">promise</phrase><phrase role="special">();</phrase> 9663</programlisting> 9664 <variablelist> 9665 <title></title> 9666 <varlistentry> 9667 <term>Effects:</term> 9668 <listitem> 9669 <para> 9670 Creates a promise with an empty <link linkend="shared_state">shared 9671 state</link>. 9672 </para> 9673 </listitem> 9674 </varlistentry> 9675 <varlistentry> 9676 <term>Throws:</term> 9677 <listitem> 9678 <para> 9679 Exceptions caused by memory allocation. 9680 </para> 9681 </listitem> 9682 </varlistentry> 9683 </variablelist> 9684 <bridgehead renderas="sect5" id="fiber.synchronization.futures.promise.h1"> 9685 <phrase id="fiber.synchronization.futures.promise.constructor"/><link linkend="fiber.synchronization.futures.promise.constructor">Constructor</link> 9686 </bridgehead> 9687<programlisting><phrase role="keyword">template</phrase><phrase role="special"><</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> 9688<phrase role="identifier">promise</phrase><phrase role="special">(</phrase> <ulink url="http://en.cppreference.com/w/cpp/memory/allocator_arg_t"><code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">allocator_arg_t</phrase></code></ulink><phrase role="special">,</phrase> <phrase role="identifier">Allocator</phrase> <phrase role="identifier">alloc</phrase><phrase role="special">);</phrase> 9689</programlisting> 9690 <variablelist> 9691 <title></title> 9692 <varlistentry> 9693 <term>Effects:</term> 9694 <listitem> 9695 <para> 9696 Creates a promise with an empty <link linkend="shared_state">shared 9697 state</link> by using <code><phrase role="identifier">alloc</phrase></code>. 9698 </para> 9699 </listitem> 9700 </varlistentry> 9701 <varlistentry> 9702 <term>Throws:</term> 9703 <listitem> 9704 <para> 9705 Exceptions caused by memory allocation. 9706 </para> 9707 </listitem> 9708 </varlistentry> 9709 <varlistentry> 9710 <term>See also:</term> 9711 <listitem> 9712 <para> 9713 <ulink url="http://en.cppreference.com/w/cpp/memory/allocator_arg_t"><code><phrase 9714 role="identifier">std</phrase><phrase role="special">::</phrase><phrase 9715 role="identifier">allocator_arg_t</phrase></code></ulink> 9716 </para> 9717 </listitem> 9718 </varlistentry> 9719 </variablelist> 9720 <bridgehead renderas="sect5" id="fiber.synchronization.futures.promise.h2"> 9721 <phrase id="fiber.synchronization.futures.promise.move_constructor"/><link 9722 linkend="fiber.synchronization.futures.promise.move_constructor">Move constructor</link> 9723 </bridgehead> 9724<programlisting><phrase role="identifier">promise</phrase><phrase role="special">(</phrase> <phrase role="identifier">promise</phrase> <phrase role="special">&&</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 9725</programlisting> 9726 <variablelist> 9727 <title></title> 9728 <varlistentry> 9729 <term>Effects:</term> 9730 <listitem> 9731 <para> 9732 Creates a promise by moving the <link linkend="shared_state">shared 9733 state</link> from <code><phrase role="identifier">other</phrase></code>. 9734 </para> 9735 </listitem> 9736 </varlistentry> 9737 <varlistentry> 9738 <term>Postcondition:</term> 9739 <listitem> 9740 <para> 9741 <code><phrase role="identifier">other</phrase></code> contains no 9742 valid shared state. 9743 </para> 9744 </listitem> 9745 </varlistentry> 9746 <varlistentry> 9747 <term>Throws:</term> 9748 <listitem> 9749 <para> 9750 Nothing. 9751 </para> 9752 </listitem> 9753 </varlistentry> 9754 </variablelist> 9755 <bridgehead renderas="sect5" id="fiber.synchronization.futures.promise.h3"> 9756 <phrase id="fiber.synchronization.futures.promise.destructor"/><link linkend="fiber.synchronization.futures.promise.destructor">Destructor</link> 9757 </bridgehead> 9758<programlisting><phrase role="special">~</phrase><phrase role="identifier">promise</phrase><phrase role="special">();</phrase> 9759</programlisting> 9760 <variablelist> 9761 <title></title> 9762 <varlistentry> 9763 <term>Effects:</term> 9764 <listitem> 9765 <para> 9766 Destroys <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code> 9767 and abandons the <link linkend="shared_state">shared state</link> 9768 if shared state is ready; otherwise stores <code><phrase role="identifier">future_error</phrase></code> 9769 with error condition <code><phrase role="identifier">future_errc</phrase><phrase 9770 role="special">::</phrase><phrase role="identifier">broken_promise</phrase></code> 9771 as if by <link linkend="promise_set_exception"><code>promise::set_exception()</code></link>: the shared 9772 state is set ready. 9773 </para> 9774 </listitem> 9775 </varlistentry> 9776 </variablelist> 9777 <para> 9778 <bridgehead renderas="sect4" id="promise_operator_assign_bridgehead"> 9779 <phrase id="promise_operator_assign"/> 9780 <link linkend="promise_operator_assign">Member 9781 function <code>operator=</code>()</link> 9782</bridgehead> 9783 </para> 9784<programlisting><phrase role="identifier">promise</phrase> <phrase role="special">&</phrase> <phrase role="keyword">operator</phrase><phrase role="special">=(</phrase> <phrase role="identifier">promise</phrase> <phrase role="special">&&</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 9785</programlisting> 9786 <variablelist> 9787 <title></title> 9788 <varlistentry> 9789 <term>Effects:</term> 9790 <listitem> 9791 <para> 9792 Transfers the ownership of <link linkend="shared_state">shared state</link> 9793 to <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>. 9794 </para> 9795 </listitem> 9796 </varlistentry> 9797 <varlistentry> 9798 <term>Postcondition:</term> 9799 <listitem> 9800 <para> 9801 <code><phrase role="identifier">other</phrase></code> contains no 9802 valid shared state. 9803 </para> 9804 </listitem> 9805 </varlistentry> 9806 <varlistentry> 9807 <term>Throws:</term> 9808 <listitem> 9809 <para> 9810 Nothing. 9811 </para> 9812 </listitem> 9813 </varlistentry> 9814 </variablelist> 9815 <para> 9816 <bridgehead renderas="sect4" id="promise_swap_bridgehead"> 9817 <phrase id="promise_swap"/> 9818 <link linkend="promise_swap">Member function <code>swap</code>()</link> 9819</bridgehead> 9820 </para> 9821<programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">swap</phrase><phrase role="special">(</phrase> <phrase role="identifier">promise</phrase> <phrase role="special">&</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 9822</programlisting> 9823 <variablelist> 9824 <title></title> 9825 <varlistentry> 9826 <term>Effects:</term> 9827 <listitem> 9828 <para> 9829 Swaps the <link linkend="shared_state">shared state</link> between 9830 other and <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>. 9831 </para> 9832 </listitem> 9833 </varlistentry> 9834 <varlistentry> 9835 <term>Throws:</term> 9836 <listitem> 9837 <para> 9838 Nothing. 9839 </para> 9840 </listitem> 9841 </varlistentry> 9842 </variablelist> 9843 <para> 9844 <bridgehead renderas="sect4" id="promise_get_future_bridgehead"> 9845 <phrase id="promise_get_future"/> 9846 <link linkend="promise_get_future">Member 9847 function <code>get_future</code>()</link> 9848</bridgehead> 9849 </para> 9850<programlisting><phrase role="identifier">future</phrase><phrase role="special"><</phrase> <phrase role="identifier">R</phrase> <phrase role="special">></phrase> <phrase role="identifier">get_future</phrase><phrase role="special">();</phrase> 9851</programlisting> 9852 <variablelist> 9853 <title></title> 9854 <varlistentry> 9855 <term>Returns:</term> 9856 <listitem> 9857 <para> 9858 A <link linkend="class_future"><code>future<></code></link> with the same <link linkend="shared_state">shared 9859 state</link>. 9860 </para> 9861 </listitem> 9862 </varlistentry> 9863 <varlistentry> 9864 <term>Throws:</term> 9865 <listitem> 9866 <para> 9867 <code><phrase role="identifier">future_error</phrase></code> with 9868 <code><phrase role="identifier">future_errc</phrase><phrase role="special">::</phrase><phrase 9869 role="identifier">future_already_retrieved</phrase></code> or <code><phrase 9870 role="identifier">future_errc</phrase><phrase role="special">::</phrase><phrase 9871 role="identifier">no_state</phrase></code>. 9872 </para> 9873 </listitem> 9874 </varlistentry> 9875 </variablelist> 9876 <para> 9877 <bridgehead renderas="sect4" id="promise_set_value_bridgehead"> 9878 <phrase id="promise_set_value"/> 9879 <link linkend="promise_set_value">Member function 9880 <code>set_value</code>()</link> 9881</bridgehead> 9882 </para> 9883<programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">set_value</phrase><phrase role="special">(</phrase> <phrase role="identifier">R</phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">value</phrase><phrase role="special">);</phrase> <phrase role="comment">// member only of generic promise template</phrase> 9884<phrase role="keyword">void</phrase> <phrase role="identifier">set_value</phrase><phrase role="special">(</phrase> <phrase role="identifier">R</phrase> <phrase role="special">&&</phrase> <phrase role="identifier">value</phrase><phrase role="special">);</phrase> <phrase role="comment">// member only of generic promise template</phrase> 9885<phrase role="keyword">void</phrase> <phrase role="identifier">set_value</phrase><phrase role="special">(</phrase> <phrase role="identifier">R</phrase> <phrase role="special">&</phrase> <phrase role="identifier">value</phrase><phrase role="special">);</phrase> <phrase role="comment">// member only of promise< R & > template</phrase> 9886<phrase role="keyword">void</phrase> <phrase role="identifier">set_value</phrase><phrase role="special">();</phrase> <phrase role="comment">// member only of promise< void > template</phrase> 9887</programlisting> 9888 <variablelist> 9889 <title></title> 9890 <varlistentry> 9891 <term>Effects:</term> 9892 <listitem> 9893 <para> 9894 Store the result in the <link linkend="shared_state">shared state</link> 9895 and marks the state as ready. 9896 </para> 9897 </listitem> 9898 </varlistentry> 9899 <varlistentry> 9900 <term>Throws:</term> 9901 <listitem> 9902 <para> 9903 <code><phrase role="identifier">future_error</phrase></code> with 9904 <code><phrase role="identifier">future_errc</phrase><phrase role="special">::</phrase><phrase 9905 role="identifier">future_already_satisfied</phrase></code> or <code><phrase 9906 role="identifier">future_errc</phrase><phrase role="special">::</phrase><phrase 9907 role="identifier">no_state</phrase></code>. 9908 </para> 9909 </listitem> 9910 </varlistentry> 9911 </variablelist> 9912 <para> 9913 <bridgehead renderas="sect4" id="promise_set_exception_bridgehead"> 9914 <phrase id="promise_set_exception"/> 9915 <link linkend="promise_set_exception">Member 9916 function <code>set_exception</code>()</link> 9917</bridgehead> 9918 </para> 9919<programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">set_exception</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">exception_ptr</phrase><phrase role="special">);</phrase> 9920</programlisting> 9921 <variablelist> 9922 <title></title> 9923 <varlistentry> 9924 <term>Effects:</term> 9925 <listitem> 9926 <para> 9927 Store an exception pointer in the <link linkend="shared_state">shared 9928 state</link> and marks the state as ready. 9929 </para> 9930 </listitem> 9931 </varlistentry> 9932 <varlistentry> 9933 <term>Throws:</term> 9934 <listitem> 9935 <para> 9936 <code><phrase role="identifier">future_error</phrase></code> with 9937 <code><phrase role="identifier">future_errc</phrase><phrase role="special">::</phrase><phrase 9938 role="identifier">future_already_satisfied</phrase></code> or <code><phrase 9939 role="identifier">future_errc</phrase><phrase role="special">::</phrase><phrase 9940 role="identifier">no_state</phrase></code>. 9941 </para> 9942 </listitem> 9943 </varlistentry> 9944 </variablelist> 9945 <para> 9946 <bridgehead renderas="sect4" id="swap_for_promise_bridgehead"> 9947 <phrase id="swap_for_promise"/> 9948 <link linkend="swap_for_promise">Non-member function 9949 <code>swap()</code></link> 9950</bridgehead> 9951 </para> 9952<programlisting><phrase role="keyword">template</phrase><phrase role="special"><</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">R</phrase> <phrase role="special">></phrase> 9953<phrase role="keyword">void</phrase> <phrase role="identifier">swap</phrase><phrase role="special">(</phrase> <phrase role="identifier">promise</phrase><phrase role="special"><</phrase> <phrase role="identifier">R</phrase> <phrase role="special">></phrase> <phrase role="special">&</phrase> <phrase role="identifier">l</phrase><phrase role="special">,</phrase> <phrase role="identifier">promise</phrase><phrase role="special"><</phrase> <phrase role="identifier">R</phrase> <phrase role="special">></phrase> <phrase role="special">&</phrase> <phrase role="identifier">r</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 9954</programlisting> 9955 <variablelist> 9956 <title></title> 9957 <varlistentry> 9958 <term>Effects:</term> 9959 <listitem> 9960 <para> 9961 Same as <code><phrase role="identifier">l</phrase><phrase role="special">.</phrase><phrase 9962 role="identifier">swap</phrase><phrase role="special">(</phrase> 9963 <phrase role="identifier">r</phrase><phrase role="special">)</phrase></code>. 9964 </para> 9965 </listitem> 9966 </varlistentry> 9967 </variablelist> 9968 </section> 9969 <section id="fiber.synchronization.futures.packaged_task"> 9970 <title><anchor id="class_packaged_task"/><link linkend="fiber.synchronization.futures.packaged_task">Template 9971 <code><phrase role="identifier">packaged_task</phrase><phrase role="special"><></phrase></code></link></title> 9972 <para> 9973 A <link linkend="class_packaged_task"><code>packaged_task<></code></link> wraps a callable target that 9974 returns a value so that the return value can be computed asynchronously. 9975 </para> 9976 <para> 9977 Conventional usage of <code><phrase role="identifier">packaged_task</phrase><phrase 9978 role="special"><></phrase></code> is like this: 9979 </para> 9980 <orderedlist> 9981 <listitem> 9982 <simpara> 9983 Instantiate <code><phrase role="identifier">packaged_task</phrase><phrase 9984 role="special"><></phrase></code> with template arguments matching 9985 the signature of the callable. Pass the callable to the <link linkend="packaged_task_packaged_task">constructor</link>. 9986 </simpara> 9987 </listitem> 9988 <listitem> 9989 <simpara> 9990 Call <link linkend="packaged_task_get_future"><code>packaged_task::get_future()</code></link> and capture 9991 the returned <link linkend="class_future"><code>future<></code></link> instance. 9992 </simpara> 9993 </listitem> 9994 <listitem> 9995 <simpara> 9996 Launch a <link linkend="class_fiber"><code>fiber</code></link> to run the new <code><phrase role="identifier">packaged_task</phrase><phrase 9997 role="special"><></phrase></code>, passing any arguments required 9998 by the original callable. 9999 </simpara> 10000 </listitem> 10001 <listitem> 10002 <simpara> 10003 Call <link linkend="fiber_detach"><code>fiber::detach()</code></link> on the newly-launched <code><phrase 10004 role="identifier">fiber</phrase></code>. 10005 </simpara> 10006 </listitem> 10007 <listitem> 10008 <simpara> 10009 At some later point, retrieve the result from the <code><phrase role="identifier">future</phrase><phrase 10010 role="special"><></phrase></code>. 10011 </simpara> 10012 </listitem> 10013 </orderedlist> 10014 <para> 10015 This is, in fact, pretty much what <link linkend="fibers_async"><code>fibers::async()</code></link> 10016encapsulates. 10017 </para> 10018<programlisting><phrase role="preprocessor">#include</phrase> <phrase role="special"><</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">></phrase> 10019 10020<phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase> 10021<phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase> 10022 10023<phrase role="keyword">template</phrase><phrase role="special"><</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">></phrase> 10024<phrase role="keyword">class</phrase> <phrase role="identifier">packaged_task</phrase><phrase role="special"><</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">></phrase> <phrase role="special">{</phrase> 10025<phrase role="keyword">public</phrase><phrase role="special">:</phrase> 10026 <phrase role="identifier">packaged_task</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 10027 10028 <phrase role="keyword">template</phrase><phrase role="special"><</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Fn</phrase> <phrase role="special">></phrase> 10029 <phrase role="keyword">explicit</phrase> <phrase role="identifier">packaged_task</phrase><phrase role="special">(</phrase> <phrase role="identifier">Fn</phrase> <phrase role="special">&&);</phrase> 10030 10031 <phrase role="keyword">template</phrase><phrase role="special"><</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">></phrase> 10032 <phrase role="identifier">packaged_task</phrase><phrase role="special">(</phrase> <ulink url="http://en.cppreference.com/w/cpp/memory/allocator_arg_t"><code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">allocator_arg_t</phrase></code></ulink><phrase role="special">,</phrase> <phrase role="identifier">Allocator</phrase> <phrase role="keyword">const</phrase><phrase role="special">&,</phrase> <phrase role="identifier">Fn</phrase> <phrase role="special">&&);</phrase> 10033 10034 <phrase role="identifier">packaged_task</phrase><phrase role="special">(</phrase> <phrase role="identifier">packaged_task</phrase> <phrase role="special">&&)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 10035 10036 <phrase role="identifier">packaged_task</phrase> <phrase role="special">&</phrase> <phrase role="keyword">operator</phrase><phrase role="special">=(</phrase> <phrase role="identifier">packaged_task</phrase> <phrase role="special">&&)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 10037 10038 <phrase role="identifier">packaged_task</phrase><phrase role="special">(</phrase> <phrase role="identifier">packaged_task</phrase> <phrase role="keyword">const</phrase><phrase role="special">&)</phrase> <phrase role="special">=</phrase> <phrase role="keyword">delete</phrase><phrase role="special">;</phrase> 10039 10040 <phrase role="identifier">packaged_task</phrase> <phrase role="special">&</phrase> <phrase role="keyword">operator</phrase><phrase role="special">=(</phrase> <phrase role="identifier">packaged_task</phrase> <phrase role="keyword">const</phrase><phrase role="special">&)</phrase> <phrase role="special">=</phrase> <phrase role="keyword">delete</phrase><phrase role="special">;</phrase> 10041 10042 <phrase role="special">~</phrase><phrase role="identifier">packaged_task</phrase><phrase role="special">();</phrase> 10043 10044 <phrase role="keyword">void</phrase> <phrase role="identifier">swap</phrase><phrase role="special">(</phrase> <phrase role="identifier">packaged_task</phrase> <phrase role="special">&)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 10045 10046 <phrase role="keyword">bool</phrase> <phrase role="identifier">valid</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 10047 10048 <phrase role="identifier">future</phrase><phrase role="special"><</phrase> <phrase role="identifier">R</phrase> <phrase role="special">></phrase> <phrase role="identifier">get_future</phrase><phrase role="special">();</phrase> 10049 10050 <phrase role="keyword">void</phrase> <phrase role="keyword">operator</phrase><phrase role="special">()(</phrase> <phrase role="identifier">Args</phrase> <phrase role="special">...);</phrase> 10051 10052 <phrase role="keyword">void</phrase> <phrase role="identifier">reset</phrase><phrase role="special">();</phrase> 10053<phrase role="special">};</phrase> 10054 10055<phrase role="keyword">template</phrase><phrase role="special"><</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Signature</phrase> <phrase role="special">></phrase> 10056<phrase role="keyword">void</phrase> <phrase role="identifier">swap</phrase><phrase role="special">(</phrase> <phrase role="identifier">packaged_task</phrase><phrase role="special"><</phrase> <phrase role="identifier">Signature</phrase> <phrase role="special">></phrase> <phrase role="special">&,</phrase> <phrase role="identifier">packaged_task</phrase><phrase role="special"><</phrase> <phrase role="identifier">Signature</phrase> <phrase role="special">></phrase> <phrase role="special">&)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 10057 10058<phrase role="special">}}</phrase> 10059</programlisting> 10060 <bridgehead renderas="sect5" id="fiber.synchronization.futures.packaged_task.h0"> 10061 <phrase id="fiber.synchronization.futures.packaged_task.default_constructor__code__phrase_role__identifier__packaged_task__phrase__phrase_role__special______phrase___code_"/><link 10062 linkend="fiber.synchronization.futures.packaged_task.default_constructor__code__phrase_role__identifier__packaged_task__phrase__phrase_role__special______phrase___code_">Default 10063 constructor <code><phrase role="identifier">packaged_task</phrase><phrase 10064 role="special">()</phrase></code></link> 10065 </bridgehead> 10066<programlisting><phrase role="identifier">packaged_task</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 10067</programlisting> 10068 <variablelist> 10069 <title></title> 10070 <varlistentry> 10071 <term>Effects:</term> 10072 <listitem> 10073 <para> 10074 Constructs an object of class <code><phrase role="identifier">packaged_task</phrase></code> 10075 with no <link linkend="shared_state">shared state</link>. 10076 </para> 10077 </listitem> 10078 </varlistentry> 10079 <varlistentry> 10080 <term>Throws:</term> 10081 <listitem> 10082 <para> 10083 Nothing. 10084 </para> 10085 </listitem> 10086 </varlistentry> 10087 </variablelist> 10088 <anchor id="packaged_task_packaged_task"/> 10089 <bridgehead renderas="sect5" id="fiber.synchronization.futures.packaged_task.h1"> 10090 <phrase id="fiber.synchronization.futures.packaged_task.templated_constructor__code__phrase_role__identifier__packaged_task__phrase__phrase_role__special______phrase___code_"/><link 10091 linkend="fiber.synchronization.futures.packaged_task.templated_constructor__code__phrase_role__identifier__packaged_task__phrase__phrase_role__special______phrase___code_">Templated 10092 constructor <code><phrase role="identifier">packaged_task</phrase><phrase 10093 role="special">()</phrase></code></link> 10094 </bridgehead> 10095<programlisting><phrase role="keyword">template</phrase><phrase role="special"><</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Fn</phrase> <phrase role="special">></phrase> 10096<phrase role="keyword">explicit</phrase> <phrase role="identifier">packaged_task</phrase><phrase role="special">(</phrase> <phrase role="identifier">Fn</phrase> <phrase role="special">&&</phrase> <phrase role="identifier">fn</phrase><phrase role="special">);</phrase> 10097 10098<phrase role="keyword">template</phrase><phrase role="special"><</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">></phrase> 10099<phrase role="identifier">packaged_task</phrase><phrase role="special">(</phrase> <ulink url="http://en.cppreference.com/w/cpp/memory/allocator_arg_t"><code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">allocator_arg_t</phrase></code></ulink><phrase role="special">,</phrase> <phrase role="identifier">Allocator</phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">alloc</phrase><phrase role="special">,</phrase> <phrase role="identifier">Fn</phrase> <phrase role="special">&&</phrase> <phrase role="identifier">fn</phrase><phrase role="special">);</phrase> 10100</programlisting> 10101 <variablelist> 10102 <title></title> 10103 <varlistentry> 10104 <term>Effects:</term> 10105 <listitem> 10106 <para> 10107 Constructs an object of class <code><phrase role="identifier">packaged_task</phrase></code> 10108 with a <link linkend="shared_state">shared state</link> and copies 10109 or moves the callable target <code><phrase role="identifier">fn</phrase></code> 10110 to internal storage. 10111 </para> 10112 </listitem> 10113 </varlistentry> 10114 <varlistentry> 10115 <term>Throws:</term> 10116 <listitem> 10117 <para> 10118 Exceptions caused by memory allocation. 10119 </para> 10120 </listitem> 10121 </varlistentry> 10122 <varlistentry> 10123 <term>Note:</term> 10124 <listitem> 10125 <para> 10126 The signature of <code><phrase role="identifier">Fn</phrase></code> 10127 should have a return type convertible to <code><phrase role="identifier">R</phrase></code>. 10128 </para> 10129 </listitem> 10130 </varlistentry> 10131 <varlistentry> 10132 <term>See also:</term> 10133 <listitem> 10134 <para> 10135 <ulink url="http://en.cppreference.com/w/cpp/memory/allocator_arg_t"><code><phrase 10136 role="identifier">std</phrase><phrase role="special">::</phrase><phrase 10137 role="identifier">allocator_arg_t</phrase></code></ulink> 10138 </para> 10139 </listitem> 10140 </varlistentry> 10141 </variablelist> 10142 <bridgehead renderas="sect5" id="fiber.synchronization.futures.packaged_task.h2"> 10143 <phrase id="fiber.synchronization.futures.packaged_task.move_constructor"/><link 10144 linkend="fiber.synchronization.futures.packaged_task.move_constructor">Move 10145 constructor</link> 10146 </bridgehead> 10147<programlisting><phrase role="identifier">packaged_task</phrase><phrase role="special">(</phrase> <phrase role="identifier">packaged_task</phrase> <phrase role="special">&&</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 10148</programlisting> 10149 <variablelist> 10150 <title></title> 10151 <varlistentry> 10152 <term>Effects:</term> 10153 <listitem> 10154 <para> 10155 Creates a packaged_task by moving the <link linkend="shared_state">shared 10156 state</link> from <code><phrase role="identifier">other</phrase></code>. 10157 </para> 10158 </listitem> 10159 </varlistentry> 10160 <varlistentry> 10161 <term>Postcondition:</term> 10162 <listitem> 10163 <para> 10164 <code><phrase role="identifier">other</phrase></code> contains no 10165 valid shared state. 10166 </para> 10167 </listitem> 10168 </varlistentry> 10169 <varlistentry> 10170 <term>Throws:</term> 10171 <listitem> 10172 <para> 10173 Nothing. 10174 </para> 10175 </listitem> 10176 </varlistentry> 10177 </variablelist> 10178 <bridgehead renderas="sect5" id="fiber.synchronization.futures.packaged_task.h3"> 10179 <phrase id="fiber.synchronization.futures.packaged_task.destructor"/><link 10180 linkend="fiber.synchronization.futures.packaged_task.destructor">Destructor</link> 10181 </bridgehead> 10182<programlisting><phrase role="special">~</phrase><phrase role="identifier">packaged_task</phrase><phrase role="special">();</phrase> 10183</programlisting> 10184 <variablelist> 10185 <title></title> 10186 <varlistentry> 10187 <term>Effects:</term> 10188 <listitem> 10189 <para> 10190 Destroys <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code> 10191 and abandons the <link linkend="shared_state">shared state</link> 10192 if shared state is ready; otherwise stores <code><phrase role="identifier">future_error</phrase></code> 10193 with error condition <code><phrase role="identifier">future_errc</phrase><phrase 10194 role="special">::</phrase><phrase role="identifier">broken_promise</phrase></code> 10195 as if by <link linkend="promise_set_exception"><code>promise::set_exception()</code></link>: the shared 10196 state is set ready. 10197 </para> 10198 </listitem> 10199 </varlistentry> 10200 </variablelist> 10201 <para> 10202 <bridgehead renderas="sect4" id="packaged_task_operator_assign_bridgehead"> 10203 <phrase id="packaged_task_operator_assign"/> 10204 <link linkend="packaged_task_operator_assign">Member 10205 function <code>operator=</code>()</link> 10206</bridgehead> 10207 </para> 10208<programlisting><phrase role="identifier">packaged_task</phrase> <phrase role="special">&</phrase> <phrase role="keyword">operator</phrase><phrase role="special">=(</phrase> <phrase role="identifier">packaged_task</phrase> <phrase role="special">&&</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 10209</programlisting> 10210 <variablelist> 10211 <title></title> 10212 <varlistentry> 10213 <term>Effects:</term> 10214 <listitem> 10215 <para> 10216 Transfers the ownership of <link linkend="shared_state">shared state</link> 10217 to <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>. 10218 </para> 10219 </listitem> 10220 </varlistentry> 10221 <varlistentry> 10222 <term>Postcondition:</term> 10223 <listitem> 10224 <para> 10225 <code><phrase role="identifier">other</phrase></code> contains no 10226 valid shared state. 10227 </para> 10228 </listitem> 10229 </varlistentry> 10230 <varlistentry> 10231 <term>Throws:</term> 10232 <listitem> 10233 <para> 10234 Nothing. 10235 </para> 10236 </listitem> 10237 </varlistentry> 10238 </variablelist> 10239 <para> 10240 <bridgehead renderas="sect4" id="packaged_task_swap_bridgehead"> 10241 <phrase id="packaged_task_swap"/> 10242 <link linkend="packaged_task_swap">Member 10243 function <code>swap</code>()</link> 10244</bridgehead> 10245 </para> 10246<programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">swap</phrase><phrase role="special">(</phrase> <phrase role="identifier">packaged_task</phrase> <phrase role="special">&</phrase> <phrase role="identifier">other</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 10247</programlisting> 10248 <variablelist> 10249 <title></title> 10250 <varlistentry> 10251 <term>Effects:</term> 10252 <listitem> 10253 <para> 10254 Swaps the <link linkend="shared_state">shared state</link> between 10255 other and <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>. 10256 </para> 10257 </listitem> 10258 </varlistentry> 10259 <varlistentry> 10260 <term>Throws:</term> 10261 <listitem> 10262 <para> 10263 Nothing. 10264 </para> 10265 </listitem> 10266 </varlistentry> 10267 </variablelist> 10268 <para> 10269 <bridgehead renderas="sect4" id="packaged_task_valid_bridgehead"> 10270 <phrase id="packaged_task_valid"/> 10271 <link linkend="packaged_task_valid">Member 10272 function <code>valid</code>()</link> 10273</bridgehead> 10274 </para> 10275<programlisting><phrase role="keyword">bool</phrase> <phrase role="identifier">valid</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 10276</programlisting> 10277 <variablelist> 10278 <title></title> 10279 <varlistentry> 10280 <term>Effects:</term> 10281 <listitem> 10282 <para> 10283 Returns <code><phrase role="keyword">true</phrase></code> if <code><phrase 10284 role="special">*</phrase><phrase role="keyword">this</phrase></code> 10285 contains a <link linkend="shared_state">shared state</link>. 10286 </para> 10287 </listitem> 10288 </varlistentry> 10289 <varlistentry> 10290 <term>Throws:</term> 10291 <listitem> 10292 <para> 10293 Nothing. 10294 </para> 10295 </listitem> 10296 </varlistentry> 10297 </variablelist> 10298 <para> 10299 <bridgehead renderas="sect4" id="packaged_task_get_future_bridgehead"> 10300 <phrase id="packaged_task_get_future"/> 10301 <link linkend="packaged_task_get_future">Member 10302 function <code>get_future</code>()</link> 10303</bridgehead> 10304 </para> 10305<programlisting><phrase role="identifier">future</phrase><phrase role="special"><</phrase> <phrase role="identifier">R</phrase> <phrase role="special">></phrase> <phrase role="identifier">get_future</phrase><phrase role="special">();</phrase> 10306</programlisting> 10307 <variablelist> 10308 <title></title> 10309 <varlistentry> 10310 <term>Returns:</term> 10311 <listitem> 10312 <para> 10313 A <link linkend="class_future"><code>future<></code></link> with the same <link linkend="shared_state">shared 10314 state</link>. 10315 </para> 10316 </listitem> 10317 </varlistentry> 10318 <varlistentry> 10319 <term>Throws:</term> 10320 <listitem> 10321 <para> 10322 <code><phrase role="identifier">future_error</phrase></code> with 10323 <code><phrase role="identifier">future_errc</phrase><phrase role="special">::</phrase><phrase 10324 role="identifier">future_already_retrieved</phrase></code> or <code><phrase 10325 role="identifier">future_errc</phrase><phrase role="special">::</phrase><phrase 10326 role="identifier">no_state</phrase></code>. 10327 </para> 10328 </listitem> 10329 </varlistentry> 10330 </variablelist> 10331 <para> 10332 <bridgehead renderas="sect4" id="packaged_task_operator_apply_bridgehead"> 10333 <phrase id="packaged_task_operator_apply"/> 10334 <link linkend="packaged_task_operator_apply">Member 10335 function <code>operator()</code>()</link> 10336</bridgehead> 10337 </para> 10338<programlisting><phrase role="keyword">void</phrase> <phrase role="keyword">operator</phrase><phrase role="special">()(</phrase> <phrase role="identifier">Args</phrase> <phrase role="special">&&</phrase> <phrase role="special">...</phrase> <phrase role="identifier">args</phrase><phrase role="special">);</phrase> 10339</programlisting> 10340 <variablelist> 10341 <title></title> 10342 <varlistentry> 10343 <term>Effects:</term> 10344 <listitem> 10345 <para> 10346 Invokes the stored callable target. Any exception thrown by the callable 10347 target <code><phrase role="identifier">fn</phrase></code> is stored 10348 in the <link linkend="shared_state">shared state</link> as if by 10349 <link linkend="promise_set_exception"><code>promise::set_exception()</code></link>. Otherwise, the value 10350 returned by <code><phrase role="identifier">fn</phrase></code> is 10351 stored in the shared state as if by <link linkend="promise_set_value"><code>promise::set_value()</code></link>. 10352 </para> 10353 </listitem> 10354 </varlistentry> 10355 <varlistentry> 10356 <term>Throws:</term> 10357 <listitem> 10358 <para> 10359 <code><phrase role="identifier">future_error</phrase></code> with 10360 <code><phrase role="identifier">future_errc</phrase><phrase role="special">::</phrase><phrase 10361 role="identifier">no_state</phrase></code>. 10362 </para> 10363 </listitem> 10364 </varlistentry> 10365 </variablelist> 10366 <para> 10367 <bridgehead renderas="sect4" id="packaged_task_reset_bridgehead"> 10368 <phrase id="packaged_task_reset"/> 10369 <link linkend="packaged_task_reset">Member 10370 function <code>reset</code>()</link> 10371</bridgehead> 10372 </para> 10373<programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">reset</phrase><phrase role="special">();</phrase> 10374</programlisting> 10375 <variablelist> 10376 <title></title> 10377 <varlistentry> 10378 <term>Effects:</term> 10379 <listitem> 10380 <para> 10381 Resets the <link linkend="shared_state">shared state</link> and abandons 10382 the result of previous executions. A new shared state is constructed. 10383 </para> 10384 </listitem> 10385 </varlistentry> 10386 <varlistentry> 10387 <term>Throws:</term> 10388 <listitem> 10389 <para> 10390 <code><phrase role="identifier">future_error</phrase></code> with 10391 <code><phrase role="identifier">future_errc</phrase><phrase role="special">::</phrase><phrase 10392 role="identifier">no_state</phrase></code>. 10393 </para> 10394 </listitem> 10395 </varlistentry> 10396 </variablelist> 10397 <para> 10398 <bridgehead renderas="sect4" id="swap_for_packaged_task_bridgehead"> 10399 <phrase id="swap_for_packaged_task"/> 10400 <link linkend="swap_for_packaged_task">Non-member 10401 function <code>swap()</code></link> 10402</bridgehead> 10403 </para> 10404<programlisting><phrase role="keyword">template</phrase><phrase role="special"><</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Signature</phrase> <phrase role="special">></phrase> 10405<phrase role="keyword">void</phrase> <phrase role="identifier">swap</phrase><phrase role="special">(</phrase> <phrase role="identifier">packaged_task</phrase><phrase role="special"><</phrase> <phrase role="identifier">Signature</phrase> <phrase role="special">></phrase> <phrase role="special">&</phrase> <phrase role="identifier">l</phrase><phrase role="special">,</phrase> <phrase role="identifier">packaged_task</phrase><phrase role="special"><</phrase> <phrase role="identifier">Signature</phrase> <phrase role="special">></phrase> <phrase role="special">&</phrase> <phrase role="identifier">r</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 10406</programlisting> 10407 <variablelist> 10408 <title></title> 10409 <varlistentry> 10410 <term>Effects:</term> 10411 <listitem> 10412 <para> 10413 Same as <code><phrase role="identifier">l</phrase><phrase role="special">.</phrase><phrase 10414 role="identifier">swap</phrase><phrase role="special">(</phrase> 10415 <phrase role="identifier">r</phrase><phrase role="special">)</phrase></code>. 10416 </para> 10417 </listitem> 10418 </varlistentry> 10419 </variablelist> 10420 </section> 10421 </section> 10422 </section> 10423 <section id="fiber.fls"> 10424 <title><link linkend="fiber.fls">Fiber local storage</link></title> 10425 <bridgehead renderas="sect3" id="fiber.fls.h0"> 10426 <phrase id="fiber.fls.synopsis"/><link linkend="fiber.fls.synopsis">Synopsis</link> 10427 </bridgehead> 10428 <para> 10429 Fiber local storage allows a separate instance of a given data item for each 10430 fiber. 10431 </para> 10432 <bridgehead renderas="sect3" id="fiber.fls.h1"> 10433 <phrase id="fiber.fls.cleanup_at_fiber_exit"/><link linkend="fiber.fls.cleanup_at_fiber_exit">Cleanup 10434 at fiber exit</link> 10435 </bridgehead> 10436 <para> 10437 When a fiber exits, the objects associated with each <link linkend="class_fiber_specific_ptr"><code>fiber_specific_ptr</code></link> instance 10438 are destroyed. By default, the object pointed to by a pointer <code><phrase 10439 role="identifier">p</phrase></code> is destroyed by invoking <code><phrase 10440 role="keyword">delete</phrase> <phrase role="identifier">p</phrase></code>, 10441 but this can be overridden for a specific instance of <link linkend="class_fiber_specific_ptr"><code>fiber_specific_ptr</code></link> by 10442 providing a cleanup routine <code><phrase role="identifier">func</phrase></code> 10443 to the constructor. In this case, the object is destroyed by invoking <code><phrase 10444 role="identifier">func</phrase><phrase role="special">(</phrase><phrase role="identifier">p</phrase><phrase 10445 role="special">)</phrase></code>. The cleanup functions are called in an unspecified 10446 order. 10447 </para> 10448 <para> 10449 <bridgehead renderas="sect4" id="class_fiber_specific_ptr_bridgehead"> 10450 <phrase id="class_fiber_specific_ptr"/> 10451 <link linkend="class_fiber_specific_ptr">Class 10452 <code>fiber_specific_ptr</code></link> 10453</bridgehead> 10454 </para> 10455<programlisting><phrase role="preprocessor">#include</phrase> <phrase role="special"><</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">></phrase> 10456 10457<phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase> 10458<phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase> 10459 10460<phrase role="keyword">template</phrase><phrase role="special"><</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">T</phrase> <phrase role="special">></phrase> 10461<phrase role="keyword">class</phrase> <phrase role="identifier">fiber_specific_ptr</phrase> <phrase role="special">{</phrase> 10462<phrase role="keyword">public</phrase><phrase role="special">:</phrase> 10463 <phrase role="keyword">typedef</phrase> <phrase role="identifier">T</phrase> <phrase role="identifier">element_type</phrase><phrase role="special">;</phrase> 10464 10465 <phrase role="identifier">fiber_specific_ptr</phrase><phrase role="special">();</phrase> 10466 10467 <phrase role="keyword">explicit</phrase> <phrase role="identifier">fiber_specific_ptr</phrase><phrase role="special">(</phrase> <phrase role="keyword">void</phrase><phrase role="special">(*</phrase><phrase role="identifier">fn</phrase><phrase role="special">)(</phrase><phrase role="identifier">T</phrase><phrase role="special">*)</phrase> <phrase role="special">);</phrase> 10468 10469 <phrase role="special">~</phrase><phrase role="identifier">fiber_specific_ptr</phrase><phrase role="special">();</phrase> 10470 10471 <phrase role="identifier">fiber_specific_ptr</phrase><phrase role="special">(</phrase> <phrase role="identifier">fiber_specific_ptr</phrase> <phrase role="keyword">const</phrase><phrase role="special">&)</phrase> <phrase role="special">=</phrase> <phrase role="keyword">delete</phrase><phrase role="special">;</phrase> 10472 <phrase role="identifier">fiber_specific_ptr</phrase> <phrase role="special">&</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">&)</phrase> <phrase role="special">=</phrase> <phrase role="keyword">delete</phrase><phrase role="special">;</phrase> 10473 10474 <phrase role="identifier">T</phrase> <phrase role="special">*</phrase> <phrase role="identifier">get</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 10475 10476 <phrase role="identifier">T</phrase> <phrase role="special">*</phrase> <phrase role="keyword">operator</phrase><phrase role="special">->()</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 10477 10478 <phrase role="identifier">T</phrase> <phrase role="special">&</phrase> <phrase role="keyword">operator</phrase><phrase role="special">*()</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 10479 10480 <phrase role="identifier">T</phrase> <phrase role="special">*</phrase> <phrase role="identifier">release</phrase><phrase role="special">();</phrase> 10481 10482 <phrase role="keyword">void</phrase> <phrase role="identifier">reset</phrase><phrase role="special">(</phrase> <phrase role="identifier">T</phrase> <phrase role="special">*);</phrase> 10483<phrase role="special">};</phrase> 10484 10485<phrase role="special">}}</phrase> 10486</programlisting> 10487 <bridgehead renderas="sect3" id="fiber.fls.h2"> 10488 <phrase id="fiber.fls.constructor"/><link linkend="fiber.fls.constructor">Constructor</link> 10489 </bridgehead> 10490<programlisting><phrase role="identifier">fiber_specific_ptr</phrase><phrase role="special">();</phrase> 10491<phrase role="keyword">explicit</phrase> <phrase role="identifier">fiber_specific_ptr</phrase><phrase role="special">(</phrase> <phrase role="keyword">void</phrase><phrase role="special">(*</phrase><phrase role="identifier">fn</phrase><phrase role="special">)(</phrase><phrase role="identifier">T</phrase><phrase role="special">*)</phrase> <phrase role="special">);</phrase> 10492</programlisting> 10493 <variablelist> 10494 <title></title> 10495 <varlistentry> 10496 <term>Requires:</term> 10497 <listitem> 10498 <para> 10499 <code><phrase role="keyword">delete</phrase> <phrase role="keyword">this</phrase><phrase 10500 role="special">-></phrase><phrase role="identifier">get</phrase><phrase 10501 role="special">()</phrase></code> is well-formed; <code><phrase role="identifier">fn</phrase><phrase 10502 role="special">(</phrase><phrase role="keyword">this</phrase><phrase 10503 role="special">-></phrase><phrase role="identifier">get</phrase><phrase 10504 role="special">())</phrase></code> does not throw 10505 </para> 10506 </listitem> 10507 </varlistentry> 10508 <varlistentry> 10509 <term>Effects:</term> 10510 <listitem> 10511 <para> 10512 Construct a <link linkend="class_fiber_specific_ptr"><code>fiber_specific_ptr</code></link> object for storing 10513 a pointer to an object of type <code><phrase role="identifier">T</phrase></code> 10514 specific to each fiber. When <code><phrase role="identifier">reset</phrase><phrase 10515 role="special">()</phrase></code> is called, or the fiber exits, <link linkend="class_fiber_specific_ptr"><code>fiber_specific_ptr</code></link> calls 10516 <code><phrase role="identifier">fn</phrase><phrase role="special">(</phrase><phrase 10517 role="keyword">this</phrase><phrase role="special">-></phrase><phrase 10518 role="identifier">get</phrase><phrase role="special">())</phrase></code>. 10519 If the no-arguments constructor is used, the default <code><phrase role="keyword">delete</phrase></code>-based 10520 cleanup function will be used to destroy the fiber-local objects. 10521 </para> 10522 </listitem> 10523 </varlistentry> 10524 <varlistentry> 10525 <term>Throws:</term> 10526 <listitem> 10527 <para> 10528 <code><phrase role="identifier">fiber_error</phrase></code> if an error 10529 occurs. 10530 </para> 10531 </listitem> 10532 </varlistentry> 10533 </variablelist> 10534 <bridgehead renderas="sect3" id="fiber.fls.h3"> 10535 <phrase id="fiber.fls.destructor"/><link linkend="fiber.fls.destructor">Destructor</link> 10536 </bridgehead> 10537<programlisting><phrase role="special">~</phrase><phrase role="identifier">fiber_specific_ptr</phrase><phrase role="special">();</phrase> 10538</programlisting> 10539 <variablelist> 10540 <title></title> 10541 <varlistentry> 10542 <term>Requires:</term> 10543 <listitem> 10544 <para> 10545 All the fiber specific instances associated to this <link linkend="class_fiber_specific_ptr"><code>fiber_specific_ptr</code></link> 10546(except 10547 maybe the one associated to this fiber) must be nullptr. 10548 </para> 10549 </listitem> 10550 </varlistentry> 10551 <varlistentry> 10552 <term>Effects:</term> 10553 <listitem> 10554 <para> 10555 Calls <code><phrase role="keyword">this</phrase><phrase role="special">-></phrase><phrase 10556 role="identifier">reset</phrase><phrase role="special">()</phrase></code> 10557 to clean up the associated value for the current fiber, and destroys 10558 <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>. 10559 </para> 10560 </listitem> 10561 </varlistentry> 10562 <varlistentry> 10563 <term>Remarks:</term> 10564 <listitem> 10565 <para> 10566 The requirement is an implementation restriction. If the destructor promised 10567 to delete instances for all fibers, the implementation would be forced 10568 to maintain a list of all the fibers having an associated specific ptr, 10569 which is against the goal of fiber specific data. In general, a <link linkend="class_fiber_specific_ptr"><code>fiber_specific_ptr</code></link> should 10570 outlive the fibers that use it. 10571 </para> 10572 </listitem> 10573 </varlistentry> 10574 </variablelist> 10575 <note> 10576 <para> 10577 Care needs to be taken to ensure that any fibers still running after an instance 10578 of <link linkend="class_fiber_specific_ptr"><code>fiber_specific_ptr</code></link> has been destroyed do not call 10579 any member functions on that instance. 10580 </para> 10581 </note> 10582 <para> 10583 <bridgehead renderas="sect4" id="fiber_specific_ptr_get_bridgehead"> 10584 <phrase id="fiber_specific_ptr_get"/> 10585 <link linkend="fiber_specific_ptr_get">Member 10586 function <code>get</code>()</link> 10587</bridgehead> 10588 </para> 10589<programlisting><phrase role="identifier">T</phrase> <phrase role="special">*</phrase> <phrase role="identifier">get</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 10590</programlisting> 10591 <variablelist> 10592 <title></title> 10593 <varlistentry> 10594 <term>Returns:</term> 10595 <listitem> 10596 <para> 10597 The pointer associated with the current fiber. 10598 </para> 10599 </listitem> 10600 </varlistentry> 10601 <varlistentry> 10602 <term>Throws:</term> 10603 <listitem> 10604 <para> 10605 Nothing. 10606 </para> 10607 </listitem> 10608 </varlistentry> 10609 </variablelist> 10610 <note> 10611 <para> 10612 The initial value associated with an instance of <link linkend="class_fiber_specific_ptr"><code>fiber_specific_ptr</code></link> is 10613 <code><phrase role="keyword">nullptr</phrase></code> for each fiber. 10614 </para> 10615 </note> 10616 <para> 10617 <bridgehead renderas="sect4" id="fiber_specific_ptr_operator_arrow_bridgehead"> 10618 <phrase id="fiber_specific_ptr_operator_arrow"/> 10619 <link linkend="fiber_specific_ptr_operator_arrow">Member 10620 function <code>operator-></code>()</link> 10621</bridgehead> 10622 </para> 10623<programlisting><phrase role="identifier">T</phrase> <phrase role="special">*</phrase> <phrase role="keyword">operator</phrase><phrase role="special">->()</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 10624</programlisting> 10625 <variablelist> 10626 <title></title> 10627 <varlistentry> 10628 <term>Requires:</term> 10629 <listitem> 10630 <para> 10631 <code><phrase role="keyword">this</phrase><phrase role="special">-></phrase><phrase 10632 role="identifier">get</phrase><phrase role="special">()</phrase></code> 10633 is not <code><phrase role="keyword">nullptr</phrase></code>. 10634 </para> 10635 </listitem> 10636 </varlistentry> 10637 <varlistentry> 10638 <term>Returns:</term> 10639 <listitem> 10640 <para> 10641 <code><phrase role="keyword">this</phrase><phrase role="special">-></phrase><phrase 10642 role="identifier">get</phrase><phrase role="special">()</phrase></code> 10643 </para> 10644 </listitem> 10645 </varlistentry> 10646 <varlistentry> 10647 <term>Throws:</term> 10648 <listitem> 10649 <para> 10650 Nothing. 10651 </para> 10652 </listitem> 10653 </varlistentry> 10654 </variablelist> 10655 <para> 10656 <bridgehead renderas="sect4" id="fiber_specific_ptr_operator_star_bridgehead"> 10657 <phrase id="fiber_specific_ptr_operator_star"/> 10658 <link linkend="fiber_specific_ptr_operator_star">Member 10659 function <code>operator*</code>()</link> 10660</bridgehead> 10661 </para> 10662<programlisting><phrase role="identifier">T</phrase> <phrase role="special">&</phrase> <phrase role="keyword">operator</phrase><phrase role="special">*()</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 10663</programlisting> 10664 <variablelist> 10665 <title></title> 10666 <varlistentry> 10667 <term>Requires:</term> 10668 <listitem> 10669 <para> 10670 <code><phrase role="keyword">this</phrase><phrase role="special">-></phrase><phrase 10671 role="identifier">get</phrase><phrase role="special">()</phrase></code> 10672 is not <code><phrase role="keyword">nullptr</phrase></code>. 10673 </para> 10674 </listitem> 10675 </varlistentry> 10676 <varlistentry> 10677 <term>Returns:</term> 10678 <listitem> 10679 <para> 10680 <code><phrase role="special">*(</phrase><phrase role="keyword">this</phrase><phrase 10681 role="special">-></phrase><phrase role="identifier">get</phrase><phrase 10682 role="special">())</phrase></code> 10683 </para> 10684 </listitem> 10685 </varlistentry> 10686 <varlistentry> 10687 <term>Throws:</term> 10688 <listitem> 10689 <para> 10690 Nothing. 10691 </para> 10692 </listitem> 10693 </varlistentry> 10694 </variablelist> 10695 <para> 10696 <bridgehead renderas="sect4" id="fiber_specific_ptr_release_bridgehead"> 10697 <phrase id="fiber_specific_ptr_release"/> 10698 <link linkend="fiber_specific_ptr_release">Member 10699 function <code>release</code>()</link> 10700</bridgehead> 10701 </para> 10702<programlisting><phrase role="identifier">T</phrase> <phrase role="special">*</phrase> <phrase role="identifier">release</phrase><phrase role="special">();</phrase> 10703</programlisting> 10704 <variablelist> 10705 <title></title> 10706 <varlistentry> 10707 <term>Effects:</term> 10708 <listitem> 10709 <para> 10710 Return <code><phrase role="keyword">this</phrase><phrase role="special">-></phrase><phrase 10711 role="identifier">get</phrase><phrase role="special">()</phrase></code> 10712 and store <code><phrase role="keyword">nullptr</phrase></code> as the 10713 pointer associated with the current fiber without invoking the cleanup 10714 function. 10715 </para> 10716 </listitem> 10717 </varlistentry> 10718 <varlistentry> 10719 <term>Postcondition:</term> 10720 <listitem> 10721 <para> 10722 <code><phrase role="keyword">this</phrase><phrase role="special">-></phrase><phrase 10723 role="identifier">get</phrase><phrase role="special">()==</phrase><phrase 10724 role="keyword">nullptr</phrase></code> 10725 </para> 10726 </listitem> 10727 </varlistentry> 10728 <varlistentry> 10729 <term>Throws:</term> 10730 <listitem> 10731 <para> 10732 Nothing. 10733 </para> 10734 </listitem> 10735 </varlistentry> 10736 </variablelist> 10737 <para> 10738 <bridgehead renderas="sect4" id="fiber_specific_ptr_reset_bridgehead"> 10739 <phrase id="fiber_specific_ptr_reset"/> 10740 <link linkend="fiber_specific_ptr_reset">Member 10741 function <code>reset</code>()</link> 10742</bridgehead> 10743 </para> 10744<programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">reset</phrase><phrase role="special">(</phrase> <phrase role="identifier">T</phrase> <phrase role="special">*</phrase> <phrase role="identifier">new_value</phrase><phrase role="special">);</phrase> 10745</programlisting> 10746 <variablelist> 10747 <title></title> 10748 <varlistentry> 10749 <term>Effects:</term> 10750 <listitem> 10751 <para> 10752 If <code><phrase role="keyword">this</phrase><phrase role="special">-></phrase><phrase 10753 role="identifier">get</phrase><phrase role="special">()!=</phrase><phrase 10754 role="identifier">new_value</phrase></code> and <code><phrase role="keyword">this</phrase><phrase 10755 role="special">-></phrase><phrase role="identifier">get</phrase><phrase 10756 role="special">()</phrase></code> is not <code><phrase role="keyword">nullptr</phrase></code>, 10757 invoke <code><phrase role="keyword">delete</phrase> <phrase role="keyword">this</phrase><phrase 10758 role="special">-></phrase><phrase role="identifier">get</phrase><phrase 10759 role="special">()</phrase></code> or <code><phrase role="identifier">fn</phrase><phrase 10760 role="special">(</phrase><phrase role="keyword">this</phrase><phrase 10761 role="special">-></phrase><phrase role="identifier">get</phrase><phrase 10762 role="special">())</phrase></code> as appropriate. Store <code><phrase 10763 role="identifier">new_value</phrase></code> as the pointer associated 10764 with the current fiber. 10765 </para> 10766 </listitem> 10767 </varlistentry> 10768 <varlistentry> 10769 <term>Postcondition:</term> 10770 <listitem> 10771 <para> 10772 <code><phrase role="keyword">this</phrase><phrase role="special">-></phrase><phrase 10773 role="identifier">get</phrase><phrase role="special">()==</phrase><phrase 10774 role="identifier">new_value</phrase></code> 10775 </para> 10776 </listitem> 10777 </varlistentry> 10778 <varlistentry> 10779 <term>Throws:</term> 10780 <listitem> 10781 <para> 10782 Exception raised during cleanup of previous value. 10783 </para> 10784 </listitem> 10785 </varlistentry> 10786 </variablelist> 10787 </section> 10788 <section id="fiber.migration"> 10789 <title><anchor id="migration"/><link linkend="fiber.migration">Migrating fibers 10790 between threads</link></title> 10791 <bridgehead renderas="sect3" id="fiber.migration.h0"> 10792 <phrase id="fiber.migration.overview"/><link linkend="fiber.migration.overview">Overview</link> 10793 </bridgehead> 10794 <para> 10795 Each fiber owns a stack and manages its execution state, including all registers 10796 and CPU flags, the instruction pointer and the stack pointer. That means, in 10797 general, a fiber is not bound to a specific thread.<footnote id="fiber.migration.f0"> 10798 <para> 10799 The <quote>main</quote> fiber on each thread, that is, the fiber on which 10800 the thread is launched, cannot migrate to any other thread. Also <emphasis 10801 role="bold">Boost.Fiber</emphasis> implicitly creates a dispatcher fiber 10802 for each thread — this cannot migrate either. 10803 </para> 10804 </footnote><superscript>,</superscript><footnote id="fiber.migration.f1"> 10805 <para> 10806 Of course it would be problematic to migrate a fiber that relies on <link 10807 linkend="thread_local_storage">thread-local storage</link>. 10808 </para> 10809 </footnote> 10810 </para> 10811 <para> 10812 Migrating a fiber from a logical CPU with heavy workload to another logical 10813 CPU with a lighter workload might speed up the overall execution. Note that 10814 in the case of NUMA-architectures, it is not always advisable to migrate data 10815 between threads. Suppose fiber <emphasis>f</emphasis> is running on logical 10816 CPU <emphasis>cpu0</emphasis> which belongs to NUMA node <emphasis>node0</emphasis>. 10817 The data of <emphasis>f</emphasis> are allocated on the physical memory located 10818 at <emphasis>node0</emphasis>. Migrating the fiber from <emphasis>cpu0</emphasis> 10819 to another logical CPU <emphasis>cpuX</emphasis> which is part of a different 10820 NUMA node <emphasis>nodeX</emphasis> might reduce the performance of the application 10821 due to increased latency of memory access. 10822 </para> 10823 <para> 10824 Only fibers that are contained in <link linkend="class_algorithm"><code>algorithm</code></link>’s ready queue can 10825 migrate between threads. You cannot migrate a running fiber, nor one that is 10826 <link linkend="blocking"><emphasis>blocked</emphasis></link>. You cannot migrate 10827 a fiber if its <link linkend="context_is_context"><code>context::is_context()</code></link> method returns <code><phrase 10828 role="keyword">true</phrase></code> for <code><phrase role="identifier">pinned_context</phrase></code>. 10829 </para> 10830 <para> 10831 In <emphasis role="bold">Boost.Fiber</emphasis> a fiber is migrated by invoking 10832 <link linkend="context_detach"><code>context::detach()</code></link> on the thread from which the fiber migrates 10833 and <link linkend="context_attach"><code>context::attach()</code></link> on the thread to which the fiber migrates. 10834 </para> 10835 <para> 10836 Thus, fiber migration is accomplished by sharing state between instances of 10837 a user-coded <link linkend="class_algorithm"><code>algorithm</code></link> implementation running on different threads. 10838 The fiber’s original thread calls <link linkend="algorithm_awakened"><code>algorithm::awakened()</code></link>, passing 10839 the fiber’s <link linkend="class_context"><code>context</code></link><literal>*</literal>. The <code><phrase role="identifier">awakened</phrase><phrase 10840 role="special">()</phrase></code> implementation calls <link linkend="context_detach"><code>context::detach()</code></link>. 10841 </para> 10842 <para> 10843 At some later point, when the same or a different thread calls <link linkend="algorithm_pick_next"><code>algorithm::pick_next()</code></link>, 10844 the <code><phrase role="identifier">pick_next</phrase><phrase role="special">()</phrase></code> 10845 implementation selects a ready fiber and calls <link linkend="context_attach"><code>context::attach()</code></link> on 10846 it before returning it. 10847 </para> 10848 <para> 10849 As stated above, a <code><phrase role="identifier">context</phrase></code> 10850 for which <code><phrase role="identifier">is_context</phrase><phrase role="special">(</phrase><phrase 10851 role="identifier">pinned_context</phrase><phrase role="special">)</phrase> 10852 <phrase role="special">==</phrase> <phrase role="keyword">true</phrase></code> 10853 must never be passed to either <link linkend="context_detach"><code>context::detach()</code></link> or <link linkend="context_attach"><code>context::attach()</code></link>. 10854 It may only be returned from <code><phrase role="identifier">pick_next</phrase><phrase 10855 role="special">()</phrase></code> called by the <emphasis>same</emphasis> thread 10856 that passed that context to <code><phrase role="identifier">awakened</phrase><phrase 10857 role="special">()</phrase></code>. 10858 </para> 10859 <bridgehead renderas="sect3" id="fiber.migration.h1"> 10860 <phrase id="fiber.migration.example_of_work_sharing"/><link linkend="fiber.migration.example_of_work_sharing">Example 10861 of work sharing</link> 10862 </bridgehead> 10863 <para> 10864 In the example <ulink url="../../examples/work_sharing.cpp">work_sharing.cpp</ulink> 10865 multiple worker fibers are created on the main thread. Each fiber gets a character 10866 as parameter at construction. This character is printed out ten times. Between 10867 each iteration the fiber calls <link linkend="this_fiber_yield"><code>this_fiber::yield()</code></link>. That puts 10868 the fiber in the ready queue of the fiber-scheduler <emphasis>shared_ready_queue</emphasis>, 10869 running in the current thread. The next fiber ready to be executed is dequeued 10870 from the shared ready queue and resumed by <emphasis>shared_ready_queue</emphasis> 10871 running on <emphasis>any participating thread</emphasis>. 10872 </para> 10873 <para> 10874 All instances of <emphasis>shared_ready_queue</emphasis> share one global concurrent 10875 queue, used as ready queue. This mechanism shares all worker fibers between 10876 all instances of <emphasis>shared_ready_queue</emphasis>, thus between all 10877 participating threads. 10878 </para> 10879 <bridgehead renderas="sect3" id="fiber.migration.h2"> 10880 <phrase id="fiber.migration.setup_of_threads_and_fibers"/><link linkend="fiber.migration.setup_of_threads_and_fibers">Setup 10881 of threads and fibers</link> 10882 </bridgehead> 10883 <para> 10884 In <code><phrase role="identifier">main</phrase><phrase role="special">()</phrase></code> 10885 the fiber-scheduler is installed and the worker fibers and the threads are 10886 launched. 10887 </para> 10888 <para> 10889<programlisting><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">use_scheduling_algorithm</phrase><phrase role="special"><</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">>();</phrase> <co id="fiber.migration.c0" linkends="fiber.migration.c1" /> 10890 10891<phrase role="keyword">for</phrase> <phrase role="special">(</phrase> <phrase role="keyword">char</phrase> <phrase role="identifier">c</phrase> <phrase role="special">:</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase><phrase role="special">(</phrase><phrase role="string">"abcdefghijklmnopqrstuvwxyz"</phrase><phrase role="special">))</phrase> <phrase role="special">{</phrase> <co id="fiber.migration.c2" linkends="fiber.migration.c3" /> 10892 <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">fiber</phrase><phrase role="special">([</phrase><phrase role="identifier">c</phrase><phrase role="special">](){</phrase> <phrase role="identifier">whatevah</phrase><phrase role="special">(</phrase> <phrase role="identifier">c</phrase><phrase role="special">);</phrase> <phrase role="special">}).</phrase><phrase role="identifier">detach</phrase><phrase role="special">();</phrase> 10893 <phrase role="special">++</phrase><phrase role="identifier">fiber_count</phrase><phrase role="special">;</phrase> <co id="fiber.migration.c4" linkends="fiber.migration.c5" /> 10894<phrase role="special">}</phrase> 10895<phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">detail</phrase><phrase role="special">::</phrase><phrase role="identifier">thread_barrier</phrase> <phrase role="identifier">b</phrase><phrase role="special">(</phrase> <phrase role="number">4</phrase><phrase role="special">);</phrase> 10896<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">thread</phrase> <phrase role="identifier">threads</phrase><phrase role="special">[]</phrase> <phrase role="special">=</phrase> <phrase role="special">{</phrase> <co id="fiber.migration.c6" linkends="fiber.migration.c7" /> 10897 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">thread</phrase><phrase role="special">(</phrase> <phrase role="identifier">thread</phrase><phrase role="special">,</phrase> <phrase role="special">&</phrase> <phrase role="identifier">b</phrase><phrase role="special">),</phrase> 10898 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">thread</phrase><phrase role="special">(</phrase> <phrase role="identifier">thread</phrase><phrase role="special">,</phrase> <phrase role="special">&</phrase> <phrase role="identifier">b</phrase><phrase role="special">),</phrase> 10899 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">thread</phrase><phrase role="special">(</phrase> <phrase role="identifier">thread</phrase><phrase role="special">,</phrase> <phrase role="special">&</phrase> <phrase role="identifier">b</phrase><phrase role="special">)</phrase> 10900<phrase role="special">};</phrase> 10901<phrase role="identifier">b</phrase><phrase role="special">.</phrase><phrase role="identifier">wait</phrase><phrase role="special">();</phrase> <co id="fiber.migration.c8" linkends="fiber.migration.c9" /> 10902<phrase role="special">{</phrase> 10903 <phrase role="identifier">lock_type</phrase><co id="fiber.migration.c10" linkends="fiber.migration.c11" /> <phrase role="identifier">lk</phrase><phrase role="special">(</phrase> <phrase role="identifier">mtx_count</phrase><phrase role="special">);</phrase> 10904 <phrase role="identifier">cnd_count</phrase><phrase role="special">.</phrase><phrase role="identifier">wait</phrase><phrase role="special">(</phrase> <phrase role="identifier">lk</phrase><phrase role="special">,</phrase> <phrase role="special">[](){</phrase> <phrase role="keyword">return</phrase> <phrase role="number">0</phrase> <phrase role="special">==</phrase> <phrase role="identifier">fiber_count</phrase><phrase role="special">;</phrase> <phrase role="special">}</phrase> <phrase role="special">);</phrase> <co id="fiber.migration.c12" linkends="fiber.migration.c13" /> 10905<phrase role="special">}</phrase> <co id="fiber.migration.c14" linkends="fiber.migration.c15" /> 10906<phrase role="identifier">BOOST_ASSERT</phrase><phrase role="special">(</phrase> <phrase role="number">0</phrase> <phrase role="special">==</phrase> <phrase role="identifier">fiber_count</phrase><phrase role="special">);</phrase> 10907<phrase role="keyword">for</phrase> <phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">thread</phrase> <phrase role="special">&</phrase> <phrase role="identifier">t</phrase> <phrase role="special">:</phrase> <phrase role="identifier">threads</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase> <co id="fiber.migration.c16" linkends="fiber.migration.c17" /> 10908 <phrase role="identifier">t</phrase><phrase role="special">.</phrase><phrase role="identifier">join</phrase><phrase role="special">();</phrase> 10909<phrase role="special">}</phrase> 10910</programlisting> 10911 </para> 10912 <calloutlist> 10913 <callout arearefs="fiber.migration.c0" id="fiber.migration.c1"> 10914 <para> 10915 Install the scheduling algorithm <code><phrase role="identifier">boost</phrase><phrase 10916 role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase 10917 role="special">::</phrase><phrase role="identifier">algo</phrase><phrase 10918 role="special">::</phrase><phrase role="identifier">shared_work</phrase></code> 10919 in the main thread too, so each new fiber gets launched into the shared 10920 pool. 10921 </para> 10922 </callout> 10923 <callout arearefs="fiber.migration.c2" id="fiber.migration.c3"> 10924 <para> 10925 Launch a number of worker fibers; each worker fiber picks up a character 10926 that is passed as parameter to fiber-function <code><phrase role="identifier">whatevah</phrase></code>. 10927 Each worker fiber gets detached. 10928 </para> 10929 </callout> 10930 <callout arearefs="fiber.migration.c4" id="fiber.migration.c5"> 10931 <para> 10932 Increment fiber counter for each new fiber. 10933 </para> 10934 </callout> 10935 <callout arearefs="fiber.migration.c6" id="fiber.migration.c7"> 10936 <para> 10937 Launch a couple of threads that join the work sharing. 10938 </para> 10939 </callout> 10940 <callout arearefs="fiber.migration.c8" id="fiber.migration.c9"> 10941 <para> 10942 sync with other threads: allow them to start processing 10943 </para> 10944 </callout> 10945 <callout arearefs="fiber.migration.c10" id="fiber.migration.c11"> 10946 <para> 10947 <code><phrase role="identifier">lock_type</phrase></code> is typedef'ed 10948 as <ulink url="http://en.cppreference.com/w/cpp/thread/unique_lock"><code><phrase 10949 role="identifier">std</phrase><phrase role="special">::</phrase><phrase 10950 role="identifier">unique_lock</phrase></code></ulink>< <ulink url="http://en.cppreference.com/w/cpp/thread/mutex"><code><phrase 10951 role="identifier">std</phrase><phrase role="special">::</phrase><phrase 10952 role="identifier">mutex</phrase></code></ulink> > 10953 </para> 10954 </callout> 10955 <callout arearefs="fiber.migration.c12" id="fiber.migration.c13"> 10956 <para> 10957 Suspend main fiber and resume worker fibers in the meanwhile. Main fiber 10958 gets resumed (e.g returns from <code><phrase role="identifier">condition_variable_any</phrase><phrase 10959 role="special">::</phrase><phrase role="identifier">wait</phrase><phrase 10960 role="special">()</phrase></code>) if all worker fibers are complete. 10961 </para> 10962 </callout> 10963 <callout arearefs="fiber.migration.c14" id="fiber.migration.c15"> 10964 <para> 10965 Releasing lock of mtx_count is required before joining the threads, otherwise 10966 the other threads would be blocked inside condition_variable::wait() and 10967 would never return (deadlock). 10968 </para> 10969 </callout> 10970 <callout arearefs="fiber.migration.c16" id="fiber.migration.c17"> 10971 <para> 10972 wait for threads to terminate 10973 </para> 10974 </callout> 10975 </calloutlist> 10976 <para> 10977 The start of the threads is synchronized with a barrier. The main fiber of 10978 each thread (including main thread) is suspended until all worker fibers are 10979 complete. When the main fiber returns from <link linkend="condition_variable_wait"><code>condition_variable::wait()</code></link>, 10980 the thread terminates: the main thread joins all other threads. 10981 </para> 10982 <para> 10983<programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">thread</phrase><phrase role="special">(</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">detail</phrase><phrase role="special">::</phrase><phrase role="identifier">thread_barrier</phrase> <phrase role="special">*</phrase> <phrase role="identifier">b</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase> 10984 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">ostringstream</phrase> <phrase role="identifier">buffer</phrase><phrase role="special">;</phrase> 10985 <phrase role="identifier">buffer</phrase> <phrase role="special"><<</phrase> <phrase role="string">"thread started "</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> <phrase role="special"><<</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">endl</phrase><phrase role="special">;</phrase> 10986 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cout</phrase> <phrase role="special"><<</phrase> <phrase role="identifier">buffer</phrase><phrase role="special">.</phrase><phrase role="identifier">str</phrase><phrase role="special">()</phrase> <phrase role="special"><<</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">flush</phrase><phrase role="special">;</phrase> 10987 <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">use_scheduling_algorithm</phrase><phrase role="special"><</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">>();</phrase> <co id="fiber.migration.c18" linkends="fiber.migration.c19" /> 10988 <phrase role="identifier">b</phrase><phrase role="special">-></phrase><phrase role="identifier">wait</phrase><phrase role="special">();</phrase> <co id="fiber.migration.c20" linkends="fiber.migration.c21" /> 10989 <phrase role="identifier">lock_type</phrase> <phrase role="identifier">lk</phrase><phrase role="special">(</phrase> <phrase role="identifier">mtx_count</phrase><phrase role="special">);</phrase> 10990 <phrase role="identifier">cnd_count</phrase><phrase role="special">.</phrase><phrase role="identifier">wait</phrase><phrase role="special">(</phrase> <phrase role="identifier">lk</phrase><phrase role="special">,</phrase> <phrase role="special">[](){</phrase> <phrase role="keyword">return</phrase> <phrase role="number">0</phrase> <phrase role="special">==</phrase> <phrase role="identifier">fiber_count</phrase><phrase role="special">;</phrase> <phrase role="special">}</phrase> <phrase role="special">);</phrase> <co id="fiber.migration.c22" linkends="fiber.migration.c23" /> 10991 <phrase role="identifier">BOOST_ASSERT</phrase><phrase role="special">(</phrase> <phrase role="number">0</phrase> <phrase role="special">==</phrase> <phrase role="identifier">fiber_count</phrase><phrase role="special">);</phrase> 10992<phrase role="special">}</phrase> 10993</programlisting> 10994 </para> 10995 <calloutlist> 10996 <callout arearefs="fiber.migration.c18" id="fiber.migration.c19"> 10997 <para> 10998 Install the scheduling algorithm <code><phrase role="identifier">boost</phrase><phrase 10999 role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase 11000 role="special">::</phrase><phrase role="identifier">algo</phrase><phrase 11001 role="special">::</phrase><phrase role="identifier">shared_work</phrase></code> 11002 in order to join the work sharing. 11003 </para> 11004 </callout> 11005 <callout arearefs="fiber.migration.c20" id="fiber.migration.c21"> 11006 <para> 11007 sync with other threads: allow them to start processing 11008 </para> 11009 </callout> 11010 <callout arearefs="fiber.migration.c22" id="fiber.migration.c23"> 11011 <para> 11012 Suspend main fiber and resume worker fibers in the meanwhile. Main fiber 11013 gets resumed (e.g returns from <code><phrase role="identifier">condition_variable_any</phrase><phrase 11014 role="special">::</phrase><phrase role="identifier">wait</phrase><phrase 11015 role="special">()</phrase></code>) if all worker fibers are complete. 11016 </para> 11017 </callout> 11018 </calloutlist> 11019 <para> 11020 Each worker fiber executes function <code><phrase role="identifier">whatevah</phrase><phrase 11021 role="special">()</phrase></code> with character <code><phrase role="identifier">me</phrase></code> 11022 as parameter. The fiber yields in a loop and prints out a message if it was 11023 migrated to another thread. 11024 </para> 11025 <para> 11026<programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">whatevah</phrase><phrase role="special">(</phrase> <phrase role="keyword">char</phrase> <phrase role="identifier">me</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase> 11027 <phrase role="keyword">try</phrase> <phrase role="special">{</phrase> 11028 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">thread</phrase><phrase role="special">::</phrase><phrase role="identifier">id</phrase> <phrase role="identifier">my_thread</phrase> <phrase role="special">=</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">this_thread</phrase><phrase role="special">::</phrase><phrase role="identifier">get_id</phrase><phrase role="special">();</phrase> <co id="fiber.migration.c24" linkends="fiber.migration.c25" /> 11029 <phrase role="special">{</phrase> 11030 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">ostringstream</phrase> <phrase role="identifier">buffer</phrase><phrase role="special">;</phrase> 11031 <phrase role="identifier">buffer</phrase> <phrase role="special"><<</phrase> <phrase role="string">"fiber "</phrase> <phrase role="special"><<</phrase> <phrase role="identifier">me</phrase> <phrase role="special"><<</phrase> <phrase role="string">" started on thread "</phrase> <phrase role="special"><<</phrase> <phrase role="identifier">my_thread</phrase> <phrase role="special"><<</phrase> <phrase role="char">'\n'</phrase><phrase role="special">;</phrase> 11032 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cout</phrase> <phrase role="special"><<</phrase> <phrase role="identifier">buffer</phrase><phrase role="special">.</phrase><phrase role="identifier">str</phrase><phrase role="special">()</phrase> <phrase role="special"><<</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">flush</phrase><phrase role="special">;</phrase> 11033 <phrase role="special">}</phrase> 11034 <phrase role="keyword">for</phrase> <phrase role="special">(</phrase> <phrase role="keyword">unsigned</phrase> <phrase role="identifier">i</phrase> <phrase role="special">=</phrase> <phrase role="number">0</phrase><phrase role="special">;</phrase> <phrase role="identifier">i</phrase> <phrase role="special"><</phrase> <phrase role="number">10</phrase><phrase role="special">;</phrase> <phrase role="special">++</phrase><phrase role="identifier">i</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase> <co id="fiber.migration.c26" linkends="fiber.migration.c27" /> 11035 <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">this_fiber</phrase><phrase role="special">::</phrase><phrase role="identifier">yield</phrase><phrase role="special">();</phrase> <co id="fiber.migration.c28" linkends="fiber.migration.c29" /> 11036 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">thread</phrase><phrase role="special">::</phrase><phrase role="identifier">id</phrase> <phrase role="identifier">new_thread</phrase> <phrase role="special">=</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">this_thread</phrase><phrase role="special">::</phrase><phrase role="identifier">get_id</phrase><phrase role="special">();</phrase> <co id="fiber.migration.c30" linkends="fiber.migration.c31" /> 11037 <phrase role="keyword">if</phrase> <phrase role="special">(</phrase> <phrase role="identifier">new_thread</phrase> <phrase role="special">!=</phrase> <phrase role="identifier">my_thread</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase> <co id="fiber.migration.c32" linkends="fiber.migration.c33" /> 11038 <phrase role="identifier">my_thread</phrase> <phrase role="special">=</phrase> <phrase role="identifier">new_thread</phrase><phrase role="special">;</phrase> 11039 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">ostringstream</phrase> <phrase role="identifier">buffer</phrase><phrase role="special">;</phrase> 11040 <phrase role="identifier">buffer</phrase> <phrase role="special"><<</phrase> <phrase role="string">"fiber "</phrase> <phrase role="special"><<</phrase> <phrase role="identifier">me</phrase> <phrase role="special"><<</phrase> <phrase role="string">" switched to thread "</phrase> <phrase role="special"><<</phrase> <phrase role="identifier">my_thread</phrase> <phrase role="special"><<</phrase> <phrase role="char">'\n'</phrase><phrase role="special">;</phrase> 11041 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cout</phrase> <phrase role="special"><<</phrase> <phrase role="identifier">buffer</phrase><phrase role="special">.</phrase><phrase role="identifier">str</phrase><phrase role="special">()</phrase> <phrase role="special"><<</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">flush</phrase><phrase role="special">;</phrase> 11042 <phrase role="special">}</phrase> 11043 <phrase role="special">}</phrase> 11044 <phrase role="special">}</phrase> <phrase role="keyword">catch</phrase> <phrase role="special">(</phrase> <phrase role="special">...</phrase> <phrase role="special">)</phrase> <phrase role="special">{</phrase> 11045 <phrase role="special">}</phrase> 11046 <phrase role="identifier">lock_type</phrase> <phrase role="identifier">lk</phrase><phrase role="special">(</phrase> <phrase role="identifier">mtx_count</phrase><phrase role="special">);</phrase> 11047 <phrase role="keyword">if</phrase> <phrase role="special">(</phrase> <phrase role="number">0</phrase> <phrase role="special">==</phrase> <phrase role="special">--</phrase><phrase role="identifier">fiber_count</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase> <co id="fiber.migration.c34" linkends="fiber.migration.c35" /> 11048 <phrase role="identifier">lk</phrase><phrase role="special">.</phrase><phrase role="identifier">unlock</phrase><phrase role="special">();</phrase> 11049 <phrase role="identifier">cnd_count</phrase><phrase role="special">.</phrase><phrase role="identifier">notify_all</phrase><phrase role="special">();</phrase> <co id="fiber.migration.c36" linkends="fiber.migration.c37" /> 11050 <phrase role="special">}</phrase> 11051<phrase role="special">}</phrase> 11052</programlisting> 11053 </para> 11054 <calloutlist> 11055 <callout arearefs="fiber.migration.c24" id="fiber.migration.c25"> 11056 <para> 11057 get ID of initial thread 11058 </para> 11059 </callout> 11060 <callout arearefs="fiber.migration.c26" id="fiber.migration.c27"> 11061 <para> 11062 loop ten times 11063 </para> 11064 </callout> 11065 <callout arearefs="fiber.migration.c28" id="fiber.migration.c29"> 11066 <para> 11067 yield to other fibers 11068 </para> 11069 </callout> 11070 <callout arearefs="fiber.migration.c30" id="fiber.migration.c31"> 11071 <para> 11072 get ID of current thread 11073 </para> 11074 </callout> 11075 <callout arearefs="fiber.migration.c32" id="fiber.migration.c33"> 11076 <para> 11077 test if fiber was migrated to another thread 11078 </para> 11079 </callout> 11080 <callout arearefs="fiber.migration.c34" id="fiber.migration.c35"> 11081 <para> 11082 Decrement fiber counter for each completed fiber. 11083 </para> 11084 </callout> 11085 <callout arearefs="fiber.migration.c36" id="fiber.migration.c37"> 11086 <para> 11087 Notify all fibers waiting on <code><phrase role="identifier">cnd_count</phrase></code>. 11088 </para> 11089 </callout> 11090 </calloutlist> 11091 <bridgehead renderas="sect3" id="fiber.migration.h3"> 11092 <phrase id="fiber.migration.scheduling_fibers"/><link linkend="fiber.migration.scheduling_fibers">Scheduling 11093 fibers</link> 11094 </bridgehead> 11095 <para> 11096 The fiber scheduler <code><phrase role="identifier">shared_ready_queue</phrase></code> 11097 is like <code><phrase role="identifier">round_robin</phrase></code>, except 11098 that it shares a common ready queue among all participating threads. A thread 11099 participates in this pool by executing <link linkend="use_scheduling_algorithm"><code>use_scheduling_algorithm()</code></link> 11100before 11101 any other <emphasis role="bold">Boost.Fiber</emphasis> operation. 11102 </para> 11103 <para> 11104 The important point about the ready queue is that it’s a class static, common 11105 to all instances of shared_ready_queue. Fibers that are enqueued via <link linkend="algorithm_awakened"><code>algorithm::awakened()</code></link> (fibers 11106 that are ready to be resumed) are thus available to all threads. It is required 11107 to reserve a separate, scheduler-specific queue for the thread’s main fiber 11108 and dispatcher fibers: these may <emphasis>not</emphasis> be shared between 11109 threads! When we’re passed either of these fibers, push it there instead of 11110 in the shared queue: it would be Bad News for thread B to retrieve and attempt 11111 to execute thread A’s main fiber. 11112 </para> 11113 <para> 11114 [awakened_ws] 11115 </para> 11116 <para> 11117 When <link linkend="algorithm_pick_next"><code>algorithm::pick_next()</code></link> gets called inside one thread, 11118 a fiber is dequeued from <emphasis>rqueue_</emphasis> and will be resumed in 11119 that thread. 11120 </para> 11121 <para> 11122 [pick_next_ws] 11123 </para> 11124 <para> 11125 The source code above is found in <ulink url="../../examples/work_sharing.cpp">work_sharing.cpp</ulink>. 11126 </para> 11127 </section> 11128 <section id="fiber.callbacks"> 11129 <title><anchor id="callbacks"/><link linkend="fiber.callbacks">Integrating Fibers 11130 with Asynchronous Callbacks</link></title> 11131 <section id="fiber.callbacks.overview"> 11132 <title><link linkend="fiber.callbacks.overview">Overview</link></title> 11133 <para> 11134 One of the primary benefits of <emphasis role="bold">Boost.Fiber</emphasis> 11135 is the ability to use asynchronous operations for efficiency, while at the 11136 same time structuring the calling code <emphasis>as if</emphasis> the operations 11137 were synchronous. Asynchronous operations provide completion notification 11138 in a variety of ways, but most involve a callback function of some kind. 11139 This section discusses tactics for interfacing <emphasis role="bold">Boost.Fiber</emphasis> 11140 with an arbitrary async operation. 11141 </para> 11142 <para> 11143 For purposes of illustration, consider the following hypothetical API: 11144 </para> 11145 <para> 11146<programlisting><phrase role="keyword">class</phrase> <phrase role="identifier">AsyncAPI</phrase> <phrase role="special">{</phrase> 11147<phrase role="keyword">public</phrase><phrase role="special">:</phrase> 11148 <phrase role="comment">// constructor acquires some resource that can be read and written</phrase> 11149 <phrase role="identifier">AsyncAPI</phrase><phrase role="special">();</phrase> 11150 11151 <phrase role="comment">// callbacks accept an int error code; 0 == success</phrase> 11152 <phrase role="keyword">typedef</phrase> <phrase role="keyword">int</phrase> <phrase role="identifier">errorcode</phrase><phrase role="special">;</phrase> 11153 11154 <phrase role="comment">// write callback only needs to indicate success or failure</phrase> 11155 <phrase role="keyword">template</phrase><phrase role="special"><</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Fn</phrase> <phrase role="special">></phrase> 11156 <phrase role="keyword">void</phrase> <phrase role="identifier">init_write</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">data</phrase><phrase role="special">,</phrase> <phrase role="identifier">Fn</phrase> <phrase role="special">&&</phrase> <phrase role="identifier">callback</phrase><phrase role="special">);</phrase> 11157 11158 <phrase role="comment">// read callback needs to accept both errorcode and data</phrase> 11159 <phrase role="keyword">template</phrase><phrase role="special"><</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Fn</phrase> <phrase role="special">></phrase> 11160 <phrase role="keyword">void</phrase> <phrase role="identifier">init_read</phrase><phrase role="special">(</phrase> <phrase role="identifier">Fn</phrase> <phrase role="special">&&</phrase> <phrase role="identifier">callback</phrase><phrase role="special">);</phrase> 11161 11162 <phrase role="comment">// ... other operations ...</phrase> 11163<phrase role="special">};</phrase> 11164</programlisting> 11165 </para> 11166 <para> 11167 The significant points about each of <code><phrase role="identifier">init_write</phrase><phrase 11168 role="special">()</phrase></code> and <code><phrase role="identifier">init_read</phrase><phrase 11169 role="special">()</phrase></code> are: 11170 </para> 11171 <itemizedlist> 11172 <listitem> 11173 <simpara> 11174 The <code><phrase role="identifier">AsyncAPI</phrase></code> method only 11175 initiates the operation. It returns immediately, while the requested 11176 operation is still pending. 11177 </simpara> 11178 </listitem> 11179 <listitem> 11180 <simpara> 11181 The method accepts a callback. When the operation completes, the callback 11182 is called with relevant parameters (error code, data if applicable). 11183 </simpara> 11184 </listitem> 11185 </itemizedlist> 11186 <para> 11187 We would like to wrap these asynchronous methods in functions that appear 11188 synchronous by blocking the calling fiber until the operation completes. 11189 This lets us use the wrapper function’s return value to deliver relevant data. 11190 </para> 11191 <tip> 11192 <para> 11193 <link linkend="class_promise"><code>promise<></code></link> and <link linkend="class_future"><code>future<></code></link> are your friends 11194 here. 11195 </para> 11196 </tip> 11197 </section> 11198 <section id="fiber.callbacks.return_errorcode"> 11199 <title><link linkend="fiber.callbacks.return_errorcode">Return Errorcode</link></title> 11200 <para> 11201 The <code><phrase role="identifier">AsyncAPI</phrase><phrase role="special">::</phrase><phrase 11202 role="identifier">init_write</phrase><phrase role="special">()</phrase></code> 11203 callback passes only an <code><phrase role="identifier">errorcode</phrase></code>. 11204 If we simply want the blocking wrapper to return that <code><phrase role="identifier">errorcode</phrase></code>, 11205 this is an extremely straightforward use of <link linkend="class_promise"><code>promise<></code></link> and 11206 <link linkend="class_future"><code>future<></code></link>: 11207 </para> 11208 <para> 11209<programlisting><phrase role="identifier">AsyncAPI</phrase><phrase role="special">::</phrase><phrase role="identifier">errorcode</phrase> <phrase role="identifier">write_ec</phrase><phrase role="special">(</phrase> <phrase role="identifier">AsyncAPI</phrase> <phrase role="special">&</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">&</phrase> <phrase role="identifier">data</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase> 11210 <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">promise</phrase><phrase role="special"><</phrase> <phrase role="identifier">AsyncAPI</phrase><phrase role="special">::</phrase><phrase role="identifier">errorcode</phrase> <phrase role="special">></phrase> <phrase role="identifier">promise</phrase><phrase role="special">;</phrase> 11211 <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">future</phrase><phrase role="special"><</phrase> <phrase role="identifier">AsyncAPI</phrase><phrase role="special">::</phrase><phrase role="identifier">errorcode</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">get_future</phrase><phrase role="special">()</phrase> <phrase role="special">);</phrase> 11212 <phrase role="comment">// In general, even though we block waiting for future::get() and therefore</phrase> 11213 <phrase role="comment">// won't destroy 'promise' until promise::set_value() has been called, we</phrase> 11214 <phrase role="comment">// are advised that with threads it's possible for ~promise() to be</phrase> 11215 <phrase role="comment">// entered before promise::set_value() has returned. While that shouldn't</phrase> 11216 <phrase role="comment">// happen with fibers::promise, a robust way to deal with the lifespan</phrase> 11217 <phrase role="comment">// issue is to bind 'promise' into our lambda. Since promise is move-only,</phrase> 11218 <phrase role="comment">// use initialization capture.</phrase> 11219<phrase role="preprocessor">#if</phrase> <phrase role="special">!</phrase> <phrase role="identifier">defined</phrase><phrase role="special">(</phrase><phrase role="identifier">BOOST_NO_CXX14_INITIALIZED_LAMBDA_CAPTURES</phrase><phrase role="special">)</phrase> 11220 <phrase role="identifier">api</phrase><phrase role="special">.</phrase><phrase role="identifier">init_write</phrase><phrase role="special">(</phrase> 11221 <phrase role="identifier">data</phrase><phrase role="special">,</phrase> 11222 <phrase role="special">[</phrase><phrase role="identifier">promise</phrase><phrase role="special">=</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">move</phrase><phrase role="special">(</phrase> <phrase role="identifier">promise</phrase><phrase role="special">)](</phrase> <phrase role="identifier">AsyncAPI</phrase><phrase role="special">::</phrase><phrase role="identifier">errorcode</phrase> <phrase role="identifier">ec</phrase><phrase role="special">)</phrase> <phrase role="keyword">mutable</phrase> <phrase role="special">{</phrase> 11223 <phrase role="identifier">promise</phrase><phrase role="special">.</phrase><phrase role="identifier">set_value</phrase><phrase role="special">(</phrase> <phrase role="identifier">ec</phrase><phrase role="special">);</phrase> 11224 <phrase role="special">});</phrase> 11225 11226<phrase role="preprocessor">#else</phrase> <phrase role="comment">// defined(BOOST_NO_CXX14_INITIALIZED_LAMBDA_CAPTURES)</phrase> 11227 <phrase role="identifier">api</phrase><phrase role="special">.</phrase><phrase role="identifier">init_write</phrase><phrase role="special">(</phrase> 11228 <phrase role="identifier">data</phrase><phrase role="special">,</phrase> 11229 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">bind</phrase><phrase role="special">([](</phrase><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">promise</phrase><phrase role="special"><</phrase> <phrase role="identifier">AsyncAPI</phrase><phrase role="special">::</phrase><phrase role="identifier">errorcode</phrase> <phrase role="special">></phrase> <phrase role="special">&</phrase> <phrase role="identifier">promise</phrase><phrase role="special">,</phrase> 11230 <phrase role="identifier">AsyncAPI</phrase><phrase role="special">::</phrase><phrase role="identifier">errorcode</phrase> <phrase role="identifier">ec</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase> 11231 <phrase role="identifier">promise</phrase><phrase role="special">.</phrase><phrase role="identifier">set_value</phrase><phrase role="special">(</phrase> <phrase role="identifier">ec</phrase><phrase role="special">);</phrase> 11232 <phrase role="special">},</phrase> 11233 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">move</phrase><phrase role="special">(</phrase> <phrase role="identifier">promise</phrase><phrase role="special">),</phrase> 11234 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">placeholders</phrase><phrase role="special">::</phrase><phrase role="identifier">_1</phrase><phrase role="special">)</phrase> <phrase role="special">);</phrase> 11235<phrase role="preprocessor">#endif</phrase> <phrase role="comment">// BOOST_NO_CXX14_INITIALIZED_LAMBDA_CAPTURES</phrase> 11236 11237 <phrase role="keyword">return</phrase> <phrase role="identifier">future</phrase><phrase role="special">.</phrase><phrase role="identifier">get</phrase><phrase role="special">();</phrase> 11238<phrase role="special">}</phrase> 11239</programlisting> 11240 </para> 11241 <para> 11242 All we have to do is: 11243 </para> 11244 <orderedlist> 11245 <listitem> 11246 <simpara> 11247 Instantiate a <code><phrase role="identifier">promise</phrase><phrase 11248 role="special"><></phrase></code> of correct type. 11249 </simpara> 11250 </listitem> 11251 <listitem> 11252 <simpara> 11253 Obtain its <code><phrase role="identifier">future</phrase><phrase role="special"><></phrase></code>. 11254 </simpara> 11255 </listitem> 11256 <listitem> 11257 <simpara> 11258 Arrange for the callback to call <link linkend="promise_set_value"><code>promise::set_value()</code></link>. 11259 </simpara> 11260 </listitem> 11261 <listitem> 11262 <simpara> 11263 Block on <link linkend="future_get"><code>future::get()</code></link>. 11264 </simpara> 11265 </listitem> 11266 </orderedlist> 11267 <note> 11268 <para> 11269 This tactic for resuming a pending fiber works even if the callback is 11270 called on a different thread than the one on which the initiating fiber 11271 is running. In fact, <ulink url="../../examples/adapt_callbacks.cpp">the 11272 example program’s</ulink> dummy <code><phrase role="identifier">AsyncAPI</phrase></code> 11273 implementation illustrates that: it simulates async I/O by launching a 11274 new thread that sleeps briefly and then calls the relevant callback. 11275 </para> 11276 </note> 11277 </section> 11278 <section id="fiber.callbacks.success_or_exception"> 11279 <title><link linkend="fiber.callbacks.success_or_exception">Success or Exception</link></title> 11280 <para> 11281 A wrapper more aligned with modern C++ practice would use an exception, rather 11282 than an <code><phrase role="identifier">errorcode</phrase></code>, to communicate 11283 failure to its caller. This is straightforward to code in terms of <code><phrase 11284 role="identifier">write_ec</phrase><phrase role="special">()</phrase></code>: 11285 </para> 11286 <para> 11287<programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">write</phrase><phrase role="special">(</phrase> <phrase role="identifier">AsyncAPI</phrase> <phrase role="special">&</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">&</phrase> <phrase role="identifier">data</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase> 11288 <phrase role="identifier">AsyncAPI</phrase><phrase role="special">::</phrase><phrase role="identifier">errorcode</phrase> <phrase role="identifier">ec</phrase> <phrase role="special">=</phrase> <phrase role="identifier">write_ec</phrase><phrase role="special">(</phrase> <phrase role="identifier">api</phrase><phrase role="special">,</phrase> <phrase role="identifier">data</phrase><phrase role="special">);</phrase> 11289 <phrase role="keyword">if</phrase> <phrase role="special">(</phrase> <phrase role="identifier">ec</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase> 11290 <phrase role="keyword">throw</phrase> <phrase role="identifier">make_exception</phrase><phrase role="special">(</phrase><phrase role="string">"write"</phrase><phrase role="special">,</phrase> <phrase role="identifier">ec</phrase><phrase role="special">);</phrase> 11291 <phrase role="special">}</phrase> 11292<phrase role="special">}</phrase> 11293</programlisting> 11294 </para> 11295 <para> 11296 The point is that since each fiber has its own stack, you need not repeat 11297 messy boilerplate: normal encapsulation works. 11298 </para> 11299 </section> 11300 <section id="fiber.callbacks.return_errorcode_or_data"> 11301 <title><link linkend="fiber.callbacks.return_errorcode_or_data">Return Errorcode 11302 or Data</link></title> 11303 <para> 11304 Things get a bit more interesting when the async operation’s callback passes 11305 multiple data items of interest. One approach would be to use <code><phrase 11306 role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">pair</phrase><phrase 11307 role="special"><></phrase></code> to capture both: 11308 </para> 11309 <para> 11310<programlisting><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">pair</phrase><phrase role="special"><</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">></phrase> <phrase role="identifier">read_ec</phrase><phrase role="special">(</phrase> <phrase role="identifier">AsyncAPI</phrase> <phrase role="special">&</phrase> <phrase role="identifier">api</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase> 11311 <phrase role="keyword">typedef</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">pair</phrase><phrase role="special"><</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">></phrase> <phrase role="identifier">result_pair</phrase><phrase role="special">;</phrase> 11312 <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">promise</phrase><phrase role="special"><</phrase> <phrase role="identifier">result_pair</phrase> <phrase role="special">></phrase> <phrase role="identifier">promise</phrase><phrase role="special">;</phrase> 11313 <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">future</phrase><phrase role="special"><</phrase> <phrase role="identifier">result_pair</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">get_future</phrase><phrase role="special">()</phrase> <phrase role="special">);</phrase> 11314 <phrase role="comment">// We promise that both 'promise' and 'future' will survive until our</phrase> 11315 <phrase role="comment">// lambda has been called.</phrase> 11316<phrase role="preprocessor">#if</phrase> <phrase role="special">!</phrase> <phrase role="identifier">defined</phrase><phrase role="special">(</phrase><phrase role="identifier">BOOST_NO_CXX14_INITIALIZED_LAMBDA_CAPTURES</phrase><phrase role="special">)</phrase> 11317 <phrase role="identifier">api</phrase><phrase role="special">.</phrase><phrase role="identifier">init_read</phrase><phrase role="special">([</phrase><phrase role="identifier">promise</phrase><phrase role="special">=</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">move</phrase><phrase role="special">(</phrase> <phrase role="identifier">promise</phrase><phrase role="special">)](</phrase> <phrase role="identifier">AsyncAPI</phrase><phrase role="special">::</phrase><phrase role="identifier">errorcode</phrase> <phrase role="identifier">ec</phrase><phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">data</phrase><phrase role="special">)</phrase> <phrase role="keyword">mutable</phrase> <phrase role="special">{</phrase> 11318 <phrase role="identifier">promise</phrase><phrase role="special">.</phrase><phrase role="identifier">set_value</phrase><phrase role="special">(</phrase> <phrase role="identifier">result_pair</phrase><phrase role="special">(</phrase> <phrase role="identifier">ec</phrase><phrase role="special">,</phrase> <phrase role="identifier">data</phrase><phrase role="special">)</phrase> <phrase role="special">);</phrase> 11319 <phrase role="special">});</phrase> 11320<phrase role="preprocessor">#else</phrase> <phrase role="comment">// defined(BOOST_NO_CXX14_INITIALIZED_LAMBDA_CAPTURES)</phrase> 11321 <phrase role="identifier">api</phrase><phrase role="special">.</phrase><phrase role="identifier">init_read</phrase><phrase role="special">(</phrase> 11322 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">bind</phrase><phrase role="special">([](</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">promise</phrase><phrase role="special"><</phrase> <phrase role="identifier">result_pair</phrase> <phrase role="special">></phrase> <phrase role="special">&</phrase> <phrase role="identifier">promise</phrase><phrase role="special">,</phrase> 11323 <phrase role="identifier">AsyncAPI</phrase><phrase role="special">::</phrase><phrase role="identifier">errorcode</phrase> <phrase role="identifier">ec</phrase><phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">data</phrase><phrase role="special">)</phrase> <phrase role="keyword">mutable</phrase> <phrase role="special">{</phrase> 11324 <phrase role="identifier">promise</phrase><phrase role="special">.</phrase><phrase role="identifier">set_value</phrase><phrase role="special">(</phrase> <phrase role="identifier">result_pair</phrase><phrase role="special">(</phrase> <phrase role="identifier">ec</phrase><phrase role="special">,</phrase> <phrase role="identifier">data</phrase><phrase role="special">)</phrase> <phrase role="special">);</phrase> 11325 <phrase role="special">},</phrase> 11326 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">move</phrase><phrase role="special">(</phrase> <phrase role="identifier">promise</phrase><phrase role="special">),</phrase> 11327 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">placeholders</phrase><phrase role="special">::</phrase><phrase role="identifier">_1</phrase><phrase role="special">,</phrase> 11328 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">placeholders</phrase><phrase role="special">::</phrase><phrase role="identifier">_2</phrase><phrase role="special">)</phrase> <phrase role="special">);</phrase> 11329<phrase role="preprocessor">#endif</phrase> <phrase role="comment">// BOOST_NO_CXX14_INITIALIZED_LAMBDA_CAPTURES</phrase> 11330 <phrase role="keyword">return</phrase> <phrase role="identifier">future</phrase><phrase role="special">.</phrase><phrase role="identifier">get</phrase><phrase role="special">();</phrase> 11331<phrase role="special">}</phrase> 11332</programlisting> 11333 </para> 11334 <para> 11335 Once you bundle the interesting data in <code><phrase role="identifier">std</phrase><phrase 11336 role="special">::</phrase><phrase role="identifier">pair</phrase><phrase 11337 role="special"><></phrase></code>, the code is effectively identical 11338 to <code><phrase role="identifier">write_ec</phrase><phrase role="special">()</phrase></code>. 11339 You can call it like this: 11340 </para> 11341 <para> 11342<programlisting><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">tie</phrase><phrase role="special">(</phrase> <phrase role="identifier">ec</phrase><phrase role="special">,</phrase> <phrase role="identifier">data</phrase><phrase role="special">)</phrase> <phrase role="special">=</phrase> <phrase role="identifier">read_ec</phrase><phrase role="special">(</phrase> <phrase role="identifier">api</phrase><phrase role="special">);</phrase> 11343</programlisting> 11344 </para> 11345 </section> 11346 <section id="fiber.callbacks.data_or_exception"> 11347 <title><anchor id="Data_or_Exception"/><link linkend="fiber.callbacks.data_or_exception">Data 11348 or Exception</link></title> 11349 <para> 11350 But a more natural API for a function that obtains data is to return only 11351 the data on success, throwing an exception on error. 11352 </para> 11353 <para> 11354 As with <code><phrase role="identifier">write</phrase><phrase role="special">()</phrase></code> 11355 above, it’s certainly possible to code a <code><phrase role="identifier">read</phrase><phrase 11356 role="special">()</phrase></code> wrapper in terms of <code><phrase role="identifier">read_ec</phrase><phrase 11357 role="special">()</phrase></code>. But since a given application is unlikely 11358 to need both, let’s code <code><phrase role="identifier">read</phrase><phrase 11359 role="special">()</phrase></code> from scratch, leveraging <link linkend="promise_set_exception"><code>promise::set_exception()</code></link>: 11360 </para> 11361 <para> 11362<programlisting><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="identifier">read</phrase><phrase role="special">(</phrase> <phrase role="identifier">AsyncAPI</phrase> <phrase role="special">&</phrase> <phrase role="identifier">api</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase> 11363 <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">promise</phrase><phrase role="special"><</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="special">></phrase> <phrase role="identifier">promise</phrase><phrase role="special">;</phrase> 11364 <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">future</phrase><phrase role="special"><</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</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">get_future</phrase><phrase role="special">()</phrase> <phrase role="special">);</phrase> 11365 <phrase role="comment">// Both 'promise' and 'future' will survive until our lambda has been</phrase> 11366 <phrase role="comment">// called.</phrase> 11367<phrase role="preprocessor">#if</phrase> <phrase role="special">!</phrase> <phrase role="identifier">defined</phrase><phrase role="special">(</phrase><phrase role="identifier">BOOST_NO_CXX14_INITIALIZED_LAMBDA_CAPTURES</phrase><phrase role="special">)</phrase> 11368 <phrase role="identifier">api</phrase><phrase role="special">.</phrase><phrase role="identifier">init_read</phrase><phrase role="special">([&</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">&</phrase> <phrase role="identifier">data</phrase><phrase role="special">)</phrase> <phrase role="keyword">mutable</phrase> <phrase role="special">{</phrase> 11369 <phrase role="keyword">if</phrase> <phrase role="special">(</phrase> <phrase role="special">!</phrase> <phrase role="identifier">ec</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase> 11370 <phrase role="identifier">promise</phrase><phrase role="special">.</phrase><phrase role="identifier">set_value</phrase><phrase role="special">(</phrase> <phrase role="identifier">data</phrase><phrase role="special">);</phrase> 11371 <phrase role="special">}</phrase> <phrase role="keyword">else</phrase> <phrase role="special">{</phrase> 11372 <phrase role="identifier">promise</phrase><phrase role="special">.</phrase><phrase role="identifier">set_exception</phrase><phrase role="special">(</phrase> 11373 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">make_exception_ptr</phrase><phrase role="special">(</phrase> 11374 <phrase role="identifier">make_exception</phrase><phrase role="special">(</phrase><phrase role="string">"read"</phrase><phrase role="special">,</phrase> <phrase role="identifier">ec</phrase><phrase role="special">)</phrase> <phrase role="special">)</phrase> <phrase role="special">);</phrase> 11375 <phrase role="special">}</phrase> 11376 <phrase role="special">});</phrase> 11377<phrase role="preprocessor">#else</phrase> <phrase role="comment">// defined(BOOST_NO_CXX14_INITIALIZED_LAMBDA_CAPTURES)</phrase> 11378 <phrase role="identifier">api</phrase><phrase role="special">.</phrase><phrase role="identifier">init_read</phrase><phrase role="special">(</phrase> 11379 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">bind</phrase><phrase role="special">([](</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">promise</phrase><phrase role="special"><</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="special">></phrase> <phrase role="special">&</phrase> <phrase role="identifier">promise</phrase><phrase role="special">,</phrase> 11380 <phrase role="identifier">AsyncAPI</phrase><phrase role="special">::</phrase><phrase role="identifier">errorcode</phrase> <phrase role="identifier">ec</phrase><phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">data</phrase><phrase role="special">)</phrase> <phrase role="keyword">mutable</phrase> <phrase role="special">{</phrase> 11381 <phrase role="keyword">if</phrase> <phrase role="special">(</phrase> <phrase role="special">!</phrase> <phrase role="identifier">ec</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase> 11382 <phrase role="identifier">promise</phrase><phrase role="special">.</phrase><phrase role="identifier">set_value</phrase><phrase role="special">(</phrase> <phrase role="identifier">data</phrase><phrase role="special">);</phrase> 11383 <phrase role="special">}</phrase> <phrase role="keyword">else</phrase> <phrase role="special">{</phrase> 11384 <phrase role="identifier">promise</phrase><phrase role="special">.</phrase><phrase role="identifier">set_exception</phrase><phrase role="special">(</phrase> 11385 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">make_exception_ptr</phrase><phrase role="special">(</phrase> 11386 <phrase role="identifier">make_exception</phrase><phrase role="special">(</phrase><phrase role="string">"read"</phrase><phrase role="special">,</phrase> <phrase role="identifier">ec</phrase><phrase role="special">)</phrase> <phrase role="special">)</phrase> <phrase role="special">);</phrase> 11387 <phrase role="special">}</phrase> 11388 <phrase role="special">},</phrase> 11389 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">move</phrase><phrase role="special">(</phrase> <phrase role="identifier">promise</phrase><phrase role="special">),</phrase> 11390 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">placeholders</phrase><phrase role="special">::</phrase><phrase role="identifier">_1</phrase><phrase role="special">,</phrase> 11391 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">placeholders</phrase><phrase role="special">::</phrase><phrase role="identifier">_2</phrase><phrase role="special">)</phrase> <phrase role="special">);</phrase> 11392<phrase role="preprocessor">#endif</phrase> <phrase role="comment">// BOOST_NO_CXX14_INITIALIZED_LAMBDA_CAPTURES</phrase> 11393 <phrase role="keyword">return</phrase> <phrase role="identifier">future</phrase><phrase role="special">.</phrase><phrase role="identifier">get</phrase><phrase role="special">();</phrase> 11394<phrase role="special">}</phrase> 11395</programlisting> 11396 </para> 11397 <para> 11398 <link linkend="future_get"><code>future::get()</code></link> will do the right thing, either returning <code><phrase 11399 role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase></code> 11400 or throwing an exception. 11401 </para> 11402 </section> 11403 <section id="fiber.callbacks.success_error_virtual_methods"> 11404 <title><link linkend="fiber.callbacks.success_error_virtual_methods">Success/Error 11405 Virtual Methods</link></title> 11406 <para> 11407 One classic approach to completion notification is to define an abstract 11408 base class with <code><phrase role="identifier">success</phrase><phrase role="special">()</phrase></code> 11409 and <code><phrase role="identifier">error</phrase><phrase role="special">()</phrase></code> 11410 methods. Code wishing to perform async I/O must derive a subclass, override 11411 each of these methods and pass the async operation a pointer to a subclass 11412 instance. The abstract base class might look like this: 11413 </para> 11414 <para> 11415<programlisting><phrase role="comment">// every async operation receives a subclass instance of this abstract base</phrase> 11416<phrase role="comment">// class through which to communicate its result</phrase> 11417<phrase role="keyword">struct</phrase> <phrase role="identifier">Response</phrase> <phrase role="special">{</phrase> 11418 <phrase role="keyword">typedef</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">shared_ptr</phrase><phrase role="special"><</phrase> <phrase role="identifier">Response</phrase> <phrase role="special">></phrase> <phrase role="identifier">ptr</phrase><phrase role="special">;</phrase> 11419 11420 <phrase role="comment">// called if the operation succeeds</phrase> 11421 <phrase role="keyword">virtual</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">success</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">data</phrase><phrase role="special">)</phrase> <phrase role="special">=</phrase> <phrase role="number">0</phrase><phrase role="special">;</phrase> 11422 11423 <phrase role="comment">// called if the operation fails</phrase> 11424 <phrase role="keyword">virtual</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">error</phrase><phrase role="special">(</phrase> <phrase role="identifier">AsyncAPIBase</phrase><phrase role="special">::</phrase><phrase role="identifier">errorcode</phrase> <phrase role="identifier">ec</phrase><phrase role="special">)</phrase> <phrase role="special">=</phrase> <phrase role="number">0</phrase><phrase role="special">;</phrase> 11425<phrase role="special">};</phrase> 11426</programlisting> 11427 </para> 11428 <para> 11429 Now the <code><phrase role="identifier">AsyncAPI</phrase></code> operation 11430 might look more like this: 11431 </para> 11432 <para> 11433<programlisting><phrase role="comment">// derive Response subclass, instantiate, pass Response::ptr</phrase> 11434<phrase role="keyword">void</phrase> <phrase role="identifier">init_read</phrase><phrase role="special">(</phrase> <phrase role="identifier">Response</phrase><phrase role="special">::</phrase><phrase role="identifier">ptr</phrase><phrase role="special">);</phrase> 11435</programlisting> 11436 </para> 11437 <para> 11438 We can address this by writing a one-size-fits-all <code><phrase role="identifier">PromiseResponse</phrase></code>: 11439 </para> 11440 <para> 11441<programlisting><phrase role="keyword">class</phrase> <phrase role="identifier">PromiseResponse</phrase><phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <phrase role="identifier">Response</phrase> <phrase role="special">{</phrase> 11442<phrase role="keyword">public</phrase><phrase role="special">:</phrase> 11443 <phrase role="comment">// called if the operation succeeds</phrase> 11444 <phrase role="keyword">virtual</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">success</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">data</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase> 11445 <phrase role="identifier">promise_</phrase><phrase role="special">.</phrase><phrase role="identifier">set_value</phrase><phrase role="special">(</phrase> <phrase role="identifier">data</phrase><phrase role="special">);</phrase> 11446 <phrase role="special">}</phrase> 11447 11448 <phrase role="comment">// called if the operation fails</phrase> 11449 <phrase role="keyword">virtual</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">error</phrase><phrase role="special">(</phrase> <phrase role="identifier">AsyncAPIBase</phrase><phrase role="special">::</phrase><phrase role="identifier">errorcode</phrase> <phrase role="identifier">ec</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase> 11450 <phrase role="identifier">promise_</phrase><phrase role="special">.</phrase><phrase role="identifier">set_exception</phrase><phrase role="special">(</phrase> 11451 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">make_exception_ptr</phrase><phrase role="special">(</phrase> 11452 <phrase role="identifier">make_exception</phrase><phrase role="special">(</phrase><phrase role="string">"read"</phrase><phrase role="special">,</phrase> <phrase role="identifier">ec</phrase><phrase role="special">)</phrase> <phrase role="special">)</phrase> <phrase role="special">);</phrase> 11453 <phrase role="special">}</phrase> 11454 11455 <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">future</phrase><phrase role="special"><</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="special">></phrase> <phrase role="identifier">get_future</phrase><phrase role="special">()</phrase> <phrase role="special">{</phrase> 11456 <phrase role="keyword">return</phrase> <phrase role="identifier">promise_</phrase><phrase role="special">.</phrase><phrase role="identifier">get_future</phrase><phrase role="special">();</phrase> 11457 <phrase role="special">}</phrase> 11458 11459<phrase role="keyword">private</phrase><phrase role="special">:</phrase> 11460 <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">promise</phrase><phrase role="special"><</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="special">></phrase> <phrase role="identifier">promise_</phrase><phrase role="special">;</phrase> 11461<phrase role="special">};</phrase> 11462</programlisting> 11463 </para> 11464 <para> 11465 Now we can simply obtain the <code><phrase role="identifier">future</phrase><phrase 11466 role="special"><></phrase></code> from that <code><phrase role="identifier">PromiseResponse</phrase></code> 11467 and wait on its <code><phrase role="identifier">get</phrase><phrase role="special">()</phrase></code>: 11468 </para> 11469 <para> 11470<programlisting><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="identifier">read</phrase><phrase role="special">(</phrase> <phrase role="identifier">AsyncAPI</phrase> <phrase role="special">&</phrase> <phrase role="identifier">api</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase> 11471 <phrase role="comment">// Because init_read() requires a shared_ptr, we must allocate our</phrase> 11472 <phrase role="comment">// ResponsePromise on the heap, even though we know its lifespan.</phrase> 11473 <phrase role="keyword">auto</phrase> <phrase role="identifier">promisep</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">make_shared</phrase><phrase role="special"><</phrase> <phrase role="identifier">PromiseResponse</phrase> <phrase role="special">>()</phrase> <phrase role="special">);</phrase> 11474 <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">future</phrase><phrase role="special"><</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="special">></phrase> <phrase role="identifier">future</phrase><phrase role="special">(</phrase> <phrase role="identifier">promisep</phrase><phrase role="special">-></phrase><phrase role="identifier">get_future</phrase><phrase role="special">()</phrase> <phrase role="special">);</phrase> 11475 <phrase role="comment">// Both 'promisep' and 'future' will survive until our lambda has been</phrase> 11476 <phrase role="comment">// called.</phrase> 11477 <phrase role="identifier">api</phrase><phrase role="special">.</phrase><phrase role="identifier">init_read</phrase><phrase role="special">(</phrase> <phrase role="identifier">promisep</phrase><phrase role="special">);</phrase> 11478 <phrase role="keyword">return</phrase> <phrase role="identifier">future</phrase><phrase role="special">.</phrase><phrase role="identifier">get</phrase><phrase role="special">();</phrase> 11479<phrase role="special">}</phrase> 11480</programlisting> 11481 </para> 11482 <para> 11483 The source code above is found in <ulink url="../../examples/adapt_callbacks.cpp">adapt_callbacks.cpp</ulink> 11484 and <ulink url="../../examples/adapt_method_calls.cpp">adapt_method_calls.cpp</ulink>. 11485 </para> 11486 </section> 11487 <section id="fiber.callbacks.then_there_s____boost_asio__"> 11488 <title><anchor id="callbacks_asio"/><link linkend="fiber.callbacks.then_there_s____boost_asio__">Then 11489 There’s <ulink url="http://www.boost.org/doc/libs/release/libs/asio/index.html">Boost.Asio</ulink></link></title> 11490 <para> 11491 Since the simplest form of Boost.Asio asynchronous operation completion token 11492 is a callback function, we could apply the same tactics for Asio as for our 11493 hypothetical <code><phrase role="identifier">AsyncAPI</phrase></code> asynchronous 11494 operations. 11495 </para> 11496 <para> 11497 Fortunately we need not. Boost.Asio incorporates a mechanism<footnote id="fiber.callbacks.then_there_s____boost_asio__.f0"> 11498 <para> 11499 This mechanism has been proposed as a conventional way to allow the caller 11500 of an arbitrary async function to specify completion handling: <ulink url="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4045.pdf">N4045</ulink>. 11501 </para> 11502 </footnote> by which the caller can customize the notification behavior of 11503 any async operation. Therefore we can construct a <emphasis>completion token</emphasis> 11504 which, when passed to a <ulink url="http://www.boost.org/doc/libs/release/libs/asio/index.html">Boost.Asio</ulink> 11505 async operation, requests blocking for the calling fiber. 11506 </para> 11507 <para> 11508 A typical Asio async function might look something like this:<footnote id="fiber.callbacks.then_there_s____boost_asio__.f1"> 11509 <para> 11510 per <ulink url="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4045.pdf">N4045</ulink> 11511 </para> 11512 </footnote> 11513 </para> 11514<programlisting><phrase role="keyword">template</phrase> <phrase role="special"><</phrase> <phrase role="special">...,</phrase> <phrase role="keyword">class</phrase> <phrase role="identifier">CompletionToken</phrase> <phrase role="special">></phrase> 11515<emphasis>deduced_return_type</emphasis> 11516<phrase role="identifier">async_something</phrase><phrase role="special">(</phrase> <phrase role="special">...</phrase> <phrase role="special">,</phrase> <phrase role="identifier">CompletionToken</phrase><phrase role="special">&&</phrase> <phrase role="identifier">token</phrase><phrase role="special">)</phrase> 11517<phrase role="special">{</phrase> 11518 <phrase role="comment">// construct handler_type instance from CompletionToken</phrase> 11519 <phrase role="identifier">handler_type</phrase><phrase role="special"><</phrase><phrase role="identifier">CompletionToken</phrase><phrase role="special">,</phrase> <phrase role="special">...>::</phrase><phrase role="identifier">type</phrase> <emphasis role="bold"><!--quickbook-escape-prefix--><code><!--quickbook-escape-postfix-->handler(token)<!--quickbook-escape-prefix--></code><!--quickbook-escape-postfix--></emphasis><phrase role="special">;</phrase> 11520 <phrase role="comment">// construct async_result instance from handler_type</phrase> 11521 <phrase role="identifier">async_result</phrase><phrase role="special"><</phrase><phrase role="keyword">decltype</phrase><phrase role="special">(</phrase><phrase role="identifier">handler</phrase><phrase role="special">)></phrase> <emphasis role="bold"><!--quickbook-escape-prefix--><code><!--quickbook-escape-postfix-->result(handler)<!--quickbook-escape-prefix--></code><!--quickbook-escape-postfix--></emphasis><phrase role="special">;</phrase> 11522 11523 <phrase role="comment">// ... arrange to call handler on completion ...</phrase> 11524 <phrase role="comment">// ... initiate actual I/O operation ...</phrase> 11525 11526 <phrase role="keyword">return</phrase> <emphasis role="bold"><!--quickbook-escape-prefix--><code><!--quickbook-escape-postfix-->result.get()<!--quickbook-escape-prefix--></code><!--quickbook-escape-postfix--></emphasis><phrase role="special">;</phrase> 11527<phrase role="special">}</phrase> 11528</programlisting> 11529 <para> 11530 We will engage that mechanism, which is based on specializing Asio’s <code><phrase 11531 role="identifier">handler_type</phrase><phrase role="special"><></phrase></code> 11532 template for the <code><phrase role="identifier">CompletionToken</phrase></code> 11533 type and the signature of the specific callback. The remainder of this discussion 11534 will refer back to <code><phrase role="identifier">async_something</phrase><phrase 11535 role="special">()</phrase></code> as the Asio async function under consideration. 11536 </para> 11537 <para> 11538 The implementation described below uses lower-level facilities than <code><phrase 11539 role="identifier">promise</phrase></code> and <code><phrase role="identifier">future</phrase></code> 11540 because the <code><phrase role="identifier">promise</phrase></code> mechanism 11541 interacts badly with <ulink url="http://www.boost.org/doc/libs/release/doc/html/boost_asio/reference/io_service/stop.html"><code><phrase 11542 role="identifier">io_service</phrase><phrase role="special">::</phrase><phrase 11543 role="identifier">stop</phrase><phrase role="special">()</phrase></code></ulink>. 11544 It produces <code><phrase role="identifier">broken_promise</phrase></code> 11545 exceptions. 11546 </para> 11547 <para> 11548 <code><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase 11549 role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase 11550 role="identifier">asio</phrase><phrase role="special">::</phrase><phrase 11551 role="identifier">yield</phrase></code> is a completion token of this kind. 11552 <code><phrase role="identifier">yield</phrase></code> is an instance of 11553 <code><phrase role="identifier">yield_t</phrase></code>: 11554 </para> 11555 <para> 11556<programlisting><phrase role="keyword">class</phrase> <phrase role="identifier">yield_t</phrase> <phrase role="special">{</phrase> 11557<phrase role="keyword">public</phrase><phrase role="special">:</phrase> 11558 <phrase role="identifier">yield_t</phrase><phrase role="special">()</phrase> <phrase role="special">=</phrase> <phrase role="keyword">default</phrase><phrase role="special">;</phrase> 11559 11560 <phrase role="comment">/** 11561 * @code 11562 * static yield_t yield; 11563 * boost::system::error_code myec; 11564 * func(yield[myec]); 11565 * @endcode 11566 * @c yield[myec] returns an instance of @c yield_t whose @c ec_ points 11567 * to @c myec. The expression @c yield[myec] "binds" @c myec to that 11568 * (anonymous) @c yield_t instance, instructing @c func() to store any 11569 * @c error_code it might produce into @c myec rather than throwing @c 11570 * boost::system::system_error. 11571 */</phrase> 11572 <phrase role="identifier">yield_t</phrase> <phrase role="keyword">operator</phrase><phrase role="special">[](</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">system</phrase><phrase role="special">::</phrase><phrase role="identifier">error_code</phrase> <phrase role="special">&</phrase> <phrase role="identifier">ec</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase> <phrase role="special">{</phrase> 11573 <phrase role="identifier">yield_t</phrase> <phrase role="identifier">tmp</phrase><phrase role="special">;</phrase> 11574 <phrase role="identifier">tmp</phrase><phrase role="special">.</phrase><phrase role="identifier">ec_</phrase> <phrase role="special">=</phrase> <phrase role="special">&</phrase> <phrase role="identifier">ec</phrase><phrase role="special">;</phrase> 11575 <phrase role="keyword">return</phrase> <phrase role="identifier">tmp</phrase><phrase role="special">;</phrase> 11576 <phrase role="special">}</phrase> 11577 11578<phrase role="comment">//private:</phrase> 11579 <phrase role="comment">// ptr to bound error_code instance if any</phrase> 11580 <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">system</phrase><phrase role="special">::</phrase><phrase role="identifier">error_code</phrase> <phrase role="special">*</phrase> <phrase role="identifier">ec_</phrase><phrase role="special">{</phrase> <phrase role="keyword">nullptr</phrase> <phrase role="special">};</phrase> 11581<phrase role="special">};</phrase> 11582</programlisting> 11583 </para> 11584 <para> 11585 <code><phrase role="identifier">yield_t</phrase></code> is in fact only a 11586 placeholder, a way to trigger Boost.Asio customization. It can bind a <ulink 11587 url="http://www.boost.org/doc/libs/release/libs/system/doc/reference.html#Class-error_code"><code><phrase 11588 role="identifier">boost</phrase><phrase role="special">::</phrase><phrase 11589 role="identifier">system</phrase><phrase role="special">::</phrase><phrase 11590 role="identifier">error_code</phrase></code></ulink> for use by the actual 11591 handler. 11592 </para> 11593 <para> 11594 <code><phrase role="identifier">yield</phrase></code> is declared as: 11595 </para> 11596 <para> 11597<programlisting><phrase role="comment">// canonical instance</phrase> 11598<phrase role="keyword">thread_local</phrase> <phrase role="identifier">yield_t</phrase> <phrase role="identifier">yield</phrase><phrase role="special">{};</phrase> 11599</programlisting> 11600 </para> 11601 <para> 11602 Asio customization is engaged by specializing <ulink url="http://www.boost.org/doc/libs/release/doc/html/boost_asio/reference/handler_type.html"><code><phrase 11603 role="identifier">boost</phrase><phrase role="special">::</phrase><phrase 11604 role="identifier">asio</phrase><phrase role="special">::</phrase><phrase 11605 role="identifier">handler_type</phrase><phrase role="special"><></phrase></code></ulink> 11606 for <code><phrase role="identifier">yield_t</phrase></code>: 11607 </para> 11608 <para> 11609<programlisting><phrase role="comment">// Handler type specialisation for fibers::asio::yield.</phrase> 11610<phrase role="comment">// When 'yield' is passed as a completion handler which accepts only</phrase> 11611<phrase role="comment">// error_code, use yield_handler<void>. yield_handler will take care of the</phrase> 11612<phrase role="comment">// error_code one way or another.</phrase> 11613<phrase role="keyword">template</phrase><phrase role="special"><</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">ReturnType</phrase> <phrase role="special">></phrase> 11614<phrase role="keyword">struct</phrase> <phrase role="identifier">handler_type</phrase><phrase role="special"><</phrase> <phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">asio</phrase><phrase role="special">::</phrase><phrase role="identifier">yield_t</phrase><phrase role="special">,</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">></phrase> 11615<phrase role="special">{</phrase> <phrase role="keyword">typedef</phrase> <phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">asio</phrase><phrase role="special">::</phrase><phrase role="identifier">detail</phrase><phrase role="special">::</phrase><phrase role="identifier">yield_handler</phrase><phrase role="special"><</phrase> <phrase role="keyword">void</phrase> <phrase role="special">></phrase> <phrase role="identifier">type</phrase><phrase role="special">;</phrase> <phrase role="special">};</phrase> 11616</programlisting> 11617 </para> 11618 <para> 11619 (There are actually four different specializations in <ulink url="../../examples/asio/detail/yield.hpp">detail/yield.hpp</ulink>, 11620 one for each of the four Asio async callback signatures we expect.) 11621 </para> 11622 <para> 11623 The above directs Asio to use <code><phrase role="identifier">yield_handler</phrase></code> 11624 as the actual handler for an async operation to which <code><phrase role="identifier">yield</phrase></code> 11625 is passed. There’s a generic <code><phrase role="identifier">yield_handler</phrase><phrase 11626 role="special"><</phrase><phrase role="identifier">T</phrase><phrase role="special">></phrase></code> 11627 implementation and a <code><phrase role="identifier">yield_handler</phrase><phrase 11628 role="special"><</phrase><phrase role="keyword">void</phrase><phrase role="special">></phrase></code> 11629 specialization. Let’s start with the <code><phrase role="special"><</phrase><phrase 11630 role="keyword">void</phrase><phrase role="special">></phrase></code> specialization: 11631 </para> 11632 <para> 11633<programlisting><phrase role="comment">// yield_handler<void> is like yield_handler<T> without value_. In fact it's</phrase> 11634<phrase role="comment">// just like yield_handler_base.</phrase> 11635<phrase role="keyword">template</phrase><phrase role="special"><></phrase> 11636<phrase role="keyword">class</phrase> <phrase role="identifier">yield_handler</phrase><phrase role="special"><</phrase> <phrase role="keyword">void</phrase> <phrase role="special">>:</phrase> <phrase role="keyword">public</phrase> <phrase role="identifier">yield_handler_base</phrase> <phrase role="special">{</phrase> 11637<phrase role="keyword">public</phrase><phrase role="special">:</phrase> 11638 <phrase role="keyword">explicit</phrase> <phrase role="identifier">yield_handler</phrase><phrase role="special">(</phrase> <phrase role="identifier">yield_t</phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">y</phrase><phrase role="special">)</phrase> <phrase role="special">:</phrase> 11639 <phrase role="identifier">yield_handler_base</phrase><phrase role="special">{</phrase> <phrase role="identifier">y</phrase> <phrase role="special">}</phrase> <phrase role="special">{</phrase> 11640 <phrase role="special">}</phrase> 11641 11642 <phrase role="comment">// nullary completion callback</phrase> 11643 <phrase role="keyword">void</phrase> <phrase role="keyword">operator</phrase><phrase role="special">()()</phrase> <phrase role="special">{</phrase> 11644 <phrase role="special">(</phrase> <phrase role="special">*</phrase> <phrase role="keyword">this</phrase><phrase role="special">)(</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">system</phrase><phrase role="special">::</phrase><phrase role="identifier">error_code</phrase><phrase role="special">()</phrase> <phrase role="special">);</phrase> 11645 <phrase role="special">}</phrase> 11646 11647 <phrase role="comment">// inherit operator()(error_code) overload from base class</phrase> 11648 <phrase role="keyword">using</phrase> <phrase role="identifier">yield_handler_base</phrase><phrase role="special">::</phrase><phrase role="keyword">operator</phrase><phrase role="special">();</phrase> 11649<phrase role="special">};</phrase> 11650</programlisting> 11651 </para> 11652 <para> 11653 <code><phrase role="identifier">async_something</phrase><phrase role="special">()</phrase></code>, 11654 having consulted the <code><phrase role="identifier">handler_type</phrase><phrase 11655 role="special"><></phrase></code> traits specialization, instantiates 11656 a <code><phrase role="identifier">yield_handler</phrase><phrase role="special"><</phrase><phrase 11657 role="keyword">void</phrase><phrase role="special">></phrase></code> to 11658 be passed as the actual callback for the async operation. <code><phrase role="identifier">yield_handler</phrase></code>’s 11659 constructor accepts the <code><phrase role="identifier">yield_t</phrase></code> 11660 instance (the <code><phrase role="identifier">yield</phrase></code> object 11661 passed to the async function) and passes it along to <code><phrase role="identifier">yield_handler_base</phrase></code>: 11662 </para> 11663 <para> 11664<programlisting><phrase role="comment">// This class encapsulates common elements between yield_handler<T> (capturing</phrase> 11665<phrase role="comment">// a value to return from asio async function) and yield_handler<void> (no</phrase> 11666<phrase role="comment">// such value). See yield_handler<T> and its <void> specialization below. Both</phrase> 11667<phrase role="comment">// yield_handler<T> and yield_handler<void> are passed by value through</phrase> 11668<phrase role="comment">// various layers of asio functions. In other words, they're potentially</phrase> 11669<phrase role="comment">// copied multiple times. So key data such as the yield_completion instance</phrase> 11670<phrase role="comment">// must be stored in our async_result<yield_handler<>> specialization, which</phrase> 11671<phrase role="comment">// should be instantiated only once.</phrase> 11672<phrase role="keyword">class</phrase> <phrase role="identifier">yield_handler_base</phrase> <phrase role="special">{</phrase> 11673<phrase role="keyword">public</phrase><phrase role="special">:</phrase> 11674 <phrase role="identifier">yield_handler_base</phrase><phrase role="special">(</phrase> <phrase role="identifier">yield_t</phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">y</phrase><phrase role="special">)</phrase> <phrase role="special">:</phrase> 11675 <phrase role="comment">// capture the context* associated with the running fiber</phrase> 11676 <phrase role="identifier">ctx_</phrase><phrase role="special">{</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">context</phrase><phrase role="special">::</phrase><phrase role="identifier">active</phrase><phrase role="special">()</phrase> <phrase role="special">},</phrase> 11677 <phrase role="comment">// capture the passed yield_t</phrase> 11678 <phrase role="identifier">yt_</phrase><phrase role="special">(</phrase> <phrase role="identifier">y</phrase> <phrase role="special">)</phrase> <phrase role="special">{</phrase> 11679 <phrase role="special">}</phrase> 11680 11681 <phrase role="comment">// completion callback passing only (error_code)</phrase> 11682 <phrase role="keyword">void</phrase> <phrase role="keyword">operator</phrase><phrase role="special">()(</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">system</phrase><phrase role="special">::</phrase><phrase role="identifier">error_code</phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">ec</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase> 11683 <phrase role="identifier">BOOST_ASSERT_MSG</phrase><phrase role="special">(</phrase> <phrase role="identifier">ycomp_</phrase><phrase role="special">,</phrase> 11684 <phrase role="string">"Must inject yield_completion* "</phrase> 11685 <phrase role="string">"before calling yield_handler_base::operator()()"</phrase><phrase role="special">);</phrase> 11686 <phrase role="identifier">BOOST_ASSERT_MSG</phrase><phrase role="special">(</phrase> <phrase role="identifier">yt_</phrase><phrase role="special">.</phrase><phrase role="identifier">ec_</phrase><phrase role="special">,</phrase> 11687 <phrase role="string">"Must inject boost::system::error_code* "</phrase> 11688 <phrase role="string">"before calling yield_handler_base::operator()()"</phrase><phrase role="special">);</phrase> 11689 <phrase role="comment">// If originating fiber is busy testing state_ flag, wait until it</phrase> 11690 <phrase role="comment">// has observed (completed != state_).</phrase> 11691 <phrase role="identifier">yield_completion</phrase><phrase role="special">::</phrase><phrase role="identifier">lock_t</phrase> <phrase role="identifier">lk</phrase><phrase role="special">{</phrase> <phrase role="identifier">ycomp_</phrase><phrase role="special">-></phrase><phrase role="identifier">mtx_</phrase> <phrase role="special">};</phrase> 11692 <phrase role="identifier">yield_completion</phrase><phrase role="special">::</phrase><phrase role="identifier">state_t</phrase> <phrase role="identifier">state</phrase> <phrase role="special">=</phrase> <phrase role="identifier">ycomp_</phrase><phrase role="special">-></phrase><phrase role="identifier">state_</phrase><phrase role="special">;</phrase> 11693 <phrase role="comment">// Notify a subsequent yield_completion::wait() call that it need not</phrase> 11694 <phrase role="comment">// suspend.</phrase> 11695 <phrase role="identifier">ycomp_</phrase><phrase role="special">-></phrase><phrase role="identifier">state_</phrase> <phrase role="special">=</phrase> <phrase role="identifier">yield_completion</phrase><phrase role="special">::</phrase><phrase role="identifier">complete</phrase><phrase role="special">;</phrase> 11696 <phrase role="comment">// set the error_code bound by yield_t</phrase> 11697 <phrase role="special">*</phrase> <phrase role="identifier">yt_</phrase><phrase role="special">.</phrase><phrase role="identifier">ec_</phrase> <phrase role="special">=</phrase> <phrase role="identifier">ec</phrase><phrase role="special">;</phrase> 11698 <phrase role="comment">// unlock the lock that protects state_</phrase> 11699 <phrase role="identifier">lk</phrase><phrase role="special">.</phrase><phrase role="identifier">unlock</phrase><phrase role="special">();</phrase> 11700 <phrase role="comment">// If ctx_ is still active, e.g. because the async operation</phrase> 11701 <phrase role="comment">// immediately called its callback (this method!) before the asio</phrase> 11702 <phrase role="comment">// async function called async_result_base::get(), we must not set it</phrase> 11703 <phrase role="comment">// ready.</phrase> 11704 <phrase role="keyword">if</phrase> <phrase role="special">(</phrase> <phrase role="identifier">yield_completion</phrase><phrase role="special">::</phrase><phrase role="identifier">waiting</phrase> <phrase role="special">==</phrase> <phrase role="identifier">state</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase> 11705 <phrase role="comment">// wake the fiber</phrase> 11706 <phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">context</phrase><phrase role="special">::</phrase><phrase role="identifier">active</phrase><phrase role="special">()-></phrase><phrase role="identifier">schedule</phrase><phrase role="special">(</phrase> <phrase role="identifier">ctx_</phrase><phrase role="special">);</phrase> 11707 <phrase role="special">}</phrase> 11708 <phrase role="special">}</phrase> 11709 11710<phrase role="comment">//private:</phrase> 11711 <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">context</phrase> <phrase role="special">*</phrase> <phrase role="identifier">ctx_</phrase><phrase role="special">;</phrase> 11712 <phrase role="identifier">yield_t</phrase> <phrase role="identifier">yt_</phrase><phrase role="special">;</phrase> 11713 <phrase role="comment">// We depend on this pointer to yield_completion, which will be injected</phrase> 11714 <phrase role="comment">// by async_result.</phrase> 11715 <phrase role="identifier">yield_completion</phrase><phrase role="special">::</phrase><phrase role="identifier">ptr_t</phrase> <phrase role="identifier">ycomp_</phrase><phrase role="special">{};</phrase> 11716<phrase role="special">};</phrase> 11717</programlisting> 11718 </para> 11719 <para> 11720 <code><phrase role="identifier">yield_handler_base</phrase></code> stores 11721 a copy of the <code><phrase role="identifier">yield_t</phrase></code> instance 11722 — which, as shown above, contains only an <code><phrase role="identifier">error_code</phrase><phrase 11723 role="special">*</phrase></code>. It also captures the <link linkend="class_context"><code>context</code></link>* 11724 for the currently-running fiber by calling <link linkend="context_active"><code>context::active()</code></link>. 11725 </para> 11726 <para> 11727 You will notice that <code><phrase role="identifier">yield_handler_base</phrase></code> 11728 has one more data member (<code><phrase role="identifier">ycomp_</phrase></code>) 11729 that is initialized to <code><phrase role="keyword">nullptr</phrase></code> 11730 by its constructor — though its <code><phrase role="keyword">operator</phrase><phrase 11731 role="special">()()</phrase></code> method relies on <code><phrase role="identifier">ycomp_</phrase></code> 11732 being non-null. More on this in a moment. 11733 </para> 11734 <para> 11735 Having constructed the <code><phrase role="identifier">yield_handler</phrase><phrase 11736 role="special"><</phrase><phrase role="keyword">void</phrase><phrase role="special">></phrase></code> 11737 instance, <code><phrase role="identifier">async_something</phrase><phrase 11738 role="special">()</phrase></code> goes on to construct an <code><phrase role="identifier">async_result</phrase></code> 11739 specialized for the <code><phrase role="identifier">handler_type</phrase><phrase 11740 role="special"><>::</phrase><phrase role="identifier">type</phrase></code>: 11741 in this case, <code><phrase role="identifier">async_result</phrase><phrase 11742 role="special"><</phrase><phrase role="identifier">yield_handler</phrase><phrase 11743 role="special"><</phrase><phrase role="keyword">void</phrase><phrase role="special">>></phrase></code>. 11744 It passes the <code><phrase role="identifier">yield_handler</phrase><phrase 11745 role="special"><</phrase><phrase role="keyword">void</phrase><phrase role="special">></phrase></code> 11746 instance to the new <code><phrase role="identifier">async_result</phrase></code> 11747 instance. 11748 </para> 11749 <para> 11750<programlisting><phrase role="comment">// Without the need to handle a passed value, our yield_handler<void></phrase> 11751<phrase role="comment">// specialization is just like async_result_base.</phrase> 11752<phrase role="keyword">template</phrase><phrase role="special"><></phrase> 11753<phrase role="keyword">class</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"><</phrase> <phrase role="keyword">void</phrase> <phrase role="special">></phrase> <phrase role="special">></phrase> <phrase role="special">:</phrase> 11754 <phrase role="keyword">public</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">asio</phrase><phrase role="special">::</phrase><phrase role="identifier">detail</phrase><phrase role="special">::</phrase><phrase role="identifier">async_result_base</phrase> <phrase role="special">{</phrase> 11755<phrase role="keyword">public</phrase><phrase role="special">:</phrase> 11756 <phrase role="keyword">typedef</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">type</phrase><phrase role="special">;</phrase> 11757 11758 <phrase role="keyword">explicit</phrase> <phrase role="identifier">async_result</phrase><phrase role="special">(</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">asio</phrase><phrase role="special">::</phrase><phrase role="identifier">detail</phrase><phrase role="special">::</phrase><phrase role="identifier">yield_handler</phrase><phrase role="special"><</phrase> <phrase role="keyword">void</phrase> <phrase role="special">></phrase> <phrase role="special">&</phrase> <phrase role="identifier">h</phrase><phrase role="special">):</phrase> 11759 <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">asio</phrase><phrase role="special">::</phrase><phrase role="identifier">detail</phrase><phrase role="special">::</phrase><phrase role="identifier">async_result_base</phrase><phrase role="special">{</phrase> <phrase role="identifier">h</phrase> <phrase role="special">}</phrase> <phrase role="special">{</phrase> 11760 <phrase role="special">}</phrase> 11761<phrase role="special">};</phrase> 11762</programlisting> 11763 </para> 11764 <para> 11765 Naturally that leads us straight to <code><phrase role="identifier">async_result_base</phrase></code>: 11766 </para> 11767 <para> 11768<programlisting><phrase role="comment">// Factor out commonality between async_result<yield_handler<T>> and</phrase> 11769<phrase role="comment">// async_result<yield_handler<void>></phrase> 11770<phrase role="keyword">class</phrase> <phrase role="identifier">async_result_base</phrase> <phrase role="special">{</phrase> 11771<phrase role="keyword">public</phrase><phrase role="special">:</phrase> 11772 <phrase role="keyword">explicit</phrase> <phrase role="identifier">async_result_base</phrase><phrase role="special">(</phrase> <phrase role="identifier">yield_handler_base</phrase> <phrase role="special">&</phrase> <phrase role="identifier">h</phrase><phrase role="special">)</phrase> <phrase role="special">:</phrase> 11773 <phrase role="identifier">ycomp_</phrase><phrase role="special">{</phrase> <phrase role="keyword">new</phrase> <phrase role="identifier">yield_completion</phrase><phrase role="special">{}</phrase> <phrase role="special">}</phrase> <phrase role="special">{</phrase> 11774 <phrase role="comment">// Inject ptr to our yield_completion instance into this</phrase> 11775 <phrase role="comment">// yield_handler<>.</phrase> 11776 <phrase role="identifier">h</phrase><phrase role="special">.</phrase><phrase role="identifier">ycomp_</phrase> <phrase role="special">=</phrase> <phrase role="keyword">this</phrase><phrase role="special">-></phrase><phrase role="identifier">ycomp_</phrase><phrase role="special">;</phrase> 11777 <phrase role="comment">// if yield_t didn't bind an error_code, make yield_handler_base's</phrase> 11778 <phrase role="comment">// error_code* point to an error_code local to this object so</phrase> 11779 <phrase role="comment">// yield_handler_base::operator() can unconditionally store through</phrase> 11780 <phrase role="comment">// its error_code*</phrase> 11781 <phrase role="keyword">if</phrase> <phrase role="special">(</phrase> <phrase role="special">!</phrase> <phrase role="identifier">h</phrase><phrase role="special">.</phrase><phrase role="identifier">yt_</phrase><phrase role="special">.</phrase><phrase role="identifier">ec_</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase> 11782 <phrase role="identifier">h</phrase><phrase role="special">.</phrase><phrase role="identifier">yt_</phrase><phrase role="special">.</phrase><phrase role="identifier">ec_</phrase> <phrase role="special">=</phrase> <phrase role="special">&</phrase> <phrase role="identifier">ec_</phrase><phrase role="special">;</phrase> 11783 <phrase role="special">}</phrase> 11784 <phrase role="special">}</phrase> 11785 11786 <phrase role="keyword">void</phrase> <phrase role="identifier">get</phrase><phrase role="special">()</phrase> <phrase role="special">{</phrase> 11787 <phrase role="comment">// Unless yield_handler_base::operator() has already been called,</phrase> 11788 <phrase role="comment">// suspend the calling fiber until that call.</phrase> 11789 <phrase role="identifier">ycomp_</phrase><phrase role="special">-></phrase><phrase role="identifier">wait</phrase><phrase role="special">();</phrase> 11790 <phrase role="comment">// The only way our own ec_ member could have a non-default value is</phrase> 11791 <phrase role="comment">// if our yield_handler did not have a bound error_code AND the</phrase> 11792 <phrase role="comment">// completion callback passed a non-default error_code.</phrase> 11793 <phrase role="keyword">if</phrase> <phrase role="special">(</phrase> <phrase role="identifier">ec_</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase> 11794 <phrase role="identifier">throw_exception</phrase><phrase role="special">(</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">system</phrase><phrase role="special">::</phrase><phrase role="identifier">system_error</phrase><phrase role="special">{</phrase> <phrase role="identifier">ec_</phrase> <phrase role="special">}</phrase> <phrase role="special">);</phrase> 11795 <phrase role="special">}</phrase> 11796 <phrase role="special">}</phrase> 11797 11798<phrase role="keyword">private</phrase><phrase role="special">:</phrase> 11799 <phrase role="comment">// If yield_t does not bind an error_code instance, store into here.</phrase> 11800 <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">system</phrase><phrase role="special">::</phrase><phrase role="identifier">error_code</phrase> <phrase role="identifier">ec_</phrase><phrase role="special">{};</phrase> 11801 <phrase role="identifier">yield_completion</phrase><phrase role="special">::</phrase><phrase role="identifier">ptr_t</phrase> <phrase role="identifier">ycomp_</phrase><phrase role="special">;</phrase> 11802<phrase role="special">};</phrase> 11803</programlisting> 11804 </para> 11805 <para> 11806 This is how <code><phrase role="identifier">yield_handler_base</phrase><phrase 11807 role="special">::</phrase><phrase role="identifier">ycomp_</phrase></code> 11808 becomes non-null: <code><phrase role="identifier">async_result_base</phrase></code>’s 11809 constructor injects a pointer back to its own <code><phrase role="identifier">yield_completion</phrase></code> 11810 member. 11811 </para> 11812 <para> 11813 Recall that the canonical <code><phrase role="identifier">yield_t</phrase></code> 11814 instance <code><phrase role="identifier">yield</phrase></code> initializes 11815 its <code><phrase role="identifier">error_code</phrase><phrase role="special">*</phrase></code> 11816 member <code><phrase role="identifier">ec_</phrase></code> to <code><phrase 11817 role="keyword">nullptr</phrase></code>. If this instance is passed to <code><phrase 11818 role="identifier">async_something</phrase><phrase role="special">()</phrase></code> 11819 (<code><phrase role="identifier">ec_</phrase></code> is still <code><phrase 11820 role="keyword">nullptr</phrase></code>), the copy stored in <code><phrase 11821 role="identifier">yield_handler_base</phrase></code> will likewise have null 11822 <code><phrase role="identifier">ec_</phrase></code>. <code><phrase role="identifier">async_result_base</phrase></code>’s 11823 constructor sets <code><phrase role="identifier">yield_handler_base</phrase></code>’s 11824 <code><phrase role="identifier">yield_t</phrase></code>’s <code><phrase role="identifier">ec_</phrase></code> 11825 member to point to its own <code><phrase role="identifier">error_code</phrase></code> 11826 member. 11827 </para> 11828 <para> 11829 The stage is now set. <code><phrase role="identifier">async_something</phrase><phrase 11830 role="special">()</phrase></code> initiates the actual async operation, arranging 11831 to call its <code><phrase role="identifier">yield_handler</phrase><phrase 11832 role="special"><</phrase><phrase role="keyword">void</phrase><phrase role="special">></phrase></code> 11833 instance on completion. Let’s say, for the sake of argument, that the actual 11834 async operation’s callback has signature <code><phrase role="keyword">void</phrase><phrase 11835 role="special">(</phrase><phrase role="identifier">error_code</phrase><phrase 11836 role="special">)</phrase></code>. 11837 </para> 11838 <para> 11839 But since it’s an async operation, control returns at once to <code><phrase 11840 role="identifier">async_something</phrase><phrase role="special">()</phrase></code>. 11841 <code><phrase role="identifier">async_something</phrase><phrase role="special">()</phrase></code> 11842 calls <code><phrase role="identifier">async_result</phrase><phrase role="special"><</phrase><phrase 11843 role="identifier">yield_handler</phrase><phrase role="special"><</phrase><phrase 11844 role="keyword">void</phrase><phrase role="special">>>::</phrase><phrase 11845 role="identifier">get</phrase><phrase role="special">()</phrase></code>, 11846 and will return its return value. 11847 </para> 11848 <para> 11849 <code><phrase role="identifier">async_result</phrase><phrase role="special"><</phrase><phrase 11850 role="identifier">yield_handler</phrase><phrase role="special"><</phrase><phrase 11851 role="keyword">void</phrase><phrase role="special">>>::</phrase><phrase 11852 role="identifier">get</phrase><phrase role="special">()</phrase></code> inherits 11853 <code><phrase role="identifier">async_result_base</phrase><phrase role="special">::</phrase><phrase 11854 role="identifier">get</phrase><phrase role="special">()</phrase></code>. 11855 </para> 11856 <para> 11857 <code><phrase role="identifier">async_result_base</phrase><phrase role="special">::</phrase><phrase 11858 role="identifier">get</phrase><phrase role="special">()</phrase></code> immediately 11859 calls <code><phrase role="identifier">yield_completion</phrase><phrase role="special">::</phrase><phrase 11860 role="identifier">wait</phrase><phrase role="special">()</phrase></code>. 11861 </para> 11862 <para> 11863<programlisting><phrase role="comment">// Bundle a completion bool flag with a spinlock to protect it.</phrase> 11864<phrase role="keyword">struct</phrase> <phrase role="identifier">yield_completion</phrase> <phrase role="special">{</phrase> 11865 <phrase role="keyword">enum</phrase> <phrase role="identifier">state_t</phrase> <phrase role="special">{</phrase> 11866 <phrase role="identifier">init</phrase><phrase role="special">,</phrase> 11867 <phrase role="identifier">waiting</phrase><phrase role="special">,</phrase> 11868 <phrase role="identifier">complete</phrase> 11869 <phrase role="special">};</phrase> 11870 11871 <phrase role="keyword">typedef</phrase> <phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">detail</phrase><phrase role="special">::</phrase><phrase role="identifier">spinlock</phrase> <phrase role="identifier">mutex_t</phrase><phrase role="special">;</phrase> 11872 <phrase role="keyword">typedef</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">unique_lock</phrase><phrase role="special"><</phrase> <phrase role="identifier">mutex_t</phrase> <phrase role="special">></phrase> <phrase role="identifier">lock_t</phrase><phrase role="special">;</phrase> 11873 <phrase role="keyword">typedef</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">intrusive_ptr</phrase><phrase role="special"><</phrase> <phrase role="identifier">yield_completion</phrase> <phrase role="special">></phrase> <phrase role="identifier">ptr_t</phrase><phrase role="special">;</phrase> 11874 11875 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">atomic</phrase><phrase role="special"><</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="special">></phrase> <phrase role="identifier">use_count_</phrase><phrase role="special">{</phrase> <phrase role="number">0</phrase> <phrase role="special">};</phrase> 11876 <phrase role="identifier">mutex_t</phrase> <phrase role="identifier">mtx_</phrase><phrase role="special">{};</phrase> 11877 <phrase role="identifier">state_t</phrase> <phrase role="identifier">state_</phrase><phrase role="special">{</phrase> <phrase role="identifier">init</phrase> <phrase role="special">};</phrase> 11878 11879 <phrase role="keyword">void</phrase> <phrase role="identifier">wait</phrase><phrase role="special">()</phrase> <phrase role="special">{</phrase> 11880 <phrase role="comment">// yield_handler_base::operator()() will set state_ `complete` and</phrase> 11881 <phrase role="comment">// attempt to wake a suspended fiber. It would be Bad if that call</phrase> 11882 <phrase role="comment">// happened between our detecting (complete != state_) and suspending.</phrase> 11883 <phrase role="identifier">lock_t</phrase> <phrase role="identifier">lk</phrase><phrase role="special">{</phrase> <phrase role="identifier">mtx_</phrase> <phrase role="special">};</phrase> 11884 <phrase role="comment">// If state_ is already set, we're done here: don't suspend.</phrase> 11885 <phrase role="keyword">if</phrase> <phrase role="special">(</phrase> <phrase role="identifier">complete</phrase> <phrase role="special">!=</phrase> <phrase role="identifier">state_</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase> 11886 <phrase role="identifier">state_</phrase> <phrase role="special">=</phrase> <phrase role="identifier">waiting</phrase><phrase role="special">;</phrase> 11887 <phrase role="comment">// suspend(unique_lock<spinlock>) unlocks the lock in the act of</phrase> 11888 <phrase role="comment">// resuming another fiber</phrase> 11889 <phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">context</phrase><phrase role="special">::</phrase><phrase role="identifier">active</phrase><phrase role="special">()-></phrase><phrase role="identifier">suspend</phrase><phrase role="special">(</phrase> <phrase role="identifier">lk</phrase><phrase role="special">);</phrase> 11890 <phrase role="special">}</phrase> 11891 <phrase role="special">}</phrase> 11892 11893 <phrase role="keyword">friend</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">intrusive_ptr_add_ref</phrase><phrase role="special">(</phrase> <phrase role="identifier">yield_completion</phrase> <phrase role="special">*</phrase> <phrase role="identifier">yc</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase> <phrase role="special">{</phrase> 11894 <phrase role="identifier">BOOST_ASSERT</phrase><phrase role="special">(</phrase> <phrase role="keyword">nullptr</phrase> <phrase role="special">!=</phrase> <phrase role="identifier">yc</phrase><phrase role="special">);</phrase> 11895 <phrase role="identifier">yc</phrase><phrase role="special">-></phrase><phrase role="identifier">use_count_</phrase><phrase role="special">.</phrase><phrase role="identifier">fetch_add</phrase><phrase role="special">(</phrase> <phrase role="number">1</phrase><phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">memory_order_relaxed</phrase><phrase role="special">);</phrase> 11896 <phrase role="special">}</phrase> 11897 11898 <phrase role="keyword">friend</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">intrusive_ptr_release</phrase><phrase role="special">(</phrase> <phrase role="identifier">yield_completion</phrase> <phrase role="special">*</phrase> <phrase role="identifier">yc</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase> <phrase role="special">{</phrase> 11899 <phrase role="identifier">BOOST_ASSERT</phrase><phrase role="special">(</phrase> <phrase role="keyword">nullptr</phrase> <phrase role="special">!=</phrase> <phrase role="identifier">yc</phrase><phrase role="special">);</phrase> 11900 <phrase role="keyword">if</phrase> <phrase role="special">(</phrase> <phrase role="number">1</phrase> <phrase role="special">==</phrase> <phrase role="identifier">yc</phrase><phrase role="special">-></phrase><phrase role="identifier">use_count_</phrase><phrase role="special">.</phrase><phrase role="identifier">fetch_sub</phrase><phrase role="special">(</phrase> <phrase role="number">1</phrase><phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">memory_order_release</phrase><phrase role="special">)</phrase> <phrase role="special">)</phrase> <phrase role="special">{</phrase> 11901 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">atomic_thread_fence</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">memory_order_acquire</phrase><phrase role="special">);</phrase> 11902 <phrase role="keyword">delete</phrase> <phrase role="identifier">yc</phrase><phrase role="special">;</phrase> 11903 <phrase role="special">}</phrase> 11904 <phrase role="special">}</phrase> 11905<phrase role="special">};</phrase> 11906</programlisting> 11907 </para> 11908 <para> 11909 Supposing that the pending async operation has not yet completed, <code><phrase 11910 role="identifier">yield_completion</phrase><phrase role="special">::</phrase><phrase 11911 role="identifier">completed_</phrase></code> will still be <code><phrase 11912 role="keyword">false</phrase></code>, and <code><phrase role="identifier">wait</phrase><phrase 11913 role="special">()</phrase></code> will call <link linkend="context_suspend"><code>context::suspend()</code></link> on 11914 the currently-running fiber. 11915 </para> 11916 <para> 11917 Other fibers will now have a chance to run. 11918 </para> 11919 <para> 11920 Some time later, the async operation completes. It calls <code><phrase role="identifier">yield_handler</phrase><phrase 11921 role="special"><</phrase><phrase role="keyword">void</phrase><phrase role="special">>::</phrase><phrase 11922 role="keyword">operator</phrase><phrase role="special">()(</phrase><phrase 11923 role="identifier">error_code</phrase> <phrase role="keyword">const</phrase><phrase 11924 role="special">&)</phrase></code> with an <code><phrase role="identifier">error_code</phrase></code> 11925 indicating either success or failure. We’ll consider both cases. 11926 </para> 11927 <para> 11928 <code><phrase role="identifier">yield_handler</phrase><phrase role="special"><</phrase><phrase 11929 role="keyword">void</phrase><phrase role="special">></phrase></code> explicitly 11930 inherits <code><phrase role="keyword">operator</phrase><phrase role="special">()(</phrase><phrase 11931 role="identifier">error_code</phrase> <phrase role="keyword">const</phrase><phrase 11932 role="special">&)</phrase></code> from <code><phrase role="identifier">yield_handler_base</phrase></code>. 11933 </para> 11934 <para> 11935 <code><phrase role="identifier">yield_handler_base</phrase><phrase role="special">::</phrase><phrase 11936 role="keyword">operator</phrase><phrase role="special">()(</phrase><phrase 11937 role="identifier">error_code</phrase> <phrase role="keyword">const</phrase><phrase 11938 role="special">&)</phrase></code> first sets <code><phrase role="identifier">yield_completion</phrase><phrase 11939 role="special">::</phrase><phrase role="identifier">completed_</phrase></code> 11940 <code><phrase role="keyword">true</phrase></code>. This way, if <code><phrase 11941 role="identifier">async_something</phrase><phrase role="special">()</phrase></code>’s 11942 async operation completes immediately — if <code><phrase role="identifier">yield_handler_base</phrase><phrase 11943 role="special">::</phrase><phrase role="keyword">operator</phrase><phrase 11944 role="special">()</phrase></code> is called even before <code><phrase role="identifier">async_result_base</phrase><phrase 11945 role="special">::</phrase><phrase role="identifier">get</phrase><phrase role="special">()</phrase></code> 11946 — the calling fiber will <emphasis>not</emphasis> suspend. 11947 </para> 11948 <para> 11949 The actual <code><phrase role="identifier">error_code</phrase></code> produced 11950 by the async operation is then stored through the stored <code><phrase role="identifier">yield_t</phrase><phrase 11951 role="special">::</phrase><phrase role="identifier">ec_</phrase></code> pointer. 11952 If <code><phrase role="identifier">async_something</phrase><phrase role="special">()</phrase></code>’s 11953 caller used (e.g.) <code><phrase role="identifier">yield</phrase><phrase 11954 role="special">[</phrase><phrase role="identifier">my_ec</phrase><phrase 11955 role="special">]</phrase></code> to bind a local <code><phrase role="identifier">error_code</phrase></code> 11956 instance, the actual <code><phrase role="identifier">error_code</phrase></code> 11957 value is stored into the caller’s variable. Otherwise, it is stored into 11958 <code><phrase role="identifier">async_result_base</phrase><phrase role="special">::</phrase><phrase 11959 role="identifier">ec_</phrase></code>. 11960 </para> 11961 <para> 11962 If the stored fiber context <code><phrase role="identifier">yield_handler_base</phrase><phrase 11963 role="special">::</phrase><phrase role="identifier">ctx_</phrase></code> 11964 is not already running, it is marked as ready to run by passing it to <link linkend="context_schedule"><code>context::schedule()</code></link>. 11965 Control then returns from <code><phrase role="identifier">yield_handler_base</phrase><phrase 11966 role="special">::</phrase><phrase role="keyword">operator</phrase><phrase 11967 role="special">()</phrase></code>: the callback is done. 11968 </para> 11969 <para> 11970 In due course, that fiber is resumed. Control returns from <link linkend="context_suspend"><code>context::suspend()</code></link> to 11971 <code><phrase role="identifier">yield_completion</phrase><phrase role="special">::</phrase><phrase 11972 role="identifier">wait</phrase><phrase role="special">()</phrase></code>, 11973 which returns to <code><phrase role="identifier">async_result_base</phrase><phrase 11974 role="special">::</phrase><phrase role="identifier">get</phrase><phrase role="special">()</phrase></code>. 11975 </para> 11976 <itemizedlist> 11977 <listitem> 11978 <simpara> 11979 If the original caller passed <code><phrase role="identifier">yield</phrase><phrase 11980 role="special">[</phrase><phrase role="identifier">my_ec</phrase><phrase 11981 role="special">]</phrase></code> to <code><phrase role="identifier">async_something</phrase><phrase 11982 role="special">()</phrase></code> to bind a local <code><phrase role="identifier">error_code</phrase></code> 11983 instance, then <code><phrase role="identifier">yield_handler_base</phrase><phrase 11984 role="special">::</phrase><phrase role="keyword">operator</phrase><phrase 11985 role="special">()</phrase></code> stored its <code><phrase role="identifier">error_code</phrase></code> 11986 to the caller’s <code><phrase role="identifier">my_ec</phrase></code> 11987 instance, leaving <code><phrase role="identifier">async_result_base</phrase><phrase 11988 role="special">::</phrase><phrase role="identifier">ec_</phrase></code> 11989 initialized to success. 11990 </simpara> 11991 </listitem> 11992 <listitem> 11993 <simpara> 11994 If the original caller passed <code><phrase role="identifier">yield</phrase></code> 11995 to <code><phrase role="identifier">async_something</phrase><phrase role="special">()</phrase></code> 11996 without binding a local <code><phrase role="identifier">error_code</phrase></code> 11997 variable, then <code><phrase role="identifier">yield_handler_base</phrase><phrase 11998 role="special">::</phrase><phrase role="keyword">operator</phrase><phrase 11999 role="special">()</phrase></code> stored its <code><phrase role="identifier">error_code</phrase></code> 12000 into <code><phrase role="identifier">async_result_base</phrase><phrase 12001 role="special">::</phrase><phrase role="identifier">ec_</phrase></code>. 12002 If in fact that <code><phrase role="identifier">error_code</phrase></code> 12003 is success, then all is well. 12004 </simpara> 12005 </listitem> 12006 <listitem> 12007 <simpara> 12008 Otherwise — the original caller did not bind a local <code><phrase role="identifier">error_code</phrase></code> 12009 and <code><phrase role="identifier">yield_handler_base</phrase><phrase 12010 role="special">::</phrase><phrase role="keyword">operator</phrase><phrase 12011 role="special">()</phrase></code> was called with an <code><phrase role="identifier">error_code</phrase></code> 12012 indicating error — <code><phrase role="identifier">async_result_base</phrase><phrase 12013 role="special">::</phrase><phrase role="identifier">get</phrase><phrase 12014 role="special">()</phrase></code> throws <code><phrase role="identifier">system_error</phrase></code> 12015 with that <code><phrase role="identifier">error_code</phrase></code>. 12016 </simpara> 12017 </listitem> 12018 </itemizedlist> 12019 <para> 12020 The case in which <code><phrase role="identifier">async_something</phrase><phrase 12021 role="special">()</phrase></code>’s completion callback has signature <code><phrase 12022 role="keyword">void</phrase><phrase role="special">()</phrase></code> is 12023 similar. <code><phrase role="identifier">yield_handler</phrase><phrase role="special"><</phrase><phrase 12024 role="keyword">void</phrase><phrase role="special">>::</phrase><phrase 12025 role="keyword">operator</phrase><phrase role="special">()()</phrase></code> 12026 invokes the machinery above with a <quote>success</quote> <code><phrase role="identifier">error_code</phrase></code>. 12027 </para> 12028 <para> 12029 A completion callback with signature <code><phrase role="keyword">void</phrase><phrase 12030 role="special">(</phrase><phrase role="identifier">error_code</phrase><phrase 12031 role="special">,</phrase> <phrase role="identifier">T</phrase><phrase role="special">)</phrase></code> 12032 (that is: in addition to <code><phrase role="identifier">error_code</phrase></code>, 12033 callback receives some data item) is handled somewhat differently. For this 12034 kind of signature, <code><phrase role="identifier">handler_type</phrase><phrase 12035 role="special"><>::</phrase><phrase role="identifier">type</phrase></code> 12036 specifies <code><phrase role="identifier">yield_handler</phrase><phrase role="special"><</phrase><phrase 12037 role="identifier">T</phrase><phrase role="special">></phrase></code> (for 12038 <code><phrase role="identifier">T</phrase></code> other than <code><phrase 12039 role="keyword">void</phrase></code>). 12040 </para> 12041 <para> 12042 A <code><phrase role="identifier">yield_handler</phrase><phrase role="special"><</phrase><phrase 12043 role="identifier">T</phrase><phrase role="special">></phrase></code> reserves 12044 a <code><phrase role="identifier">value_</phrase></code> pointer to a value 12045 of type <code><phrase role="identifier">T</phrase></code>: 12046 </para> 12047 <para> 12048<programlisting><phrase role="comment">// asio uses handler_type<completion token type, signature>::type to decide</phrase> 12049<phrase role="comment">// what to instantiate as the actual handler. Below, we specialize</phrase> 12050<phrase role="comment">// handler_type< yield_t, ... > to indicate yield_handler<>. So when you pass</phrase> 12051<phrase role="comment">// an instance of yield_t as an asio completion token, asio selects</phrase> 12052<phrase role="comment">// yield_handler<> as the actual handler class.</phrase> 12053<phrase role="keyword">template</phrase><phrase role="special"><</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">T</phrase> <phrase role="special">></phrase> 12054<phrase role="keyword">class</phrase> <phrase role="identifier">yield_handler</phrase><phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <phrase role="identifier">yield_handler_base</phrase> <phrase role="special">{</phrase> 12055<phrase role="keyword">public</phrase><phrase role="special">:</phrase> 12056 <phrase role="comment">// asio passes the completion token to the handler constructor</phrase> 12057 <phrase role="keyword">explicit</phrase> <phrase role="identifier">yield_handler</phrase><phrase role="special">(</phrase> <phrase role="identifier">yield_t</phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">y</phrase><phrase role="special">)</phrase> <phrase role="special">:</phrase> 12058 <phrase role="identifier">yield_handler_base</phrase><phrase role="special">{</phrase> <phrase role="identifier">y</phrase> <phrase role="special">}</phrase> <phrase role="special">{</phrase> 12059 <phrase role="special">}</phrase> 12060 12061 <phrase role="comment">// completion callback passing only value (T)</phrase> 12062 <phrase role="keyword">void</phrase> <phrase role="keyword">operator</phrase><phrase role="special">()(</phrase> <phrase role="identifier">T</phrase> <phrase role="identifier">t</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase> 12063 <phrase role="comment">// just like callback passing success error_code</phrase> 12064 <phrase role="special">(*</phrase><phrase role="keyword">this</phrase><phrase role="special">)(</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">system</phrase><phrase role="special">::</phrase><phrase role="identifier">error_code</phrase><phrase role="special">(),</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">move</phrase><phrase role="special">(</phrase><phrase role="identifier">t</phrase><phrase role="special">)</phrase> <phrase role="special">);</phrase> 12065 <phrase role="special">}</phrase> 12066 12067 <phrase role="comment">// completion callback passing (error_code, T)</phrase> 12068 <phrase role="keyword">void</phrase> <phrase role="keyword">operator</phrase><phrase role="special">()(</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">system</phrase><phrase role="special">::</phrase><phrase role="identifier">error_code</phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">ec</phrase><phrase role="special">,</phrase> <phrase role="identifier">T</phrase> <phrase role="identifier">t</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase> 12069 <phrase role="identifier">BOOST_ASSERT_MSG</phrase><phrase role="special">(</phrase> <phrase role="identifier">value_</phrase><phrase role="special">,</phrase> 12070 <phrase role="string">"Must inject value ptr "</phrase> 12071 <phrase role="string">"before caling yield_handler<T>::operator()()"</phrase><phrase role="special">);</phrase> 12072 <phrase role="comment">// move the value to async_result<> instance BEFORE waking up a</phrase> 12073 <phrase role="comment">// suspended fiber</phrase> 12074 <phrase role="special">*</phrase> <phrase role="identifier">value_</phrase> <phrase role="special">=</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">move</phrase><phrase role="special">(</phrase> <phrase role="identifier">t</phrase><phrase role="special">);</phrase> 12075 <phrase role="comment">// forward the call to base-class completion handler</phrase> 12076 <phrase role="identifier">yield_handler_base</phrase><phrase role="special">::</phrase><phrase role="keyword">operator</phrase><phrase role="special">()(</phrase> <phrase role="identifier">ec</phrase><phrase role="special">);</phrase> 12077 <phrase role="special">}</phrase> 12078 12079<phrase role="comment">//private:</phrase> 12080 <phrase role="comment">// pointer to destination for eventual value</phrase> 12081 <phrase role="comment">// this must be injected by async_result before operator()() is called</phrase> 12082 <phrase role="identifier">T</phrase> <phrase role="special">*</phrase> <phrase role="identifier">value_</phrase><phrase role="special">{</phrase> <phrase role="keyword">nullptr</phrase> <phrase role="special">};</phrase> 12083<phrase role="special">};</phrase> 12084</programlisting> 12085 </para> 12086 <para> 12087 This pointer is initialized to <code><phrase role="keyword">nullptr</phrase></code>. 12088 </para> 12089 <para> 12090 When <code><phrase role="identifier">async_something</phrase><phrase role="special">()</phrase></code> 12091 instantiates <code><phrase role="identifier">async_result</phrase><phrase 12092 role="special"><</phrase><phrase role="identifier">yield_handler</phrase><phrase 12093 role="special"><</phrase><phrase role="identifier">T</phrase><phrase role="special">>></phrase></code>: 12094 </para> 12095 <para> 12096<programlisting><phrase role="comment">// asio constructs an async_result<> instance from the yield_handler specified</phrase> 12097<phrase role="comment">// by handler_type<>::type. A particular asio async method constructs the</phrase> 12098<phrase role="comment">// yield_handler, constructs this async_result specialization from it, then</phrase> 12099<phrase role="comment">// returns the result of calling its get() method.</phrase> 12100<phrase role="keyword">template</phrase><phrase role="special"><</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">T</phrase> <phrase role="special">></phrase> 12101<phrase role="keyword">class</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"><</phrase> <phrase role="identifier">T</phrase> <phrase role="special">></phrase> <phrase role="special">></phrase> <phrase role="special">:</phrase> 12102 <phrase role="keyword">public</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">asio</phrase><phrase role="special">::</phrase><phrase role="identifier">detail</phrase><phrase role="special">::</phrase><phrase role="identifier">async_result_base</phrase> <phrase role="special">{</phrase> 12103<phrase role="keyword">public</phrase><phrase role="special">:</phrase> 12104 <phrase role="comment">// type returned by get()</phrase> 12105 <phrase role="keyword">typedef</phrase> <phrase role="identifier">T</phrase> <phrase role="identifier">type</phrase><phrase role="special">;</phrase> 12106 12107 <phrase role="keyword">explicit</phrase> <phrase role="identifier">async_result</phrase><phrase role="special">(</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">asio</phrase><phrase role="special">::</phrase><phrase role="identifier">detail</phrase><phrase role="special">::</phrase><phrase role="identifier">yield_handler</phrase><phrase role="special"><</phrase> <phrase role="identifier">T</phrase> <phrase role="special">></phrase> <phrase role="special">&</phrase> <phrase role="identifier">h</phrase><phrase role="special">)</phrase> <phrase role="special">:</phrase> 12108 <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">asio</phrase><phrase role="special">::</phrase><phrase role="identifier">detail</phrase><phrase role="special">::</phrase><phrase role="identifier">async_result_base</phrase><phrase role="special">{</phrase> <phrase role="identifier">h</phrase> <phrase role="special">}</phrase> <phrase role="special">{</phrase> 12109 <phrase role="comment">// Inject ptr to our value_ member into yield_handler<>: result will</phrase> 12110 <phrase role="comment">// be stored here.</phrase> 12111 <phrase role="identifier">h</phrase><phrase role="special">.</phrase><phrase role="identifier">value_</phrase> <phrase role="special">=</phrase> <phrase role="special">&</phrase> <phrase role="identifier">value_</phrase><phrase role="special">;</phrase> 12112 <phrase role="special">}</phrase> 12113 12114 <phrase role="comment">// asio async method returns result of calling get()</phrase> 12115 <phrase role="identifier">type</phrase> <phrase role="identifier">get</phrase><phrase role="special">()</phrase> <phrase role="special">{</phrase> 12116 <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">asio</phrase><phrase role="special">::</phrase><phrase role="identifier">detail</phrase><phrase role="special">::</phrase><phrase role="identifier">async_result_base</phrase><phrase role="special">::</phrase><phrase role="identifier">get</phrase><phrase role="special">();</phrase> 12117 <phrase role="keyword">return</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">move</phrase><phrase role="special">(</phrase> <phrase role="identifier">value_</phrase><phrase role="special">);</phrase> 12118 <phrase role="special">}</phrase> 12119 12120<phrase role="keyword">private</phrase><phrase role="special">:</phrase> 12121 <phrase role="identifier">type</phrase> <phrase role="identifier">value_</phrase><phrase role="special">{};</phrase> 12122<phrase role="special">};</phrase> 12123</programlisting> 12124 </para> 12125 <para> 12126 this <code><phrase role="identifier">async_result</phrase><phrase role="special"><></phrase></code> 12127 specialization reserves a member of type <code><phrase role="identifier">T</phrase></code> 12128 to receive the passed data item, and sets <code><phrase role="identifier">yield_handler</phrase><phrase 12129 role="special"><</phrase><phrase role="identifier">T</phrase><phrase role="special">>::</phrase><phrase 12130 role="identifier">value_</phrase></code> to point to its own data member. 12131 </para> 12132 <para> 12133 <code><phrase role="identifier">async_result</phrase><phrase role="special"><</phrase><phrase 12134 role="identifier">yield_handler</phrase><phrase role="special"><</phrase><phrase 12135 role="identifier">T</phrase><phrase role="special">>></phrase></code> 12136 overrides <code><phrase role="identifier">get</phrase><phrase role="special">()</phrase></code>. 12137 The override calls <code><phrase role="identifier">async_result_base</phrase><phrase 12138 role="special">::</phrase><phrase role="identifier">get</phrase><phrase role="special">()</phrase></code>, 12139 so the calling fiber suspends as described above. 12140 </para> 12141 <para> 12142 <code><phrase role="identifier">yield_handler</phrase><phrase role="special"><</phrase><phrase 12143 role="identifier">T</phrase><phrase role="special">>::</phrase><phrase 12144 role="keyword">operator</phrase><phrase role="special">()(</phrase><phrase 12145 role="identifier">error_code</phrase><phrase role="special">,</phrase> <phrase 12146 role="identifier">T</phrase><phrase role="special">)</phrase></code> stores 12147 its passed <code><phrase role="identifier">T</phrase></code> value into 12148 <code><phrase role="identifier">async_result</phrase><phrase role="special"><</phrase><phrase 12149 role="identifier">yield_handler</phrase><phrase role="special"><</phrase><phrase 12150 role="identifier">T</phrase><phrase role="special">>>::</phrase><phrase 12151 role="identifier">value_</phrase></code>. 12152 </para> 12153 <para> 12154 Then it passes control to <code><phrase role="identifier">yield_handler_base</phrase><phrase 12155 role="special">::</phrase><phrase role="keyword">operator</phrase><phrase 12156 role="special">()(</phrase><phrase role="identifier">error_code</phrase><phrase 12157 role="special">)</phrase></code> to deal with waking the original fiber as 12158 described above. 12159 </para> 12160 <para> 12161 When <code><phrase role="identifier">async_result</phrase><phrase role="special"><</phrase><phrase 12162 role="identifier">yield_handler</phrase><phrase role="special"><</phrase><phrase 12163 role="identifier">T</phrase><phrase role="special">>>::</phrase><phrase 12164 role="identifier">get</phrase><phrase role="special">()</phrase></code> resumes, 12165 it returns the stored <code><phrase role="identifier">value_</phrase></code> 12166 to <code><phrase role="identifier">async_something</phrase><phrase role="special">()</phrase></code> 12167 and ultimately to <code><phrase role="identifier">async_something</phrase><phrase 12168 role="special">()</phrase></code>’s caller. 12169 </para> 12170 <para> 12171 The case of a callback signature <code><phrase role="keyword">void</phrase><phrase 12172 role="special">(</phrase><phrase role="identifier">T</phrase><phrase role="special">)</phrase></code> 12173 is handled by having <code><phrase role="identifier">yield_handler</phrase><phrase 12174 role="special"><</phrase><phrase role="identifier">T</phrase><phrase role="special">>::</phrase><phrase 12175 role="keyword">operator</phrase><phrase role="special">()(</phrase><phrase 12176 role="identifier">T</phrase><phrase role="special">)</phrase></code> engage 12177 the <code><phrase role="keyword">void</phrase><phrase role="special">(</phrase><phrase 12178 role="identifier">error_code</phrase><phrase role="special">,</phrase> <phrase 12179 role="identifier">T</phrase><phrase role="special">)</phrase></code> machinery, 12180 passing a <quote>success</quote> <code><phrase role="identifier">error_code</phrase></code>. 12181 </para> 12182 <para> 12183 The source code above is found in <ulink url="../../examples/asio/yield.hpp">yield.hpp</ulink> 12184 and <ulink url="../../examples/asio/detail/yield.hpp">detail/yield.hpp</ulink>. 12185 </para> 12186 </section> 12187 </section> 12188 <section id="fiber.nonblocking"> 12189 <title><anchor id="nonblocking"/><link linkend="fiber.nonblocking">Integrating 12190 Fibers with Nonblocking I/O</link></title> 12191 <bridgehead renderas="sect3" id="fiber.nonblocking.h0"> 12192 <phrase id="fiber.nonblocking.overview"/><link linkend="fiber.nonblocking.overview">Overview</link> 12193 </bridgehead> 12194 <para> 12195 <emphasis>Nonblocking</emphasis> I/O is distinct from <emphasis>asynchronous</emphasis> 12196 I/O. A true async I/O operation promises to initiate the operation and notify 12197 the caller on completion, usually via some sort of callback (as described in 12198 <link linkend="callbacks">Integrating Fibers with Asynchronous Callbacks</link>). 12199 </para> 12200 <para> 12201 In contrast, a nonblocking I/O operation refuses to start at all if it would 12202 be necessary to block, returning an error code such as <ulink url="http://man7.org/linux/man-pages/man3/errno.3.html"><code><phrase 12203 role="identifier">EWOULDBLOCK</phrase></code></ulink>. The operation is performed 12204 only when it can complete immediately. In effect, the caller must repeatedly 12205 retry the operation until it stops returning <code><phrase role="identifier">EWOULDBLOCK</phrase></code>. 12206 </para> 12207 <para> 12208 In a classic event-driven program, it can be something of a headache to use 12209 nonblocking I/O. At the point where the nonblocking I/O is attempted, a return 12210 value of <code><phrase role="identifier">EWOULDBLOCK</phrase></code> requires 12211 the caller to pass control back to the main event loop, arranging to retry 12212 again on the next iteration. 12213 </para> 12214 <para> 12215 Worse, a nonblocking I/O operation might <emphasis>partially</emphasis> succeed. 12216 That means that the relevant business logic must continue receiving control 12217 on every main loop iteration until all required data have been processed: a 12218 doubly-nested loop, implemented as a callback-driven state machine. 12219 </para> 12220 <para> 12221 <emphasis role="bold">Boost.Fiber</emphasis> can simplify this problem immensely. 12222 Once you have integrated with the application's main loop as described in 12223 <link linkend="integration">Sharing a Thread with Another Main Loop</link>, 12224 waiting for the next main-loop iteration is as simple as calling <link linkend="this_fiber_yield"><code>this_fiber::yield()</code></link>. 12225 </para> 12226 <bridgehead renderas="sect3" id="fiber.nonblocking.h1"> 12227 <phrase id="fiber.nonblocking.example_nonblocking_api"/><link linkend="fiber.nonblocking.example_nonblocking_api">Example 12228 Nonblocking API</link> 12229 </bridgehead> 12230 <para> 12231 For purposes of illustration, consider this API: 12232 </para> 12233 <para> 12234<programlisting><phrase role="keyword">class</phrase> <phrase role="identifier">NonblockingAPI</phrase> <phrase role="special">{</phrase> 12235<phrase role="keyword">public</phrase><phrase role="special">:</phrase> 12236 <phrase role="identifier">NonblockingAPI</phrase><phrase role="special">();</phrase> 12237 12238 <phrase role="comment">// nonblocking operation: may return EWOULDBLOCK</phrase> 12239 <phrase role="keyword">int</phrase> <phrase role="identifier">read</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="special">&</phrase> <phrase role="identifier">data</phrase><phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">desired</phrase><phrase role="special">);</phrase> 12240 12241 <phrase role="special">...</phrase> 12242<phrase role="special">};</phrase> 12243</programlisting> 12244 </para> 12245 <bridgehead renderas="sect3" id="fiber.nonblocking.h2"> 12246 <phrase id="fiber.nonblocking.polling_for_completion"/><link linkend="fiber.nonblocking.polling_for_completion">Polling 12247 for Completion</link> 12248 </bridgehead> 12249 <para> 12250 We can build a low-level wrapper around <code><phrase role="identifier">NonblockingAPI</phrase><phrase 12251 role="special">::</phrase><phrase role="identifier">read</phrase><phrase role="special">()</phrase></code> 12252 that shields its caller from ever having to deal with <code><phrase role="identifier">EWOULDBLOCK</phrase></code>: 12253 </para> 12254 <para> 12255<programlisting><phrase role="comment">// guaranteed not to return EWOULDBLOCK</phrase> 12256<phrase role="keyword">int</phrase> <phrase role="identifier">read_chunk</phrase><phrase role="special">(</phrase> <phrase role="identifier">NonblockingAPI</phrase> <phrase role="special">&</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">&</phrase> <phrase role="identifier">data</phrase><phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">desired</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase> 12257 <phrase role="keyword">int</phrase> <phrase role="identifier">error</phrase><phrase role="special">;</phrase> 12258 <phrase role="keyword">while</phrase> <phrase role="special">(</phrase> <phrase role="identifier">EWOULDBLOCK</phrase> <phrase role="special">==</phrase> <phrase role="special">(</phrase> <phrase role="identifier">error</phrase> <phrase role="special">=</phrase> <phrase role="identifier">api</phrase><phrase role="special">.</phrase><phrase role="identifier">read</phrase><phrase role="special">(</phrase> <phrase role="identifier">data</phrase><phrase role="special">,</phrase> <phrase role="identifier">desired</phrase><phrase role="special">)</phrase> <phrase role="special">)</phrase> <phrase role="special">)</phrase> <phrase role="special">{</phrase> 12259 <phrase role="comment">// not ready yet -- try again on the next iteration of the</phrase> 12260 <phrase role="comment">// application's main loop</phrase> 12261 <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">this_fiber</phrase><phrase role="special">::</phrase><phrase role="identifier">yield</phrase><phrase role="special">();</phrase> 12262 <phrase role="special">}</phrase> 12263 <phrase role="keyword">return</phrase> <phrase role="identifier">error</phrase><phrase role="special">;</phrase> 12264<phrase role="special">}</phrase> 12265</programlisting> 12266 </para> 12267 <bridgehead renderas="sect3" id="fiber.nonblocking.h3"> 12268 <phrase id="fiber.nonblocking.filling_all_desired_data"/><link linkend="fiber.nonblocking.filling_all_desired_data">Filling 12269 All Desired Data</link> 12270 </bridgehead> 12271 <para> 12272 Given <code><phrase role="identifier">read_chunk</phrase><phrase role="special">()</phrase></code>, 12273 we can straightforwardly iterate until we have all desired data: 12274 </para> 12275 <para> 12276<programlisting><phrase role="comment">// keep reading until desired length, EOF or error</phrase> 12277<phrase role="comment">// may return both partial data and nonzero error</phrase> 12278<phrase role="keyword">int</phrase> <phrase role="identifier">read_desired</phrase><phrase role="special">(</phrase> <phrase role="identifier">NonblockingAPI</phrase> <phrase role="special">&</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">&</phrase> <phrase role="identifier">data</phrase><phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">desired</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase> 12279 <phrase role="comment">// we're going to accumulate results into 'data'</phrase> 12280 <phrase role="identifier">data</phrase><phrase role="special">.</phrase><phrase role="identifier">clear</phrase><phrase role="special">();</phrase> 12281 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="identifier">chunk</phrase><phrase role="special">;</phrase> 12282 <phrase role="keyword">int</phrase> <phrase role="identifier">error</phrase> <phrase role="special">=</phrase> <phrase role="number">0</phrase><phrase role="special">;</phrase> 12283 <phrase role="keyword">while</phrase> <phrase role="special">(</phrase> <phrase role="identifier">data</phrase><phrase role="special">.</phrase><phrase role="identifier">length</phrase><phrase role="special">()</phrase> <phrase role="special"><</phrase> <phrase role="identifier">desired</phrase> <phrase role="special">&&</phrase> 12284 <phrase role="special">(</phrase> <phrase role="identifier">error</phrase> <phrase role="special">=</phrase> <phrase role="identifier">read_chunk</phrase><phrase role="special">(</phrase> <phrase role="identifier">api</phrase><phrase role="special">,</phrase> <phrase role="identifier">chunk</phrase><phrase role="special">,</phrase> <phrase role="identifier">desired</phrase> <phrase role="special">-</phrase> <phrase role="identifier">data</phrase><phrase role="special">.</phrase><phrase role="identifier">length</phrase><phrase role="special">()</phrase> <phrase role="special">)</phrase> <phrase role="special">)</phrase> <phrase role="special">==</phrase> <phrase role="number">0</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase> 12285 <phrase role="identifier">data</phrase><phrase role="special">.</phrase><phrase role="identifier">append</phrase><phrase role="special">(</phrase> <phrase role="identifier">chunk</phrase><phrase role="special">);</phrase> 12286 <phrase role="special">}</phrase> 12287 <phrase role="keyword">return</phrase> <phrase role="identifier">error</phrase><phrase role="special">;</phrase> 12288<phrase role="special">}</phrase> 12289</programlisting> 12290 </para> 12291 <para> 12292 (Of <emphasis>course</emphasis> there are more efficient ways to accumulate 12293 string data. That's not the point of this example.) 12294 </para> 12295 <bridgehead renderas="sect3" id="fiber.nonblocking.h4"> 12296 <phrase id="fiber.nonblocking.wrapping_it_up"/><link linkend="fiber.nonblocking.wrapping_it_up">Wrapping 12297 it Up</link> 12298 </bridgehead> 12299 <para> 12300 Finally, we can define a relevant exception: 12301 </para> 12302 <para> 12303<programlisting><phrase role="comment">// exception class augmented with both partially-read data and errorcode</phrase> 12304<phrase role="keyword">class</phrase> <phrase role="identifier">IncompleteRead</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">runtime_error</phrase> <phrase role="special">{</phrase> 12305<phrase role="keyword">public</phrase><phrase role="special">:</phrase> 12306 <phrase role="identifier">IncompleteRead</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="keyword">const</phrase><phrase role="special">&</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">&</phrase> <phrase role="identifier">partial</phrase><phrase role="special">,</phrase> <phrase role="keyword">int</phrase> <phrase role="identifier">ec</phrase><phrase role="special">)</phrase> <phrase role="special">:</phrase> 12307 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">runtime_error</phrase><phrase role="special">(</phrase> <phrase role="identifier">what</phrase><phrase role="special">),</phrase> 12308 <phrase role="identifier">partial_</phrase><phrase role="special">(</phrase> <phrase role="identifier">partial</phrase><phrase role="special">),</phrase> 12309 <phrase role="identifier">ec_</phrase><phrase role="special">(</phrase> <phrase role="identifier">ec</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase> 12310 <phrase role="special">}</phrase> 12311 12312 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="identifier">get_partial</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase> <phrase role="special">{</phrase> 12313 <phrase role="keyword">return</phrase> <phrase role="identifier">partial_</phrase><phrase role="special">;</phrase> 12314 <phrase role="special">}</phrase> 12315 12316 <phrase role="keyword">int</phrase> <phrase role="identifier">get_errorcode</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase> <phrase role="special">{</phrase> 12317 <phrase role="keyword">return</phrase> <phrase role="identifier">ec_</phrase><phrase role="special">;</phrase> 12318 <phrase role="special">}</phrase> 12319 12320<phrase role="keyword">private</phrase><phrase role="special">:</phrase> 12321 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="identifier">partial_</phrase><phrase role="special">;</phrase> 12322 <phrase role="keyword">int</phrase> <phrase role="identifier">ec_</phrase><phrase role="special">;</phrase> 12323<phrase role="special">};</phrase> 12324</programlisting> 12325 </para> 12326 <para> 12327 and write a simple <code><phrase role="identifier">read</phrase><phrase role="special">()</phrase></code> 12328 function that either returns all desired data or throws <code><phrase role="identifier">IncompleteRead</phrase></code>: 12329 </para> 12330 <para> 12331<programlisting><phrase role="comment">// read all desired data or throw IncompleteRead</phrase> 12332<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="identifier">read</phrase><phrase role="special">(</phrase> <phrase role="identifier">NonblockingAPI</phrase> <phrase role="special">&</phrase> <phrase role="identifier">api</phrase><phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">desired</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase> 12333 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="identifier">data</phrase><phrase role="special">;</phrase> 12334 <phrase role="keyword">int</phrase> <phrase role="identifier">ec</phrase><phrase role="special">(</phrase> <phrase role="identifier">read_desired</phrase><phrase role="special">(</phrase> <phrase role="identifier">api</phrase><phrase role="special">,</phrase> <phrase role="identifier">data</phrase><phrase role="special">,</phrase> <phrase role="identifier">desired</phrase><phrase role="special">)</phrase> <phrase role="special">);</phrase> 12335 12336 <phrase role="comment">// for present purposes, EOF isn't a failure</phrase> 12337 <phrase role="keyword">if</phrase> <phrase role="special">(</phrase> <phrase role="number">0</phrase> <phrase role="special">==</phrase> <phrase role="identifier">ec</phrase> <phrase role="special">||</phrase> <phrase role="identifier">EOF</phrase> <phrase role="special">==</phrase> <phrase role="identifier">ec</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase> 12338 <phrase role="keyword">return</phrase> <phrase role="identifier">data</phrase><phrase role="special">;</phrase> 12339 <phrase role="special">}</phrase> 12340 12341 <phrase role="comment">// oh oh, partial read</phrase> 12342 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">ostringstream</phrase> <phrase role="identifier">msg</phrase><phrase role="special">;</phrase> 12343 <phrase role="identifier">msg</phrase> <phrase role="special"><<</phrase> <phrase role="string">"NonblockingAPI::read() error "</phrase> <phrase role="special"><<</phrase> <phrase role="identifier">ec</phrase> <phrase role="special"><<</phrase> <phrase role="string">" after "</phrase> 12344 <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="string">" of "</phrase> <phrase role="special"><<</phrase> <phrase role="identifier">desired</phrase> <phrase role="special"><<</phrase> <phrase role="string">" characters"</phrase><phrase role="special">;</phrase> 12345 <phrase role="keyword">throw</phrase> <phrase role="identifier">IncompleteRead</phrase><phrase role="special">(</phrase> <phrase role="identifier">msg</phrase><phrase role="special">.</phrase><phrase role="identifier">str</phrase><phrase role="special">(),</phrase> <phrase role="identifier">data</phrase><phrase role="special">,</phrase> <phrase role="identifier">ec</phrase><phrase role="special">);</phrase> 12346<phrase role="special">}</phrase> 12347</programlisting> 12348 </para> 12349 <para> 12350 Once we can transparently wait for the next main-loop iteration using <link linkend="this_fiber_yield"><code>this_fiber::yield()</code></link>, 12351 ordinary encapsulation Just Works. 12352 </para> 12353 <para> 12354 The source code above is found in <ulink url="../../examples/adapt_nonblocking.cpp">adapt_nonblocking.cpp</ulink>. 12355 </para> 12356 </section> 12357 <section id="fiber.when_any"> 12358 <title><anchor id="when_any"/><link linkend="fiber.when_any">when_any / when_all 12359 functionality</link></title> 12360 <bridgehead renderas="sect3" id="fiber.when_any.h0"> 12361 <phrase id="fiber.when_any.overview"/><link linkend="fiber.when_any.overview">Overview</link> 12362 </bridgehead> 12363 <para> 12364 A bit of wisdom from the early days of computing still holds true today: prefer 12365 to model program state using the instruction pointer rather than with Boolean 12366 flags. In other words, if the program must <quote>do something</quote> and 12367 then do something almost the same, but with minor changes... perhaps parts 12368 of that something should be broken out as smaller separate functions, rather 12369 than introducing flags to alter the internal behavior of a monolithic function. 12370 </para> 12371 <para> 12372 To that we would add: prefer to describe control flow using C++ native constructs 12373 such as function calls, <code><phrase role="keyword">if</phrase></code>, <code><phrase 12374 role="keyword">while</phrase></code>, <code><phrase role="keyword">for</phrase></code>, 12375 <code><phrase role="keyword">do</phrase></code> et al. rather than as chains 12376 of callbacks. 12377 </para> 12378 <para> 12379 One of the great strengths of <emphasis role="bold">Boost.Fiber</emphasis> 12380 is the flexibility it confers on the coder to restructure an application from 12381 chains of callbacks to straightforward C++ statement sequence, even when code 12382 in that fiber is in fact interleaved with code running in other fibers. 12383 </para> 12384 <para> 12385 There has been much recent discussion about the benefits of when_any and when_all 12386 functionality. When dealing with asynchronous and possibly unreliable services, 12387 these are valuable idioms. But of course when_any and when_all are closely 12388 tied to the use of chains of callbacks. 12389 </para> 12390 <para> 12391 This section presents recipes for achieving the same ends, in the context of 12392 a fiber that wants to <quote>do something</quote> when one or more other independent 12393 activities have completed. Accordingly, these are <code><phrase role="identifier">wait_something</phrase><phrase 12394 role="special">()</phrase></code> functions rather than <code><phrase role="identifier">when_something</phrase><phrase 12395 role="special">()</phrase></code> functions. The expectation is that the calling 12396 fiber asks to launch those independent activities, then waits for them, then 12397 sequentially proceeds with whatever processing depends on those results. 12398 </para> 12399 <para> 12400 The function names shown (e.g. <link linkend="wait_first_simple"><code><phrase 12401 role="identifier">wait_first_simple</phrase><phrase role="special">()</phrase></code></link>) 12402 are for illustrative purposes only, because all these functions have been bundled 12403 into a single source file. Presumably, if (say) <link linkend="wait_first_success"><code><phrase 12404 role="identifier">wait_first_success</phrase><phrase role="special">()</phrase></code></link> 12405 best suits your application needs, you could introduce that variant with the 12406 name <code><phrase role="identifier">wait_any</phrase><phrase role="special">()</phrase></code>. 12407 </para> 12408 <note> 12409 <para> 12410 The functions presented in this section accept variadic argument lists of 12411 task functions. Corresponding <code><phrase role="identifier">wait_something</phrase><phrase 12412 role="special">()</phrase></code> functions accepting a container of task 12413 functions are left as an exercise for the interested reader. Those should 12414 actually be simpler. Most of the complexity would arise from overloading 12415 the same name for both purposes. 12416 </para> 12417 </note> 12418 <para> 12419 All the source code for this section is found in <ulink url="../../examples/wait_stuff.cpp">wait_stuff.cpp</ulink>. 12420 </para> 12421 <bridgehead renderas="sect3" id="fiber.when_any.h1"> 12422 <phrase id="fiber.when_any.example_task_function"/><link linkend="fiber.when_any.example_task_function">Example 12423 Task Function</link> 12424 </bridgehead> 12425 <para> 12426 <anchor id="wait_sleeper"/>We found it convenient to model an asynchronous 12427 task using this function: 12428 </para> 12429 <para> 12430<programlisting><phrase role="keyword">template</phrase><phrase role="special"><</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">T</phrase> <phrase role="special">></phrase> 12431<phrase role="identifier">T</phrase> <phrase role="identifier">sleeper_impl</phrase><phrase role="special">(</phrase> <phrase role="identifier">T</phrase> <phrase role="identifier">item</phrase><phrase role="special">,</phrase> <phrase role="keyword">int</phrase> <phrase role="identifier">ms</phrase><phrase role="special">,</phrase> <phrase role="keyword">bool</phrase> <phrase role="identifier">thrw</phrase> <phrase role="special">=</phrase> <phrase role="keyword">false</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase> 12432 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">ostringstream</phrase> <phrase role="identifier">descb</phrase><phrase role="special">,</phrase> <phrase role="identifier">funcb</phrase><phrase role="special">;</phrase> 12433 <phrase role="identifier">descb</phrase> <phrase role="special"><<</phrase> <phrase role="identifier">item</phrase><phrase role="special">;</phrase> 12434 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="identifier">desc</phrase><phrase role="special">(</phrase> <phrase role="identifier">descb</phrase><phrase role="special">.</phrase><phrase role="identifier">str</phrase><phrase role="special">()</phrase> <phrase role="special">);</phrase> 12435 <phrase role="identifier">funcb</phrase> <phrase role="special"><<</phrase> <phrase role="string">" sleeper("</phrase> <phrase role="special"><<</phrase> <phrase role="identifier">item</phrase> <phrase role="special"><<</phrase> <phrase role="string">")"</phrase><phrase role="special">;</phrase> 12436 <phrase role="identifier">Verbose</phrase> <phrase role="identifier">v</phrase><phrase role="special">(</phrase> <phrase role="identifier">funcb</phrase><phrase role="special">.</phrase><phrase role="identifier">str</phrase><phrase role="special">()</phrase> <phrase role="special">);</phrase> 12437 12438 <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">this_fiber</phrase><phrase role="special">::</phrase><phrase role="identifier">sleep_for</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">milliseconds</phrase><phrase role="special">(</phrase> <phrase role="identifier">ms</phrase><phrase role="special">)</phrase> <phrase role="special">);</phrase> 12439 <phrase role="keyword">if</phrase> <phrase role="special">(</phrase> <phrase role="identifier">thrw</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase> 12440 <phrase role="keyword">throw</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">runtime_error</phrase><phrase role="special">(</phrase> <phrase role="identifier">desc</phrase><phrase role="special">);</phrase> 12441 <phrase role="special">}</phrase> 12442 <phrase role="keyword">return</phrase> <phrase role="identifier">item</phrase><phrase role="special">;</phrase> 12443<phrase role="special">}</phrase> 12444</programlisting> 12445 </para> 12446 <para> 12447 with type-specific <code><phrase role="identifier">sleeper</phrase><phrase 12448 role="special">()</phrase></code> <quote>front ends</quote> for <code><phrase 12449 role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase></code>, 12450 <code><phrase role="keyword">double</phrase></code> and <code><phrase role="keyword">int</phrase></code>. 12451 </para> 12452 <para> 12453 <code><phrase role="identifier">Verbose</phrase></code> simply prints a message 12454 to <code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase 12455 role="identifier">cout</phrase></code> on construction and destruction. 12456 </para> 12457 <para> 12458 Basically: 12459 </para> 12460 <orderedlist> 12461 <listitem> 12462 <simpara> 12463 <code><phrase role="identifier">sleeper</phrase><phrase role="special">()</phrase></code> 12464 prints a start message; 12465 </simpara> 12466 </listitem> 12467 <listitem> 12468 <simpara> 12469 sleeps for the specified number of milliseconds; 12470 </simpara> 12471 </listitem> 12472 <listitem> 12473 <simpara> 12474 if <code><phrase role="identifier">thrw</phrase></code> is passed as <code><phrase 12475 role="keyword">true</phrase></code>, throws a string description of the 12476 passed <code><phrase role="identifier">item</phrase></code>; 12477 </simpara> 12478 </listitem> 12479 <listitem> 12480 <simpara> 12481 else returns the passed <code><phrase role="identifier">item</phrase></code>. 12482 </simpara> 12483 </listitem> 12484 <listitem> 12485 <simpara> 12486 On the way out, <code><phrase role="identifier">sleeper</phrase><phrase 12487 role="special">()</phrase></code> produces a stop message. 12488 </simpara> 12489 </listitem> 12490 </orderedlist> 12491 <para> 12492 This function will feature in the example calls to the various functions presented 12493 below. 12494 </para> 12495 <section id="fiber.when_any.when_any"> 12496 <title><link linkend="fiber.when_any.when_any">when_any</link></title> 12497 <section id="fiber.when_any.when_any.when_any__simple_completion"> 12498 <title><anchor id="wait_first_simple_section"/><link linkend="fiber.when_any.when_any.when_any__simple_completion">when_any, 12499 simple completion</link></title> 12500 <para> 12501 The simplest case is when you only need to know that the first of a set 12502 of asynchronous tasks has completed — but you don't need to obtain a return 12503 value, and you're confident that they will not throw exceptions. 12504 </para> 12505 <para> 12506 <anchor id="wait_done"/>For this we introduce a <code><phrase role="identifier">Done</phrase></code> 12507 class to wrap a <code><phrase role="keyword">bool</phrase></code> variable 12508 with a <link linkend="class_condition_variable"><code>condition_variable</code></link> and a <link linkend="class_mutex"><code>mutex</code></link>: 12509 </para> 12510 <para> 12511<programlisting><phrase role="comment">// Wrap canonical pattern for condition_variable + bool flag</phrase> 12512<phrase role="keyword">struct</phrase> <phrase role="identifier">Done</phrase> <phrase role="special">{</phrase> 12513<phrase role="keyword">private</phrase><phrase role="special">:</phrase> 12514 <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">condition_variable</phrase> <phrase role="identifier">cond</phrase><phrase role="special">;</phrase> 12515 <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">mutex</phrase> <phrase role="identifier">mutex</phrase><phrase role="special">;</phrase> 12516 <phrase role="keyword">bool</phrase> <phrase role="identifier">ready</phrase> <phrase role="special">=</phrase> <phrase role="keyword">false</phrase><phrase role="special">;</phrase> 12517 12518<phrase role="keyword">public</phrase><phrase role="special">:</phrase> 12519 <phrase role="keyword">typedef</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">shared_ptr</phrase><phrase role="special"><</phrase> <phrase role="identifier">Done</phrase> <phrase role="special">></phrase> <phrase role="identifier">ptr</phrase><phrase role="special">;</phrase> 12520 12521 <phrase role="keyword">void</phrase> <phrase role="identifier">wait</phrase><phrase role="special">()</phrase> <phrase role="special">{</phrase> 12522 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">unique_lock</phrase><phrase role="special"><</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">></phrase> <phrase role="identifier">lock</phrase><phrase role="special">(</phrase> <phrase role="identifier">mutex</phrase><phrase role="special">);</phrase> 12523 <phrase role="identifier">cond</phrase><phrase role="special">.</phrase><phrase role="identifier">wait</phrase><phrase role="special">(</phrase> <phrase role="identifier">lock</phrase><phrase role="special">,</phrase> <phrase role="special">[</phrase><phrase role="keyword">this</phrase><phrase role="special">](){</phrase> <phrase role="keyword">return</phrase> <phrase role="identifier">ready</phrase><phrase role="special">;</phrase> <phrase role="special">});</phrase> 12524 <phrase role="special">}</phrase> 12525 12526 <phrase role="keyword">void</phrase> <phrase role="identifier">notify</phrase><phrase role="special">()</phrase> <phrase role="special">{</phrase> 12527 <phrase role="special">{</phrase> 12528 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">unique_lock</phrase><phrase role="special"><</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">></phrase> <phrase role="identifier">lock</phrase><phrase role="special">(</phrase> <phrase role="identifier">mutex</phrase><phrase role="special">);</phrase> 12529 <phrase role="identifier">ready</phrase> <phrase role="special">=</phrase> <phrase role="keyword">true</phrase><phrase role="special">;</phrase> 12530 <phrase role="special">}</phrase> <phrase role="comment">// release mutex</phrase> 12531 <phrase role="identifier">cond</phrase><phrase role="special">.</phrase><phrase role="identifier">notify_one</phrase><phrase role="special">();</phrase> 12532 <phrase role="special">}</phrase> 12533<phrase role="special">};</phrase> 12534</programlisting> 12535 </para> 12536 <para> 12537 The pattern we follow throughout this section is to pass a <ulink url="http://www.cplusplus.com/reference/memory/shared_ptr/"><code><phrase 12538 role="identifier">std</phrase><phrase role="special">::</phrase><phrase 12539 role="identifier">shared_ptr</phrase><phrase role="special"><></phrase></code></ulink> 12540 to the relevant synchronization object to the various tasks' fiber functions. 12541 This eliminates nagging questions about the lifespan of the synchronization 12542 object relative to the last of the fibers. 12543 </para> 12544 <para> 12545 <anchor id="wait_first_simple"/><code><phrase role="identifier">wait_first_simple</phrase><phrase 12546 role="special">()</phrase></code> uses that tactic for <link linkend="wait_done"><code><phrase 12547 role="identifier">Done</phrase></code></link>: 12548 </para> 12549 <para> 12550<programlisting><phrase role="keyword">template</phrase><phrase role="special"><</phrase> <phrase role="keyword">typename</phrase> <phrase role="special">...</phrase> <phrase role="identifier">Fns</phrase> <phrase role="special">></phrase> 12551<phrase role="keyword">void</phrase> <phrase role="identifier">wait_first_simple</phrase><phrase role="special">(</phrase> <phrase role="identifier">Fns</phrase> <phrase role="special">&&</phrase> <phrase role="special">...</phrase> <phrase role="identifier">functions</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase> 12552 <phrase role="comment">// Use shared_ptr because each function's fiber will bind it separately,</phrase> 12553 <phrase role="comment">// and we're going to return before the last of them completes.</phrase> 12554 <phrase role="keyword">auto</phrase> <phrase role="identifier">done</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">make_shared</phrase><phrase role="special"><</phrase> <phrase role="identifier">Done</phrase> <phrase role="special">>()</phrase> <phrase role="special">);</phrase> 12555 <phrase role="identifier">wait_first_simple_impl</phrase><phrase role="special">(</phrase> <phrase role="identifier">done</phrase><phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">forward</phrase><phrase role="special"><</phrase> <phrase role="identifier">Fns</phrase> <phrase role="special">>(</phrase> <phrase role="identifier">functions</phrase><phrase role="special">)</phrase> <phrase role="special">...</phrase> <phrase role="special">);</phrase> 12556 <phrase role="identifier">done</phrase><phrase role="special">-></phrase><phrase role="identifier">wait</phrase><phrase role="special">();</phrase> 12557<phrase role="special">}</phrase> 12558</programlisting> 12559 </para> 12560 <para> 12561 <anchor id="wait_first_simple_impl"/><code><phrase role="identifier">wait_first_simple_impl</phrase><phrase 12562 role="special">()</phrase></code> is an ordinary recursion over the argument 12563 pack, capturing <code><phrase role="identifier">Done</phrase><phrase role="special">::</phrase><phrase 12564 role="identifier">ptr</phrase></code> for each new fiber: 12565 </para> 12566 <para> 12567<programlisting><phrase role="comment">// Degenerate case: when there are no functions to wait for, return</phrase> 12568<phrase role="comment">// immediately.</phrase> 12569<phrase role="keyword">void</phrase> <phrase role="identifier">wait_first_simple_impl</phrase><phrase role="special">(</phrase> <phrase role="identifier">Done</phrase><phrase role="special">::</phrase><phrase role="identifier">ptr</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase> 12570<phrase role="special">}</phrase> 12571 12572<phrase role="comment">// When there's at least one function to wait for, launch it and recur to</phrase> 12573<phrase role="comment">// process the rest.</phrase> 12574<phrase role="keyword">template</phrase><phrase role="special"><</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">></phrase> 12575<phrase role="keyword">void</phrase> <phrase role="identifier">wait_first_simple_impl</phrase><phrase role="special">(</phrase> <phrase role="identifier">Done</phrase><phrase role="special">::</phrase><phrase role="identifier">ptr</phrase> <phrase role="identifier">done</phrase><phrase role="special">,</phrase> <phrase role="identifier">Fn</phrase> <phrase role="special">&&</phrase> <phrase role="identifier">function</phrase><phrase role="special">,</phrase> <phrase role="identifier">Fns</phrase> <phrase role="special">&&</phrase> <phrase role="special">...</phrase> <phrase role="identifier">functions</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase> 12576 <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">fiber</phrase><phrase role="special">(</phrase> <phrase role="special">[</phrase><phrase role="identifier">done</phrase><phrase role="special">,</phrase> <phrase role="identifier">function</phrase><phrase role="special">](){</phrase> 12577 <phrase role="identifier">function</phrase><phrase role="special">();</phrase> 12578 <phrase role="identifier">done</phrase><phrase role="special">-></phrase><phrase role="identifier">notify</phrase><phrase role="special">();</phrase> 12579 <phrase role="special">}).</phrase><phrase role="identifier">detach</phrase><phrase role="special">();</phrase> 12580 <phrase role="identifier">wait_first_simple_impl</phrase><phrase role="special">(</phrase> <phrase role="identifier">done</phrase><phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">forward</phrase><phrase role="special"><</phrase> <phrase role="identifier">Fns</phrase> <phrase role="special">>(</phrase> <phrase role="identifier">functions</phrase><phrase role="special">)</phrase> <phrase role="special">...</phrase> <phrase role="special">);</phrase> 12581<phrase role="special">}</phrase> 12582</programlisting> 12583 </para> 12584 <para> 12585 The body of the fiber's lambda is extremely simple, as promised: call the 12586 function, notify <link linkend="wait_done"><code><phrase role="identifier">Done</phrase></code></link> 12587 when it returns. The first fiber to do so allows <code><phrase role="identifier">wait_first_simple</phrase><phrase 12588 role="special">()</phrase></code> to return — which is why it's useful to 12589 have <code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase 12590 role="identifier">shared_ptr</phrase><phrase role="special"><</phrase><phrase 12591 role="identifier">Done</phrase><phrase role="special">></phrase></code> 12592 manage the lifespan of our <code><phrase role="identifier">Done</phrase></code> 12593 object rather than declaring it as a stack variable in <code><phrase role="identifier">wait_first_simple</phrase><phrase 12594 role="special">()</phrase></code>. 12595 </para> 12596 <para> 12597 This is how you might call it: 12598 </para> 12599 <para> 12600<programlisting><phrase role="identifier">wait_first_simple</phrase><phrase role="special">(</phrase> 12601 <phrase role="special">[](){</phrase> <phrase role="identifier">sleeper</phrase><phrase role="special">(</phrase><phrase role="string">"wfs_long"</phrase><phrase role="special">,</phrase> <phrase role="number">150</phrase><phrase role="special">);</phrase> <phrase role="special">},</phrase> 12602 <phrase role="special">[](){</phrase> <phrase role="identifier">sleeper</phrase><phrase role="special">(</phrase><phrase role="string">"wfs_medium"</phrase><phrase role="special">,</phrase> <phrase role="number">100</phrase><phrase role="special">);</phrase> <phrase role="special">},</phrase> 12603 <phrase role="special">[](){</phrase> <phrase role="identifier">sleeper</phrase><phrase role="special">(</phrase><phrase role="string">"wfs_short"</phrase><phrase role="special">,</phrase> <phrase role="number">50</phrase><phrase role="special">);</phrase> <phrase role="special">});</phrase> 12604</programlisting> 12605 </para> 12606 <para> 12607 In this example, control resumes after <code><phrase role="identifier">wait_first_simple</phrase><phrase 12608 role="special">()</phrase></code> when <link linkend="wait_sleeper"><code><phrase 12609 role="identifier">sleeper</phrase><phrase role="special">(</phrase><phrase 12610 role="string">"wfs_short"</phrase><phrase role="special">,</phrase> 12611 <phrase role="number">50</phrase><phrase role="special">)</phrase></code></link> 12612 completes — even though the other two <code><phrase role="identifier">sleeper</phrase><phrase 12613 role="special">()</phrase></code> fibers are still running. 12614 </para> 12615 </section> 12616 <section id="fiber.when_any.when_any.when_any__return_value"> 12617 <title><link linkend="fiber.when_any.when_any.when_any__return_value">when_any, 12618 return value</link></title> 12619 <para> 12620 It seems more useful to add the ability to capture the return value from 12621 the first of the task functions to complete. Again, we assume that none 12622 will throw an exception. 12623 </para> 12624 <para> 12625 One tactic would be to adapt our <link linkend="wait_done"><code><phrase 12626 role="identifier">Done</phrase></code></link> class to store the first 12627 of the return values, rather than a simple <code><phrase role="keyword">bool</phrase></code>. 12628 However, we choose instead to use a <link linkend="class_buffered_channel"><code>buffered_channel<></code></link>. 12629 We'll only need to enqueue the first value, so we'll <link linkend="buffered_channel_close"><code>buffered_channel::close()</code></link> it 12630 once we've retrieved that value. Subsequent <code><phrase role="identifier">push</phrase><phrase 12631 role="special">()</phrase></code> calls will return <code><phrase role="identifier">closed</phrase></code>. 12632 </para> 12633 <para> 12634 <anchor id="wait_first_value"/> 12635<programlisting><phrase role="comment">// Assume that all passed functions have the same return type. The return type</phrase> 12636<phrase role="comment">// of wait_first_value() is the return type of the first passed function. It is</phrase> 12637<phrase role="comment">// simply invalid to pass NO functions.</phrase> 12638<phrase role="keyword">template</phrase><phrase role="special"><</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">></phrase> 12639<phrase role="keyword">typename</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">result_of</phrase><phrase role="special"><</phrase> <phrase role="identifier">Fn</phrase><phrase role="special">()</phrase> <phrase role="special">>::</phrase><phrase role="identifier">type</phrase> 12640<phrase role="identifier">wait_first_value</phrase><phrase role="special">(</phrase> <phrase role="identifier">Fn</phrase> <phrase role="special">&&</phrase> <phrase role="identifier">function</phrase><phrase role="special">,</phrase> <phrase role="identifier">Fns</phrase> <phrase role="special">&&</phrase> <phrase role="special">...</phrase> <phrase role="identifier">functions</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase> 12641 <phrase role="keyword">typedef</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">result_of</phrase><phrase role="special"><</phrase> <phrase role="identifier">Fn</phrase><phrase role="special">()</phrase> <phrase role="special">>::</phrase><phrase role="identifier">type</phrase> <phrase role="identifier">return_t</phrase><phrase role="special">;</phrase> 12642 <phrase role="keyword">typedef</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">buffered_channel</phrase><phrase role="special"><</phrase> <phrase role="identifier">return_t</phrase> <phrase role="special">></phrase> <phrase role="identifier">channel_t</phrase><phrase role="special">;</phrase> 12643 <phrase role="keyword">auto</phrase> <phrase role="identifier">chanp</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">make_shared</phrase><phrase role="special"><</phrase> <phrase role="identifier">channel_t</phrase> <phrase role="special">>(</phrase> <phrase role="number">64</phrase><phrase role="special">)</phrase> <phrase role="special">);</phrase> 12644 <phrase role="comment">// launch all the relevant fibers</phrase> 12645 <phrase role="identifier">wait_first_value_impl</phrase><phrase role="special"><</phrase> <phrase role="identifier">return_t</phrase> <phrase role="special">>(</phrase> <phrase role="identifier">chanp</phrase><phrase role="special">,</phrase> 12646 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">forward</phrase><phrase role="special"><</phrase> <phrase role="identifier">Fn</phrase> <phrase role="special">>(</phrase> <phrase role="identifier">function</phrase><phrase role="special">),</phrase> 12647 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">forward</phrase><phrase role="special"><</phrase> <phrase role="identifier">Fns</phrase> <phrase role="special">>(</phrase> <phrase role="identifier">functions</phrase><phrase role="special">)</phrase> <phrase role="special">...</phrase> <phrase role="special">);</phrase> 12648 <phrase role="comment">// retrieve the first value</phrase> 12649 <phrase role="identifier">return_t</phrase> <phrase role="identifier">value</phrase><phrase role="special">(</phrase> <phrase role="identifier">chanp</phrase><phrase role="special">-></phrase><phrase role="identifier">value_pop</phrase><phrase role="special">()</phrase> <phrase role="special">);</phrase> 12650 <phrase role="comment">// close the channel: no subsequent push() has to succeed</phrase> 12651 <phrase role="identifier">chanp</phrase><phrase role="special">-></phrase><phrase role="identifier">close</phrase><phrase role="special">();</phrase> 12652 <phrase role="keyword">return</phrase> <phrase role="identifier">value</phrase><phrase role="special">;</phrase> 12653<phrase role="special">}</phrase> 12654</programlisting> 12655 </para> 12656 <para> 12657 <anchor id="wait_first_value_impl"/>The meat of the <code><phrase role="identifier">wait_first_value_impl</phrase><phrase 12658 role="special">()</phrase></code> function is as you might expect: 12659 </para> 12660 <para> 12661<programlisting><phrase role="keyword">template</phrase><phrase role="special"><</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">></phrase> 12662<phrase role="keyword">void</phrase> <phrase role="identifier">wait_first_value_impl</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">shared_ptr</phrase><phrase role="special"><</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">buffered_channel</phrase><phrase role="special"><</phrase> <phrase role="identifier">T</phrase> <phrase role="special">></phrase> <phrase role="special">></phrase> <phrase role="identifier">chan</phrase><phrase role="special">,</phrase> 12663 <phrase role="identifier">Fn</phrase> <phrase role="special">&&</phrase> <phrase role="identifier">function</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase> 12664 <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">fiber</phrase><phrase role="special">(</phrase> <phrase role="special">[</phrase><phrase role="identifier">chan</phrase><phrase role="special">,</phrase> <phrase role="identifier">function</phrase><phrase role="special">](){</phrase> 12665 <phrase role="comment">// Ignore channel_op_status returned by push():</phrase> 12666 <phrase role="comment">// might be closed; we simply don't care.</phrase> 12667 <phrase role="identifier">chan</phrase><phrase role="special">-></phrase><phrase role="identifier">push</phrase><phrase role="special">(</phrase> <phrase role="identifier">function</phrase><phrase role="special">()</phrase> <phrase role="special">);</phrase> 12668 <phrase role="special">}).</phrase><phrase role="identifier">detach</phrase><phrase role="special">();</phrase> 12669<phrase role="special">}</phrase> 12670</programlisting> 12671 </para> 12672 <para> 12673 It calls the passed function, pushes its return value and ignores the 12674 <code><phrase role="identifier">push</phrase><phrase role="special">()</phrase></code> 12675 result. You might call it like this: 12676 </para> 12677 <para> 12678<programlisting><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="identifier">result</phrase> <phrase role="special">=</phrase> <phrase role="identifier">wait_first_value</phrase><phrase role="special">(</phrase> 12679 <phrase role="special">[](){</phrase> <phrase role="keyword">return</phrase> <phrase role="identifier">sleeper</phrase><phrase role="special">(</phrase><phrase role="string">"wfv_third"</phrase><phrase role="special">,</phrase> <phrase role="number">150</phrase><phrase role="special">);</phrase> <phrase role="special">},</phrase> 12680 <phrase role="special">[](){</phrase> <phrase role="keyword">return</phrase> <phrase role="identifier">sleeper</phrase><phrase role="special">(</phrase><phrase role="string">"wfv_second"</phrase><phrase role="special">,</phrase> <phrase role="number">100</phrase><phrase role="special">);</phrase> <phrase role="special">},</phrase> 12681 <phrase role="special">[](){</phrase> <phrase role="keyword">return</phrase> <phrase role="identifier">sleeper</phrase><phrase role="special">(</phrase><phrase role="string">"wfv_first"</phrase><phrase role="special">,</phrase> <phrase role="number">50</phrase><phrase role="special">);</phrase> <phrase role="special">});</phrase> 12682<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cout</phrase> <phrase role="special"><<</phrase> <phrase role="string">"wait_first_value() => "</phrase> <phrase role="special"><<</phrase> <phrase role="identifier">result</phrase> <phrase role="special"><<</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">endl</phrase><phrase role="special">;</phrase> 12683<phrase role="identifier">assert</phrase><phrase role="special">(</phrase><phrase role="identifier">result</phrase> <phrase role="special">==</phrase> <phrase role="string">"wfv_first"</phrase><phrase role="special">);</phrase> 12684</programlisting> 12685 </para> 12686 </section> 12687 <section id="fiber.when_any.when_any.when_any__produce_first_outcome__whether_result_or_exception"> 12688 <title><link linkend="fiber.when_any.when_any.when_any__produce_first_outcome__whether_result_or_exception">when_any, 12689 produce first outcome, whether result or exception</link></title> 12690 <para> 12691 We may not be running in an environment in which we can guarantee no exception 12692 will be thrown by any of our task functions. In that case, the above implementations 12693 of <code><phrase role="identifier">wait_first_something</phrase><phrase 12694 role="special">()</phrase></code> would be naïve: as mentioned in <link 12695 linkend="exceptions">the section on Fiber Management</link>, an uncaught 12696 exception in one of our task fibers would cause <code><phrase role="identifier">std</phrase><phrase 12697 role="special">::</phrase><phrase role="identifier">terminate</phrase><phrase 12698 role="special">()</phrase></code> to be called. 12699 </para> 12700 <para> 12701 Let's at least ensure that such an exception would propagate to the fiber 12702 awaiting the first result. We can use <link linkend="class_future"><code>future<></code></link> to transport 12703 either a return value or an exception. Therefore, we will change <link 12704 linkend="wait_first_value"><code><phrase role="identifier">wait_first_value</phrase><phrase 12705 role="special">()</phrase></code></link>'s <link linkend="class_buffered_channel"><code>buffered_channel<></code></link> to 12706 hold <code><phrase role="identifier">future</phrase><phrase role="special"><</phrase> 12707 <phrase role="identifier">T</phrase> <phrase role="special">></phrase></code> 12708 items instead of simply <code><phrase role="identifier">T</phrase></code>. 12709 </para> 12710 <para> 12711 Once we have a <code><phrase role="identifier">future</phrase><phrase role="special"><></phrase></code> 12712 in hand, all we need do is call <link linkend="future_get"><code>future::get()</code></link>, which will either 12713 return the value or rethrow the exception. 12714 </para> 12715 <para> 12716 <anchor id="wait_first_outcome"/> 12717<programlisting><phrase role="keyword">template</phrase><phrase role="special"><</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">></phrase> 12718<phrase role="keyword">typename</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">result_of</phrase><phrase role="special"><</phrase> <phrase role="identifier">Fn</phrase><phrase role="special">()</phrase> <phrase role="special">>::</phrase><phrase role="identifier">type</phrase> 12719<phrase role="identifier">wait_first_outcome</phrase><phrase role="special">(</phrase> <phrase role="identifier">Fn</phrase> <phrase role="special">&&</phrase> <phrase role="identifier">function</phrase><phrase role="special">,</phrase> <phrase role="identifier">Fns</phrase> <phrase role="special">&&</phrase> <phrase role="special">...</phrase> <phrase role="identifier">functions</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase> 12720 <phrase role="comment">// In this case, the value we pass through the channel is actually a</phrase> 12721 <phrase role="comment">// future -- which is already ready. future can carry either a value or an</phrase> 12722 <phrase role="comment">// exception.</phrase> 12723 <phrase role="keyword">typedef</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">result_of</phrase><phrase role="special"><</phrase> <phrase role="identifier">Fn</phrase><phrase role="special">()</phrase> <phrase role="special">>::</phrase><phrase role="identifier">type</phrase> <phrase role="identifier">return_t</phrase><phrase role="special">;</phrase> 12724 <phrase role="keyword">typedef</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">future</phrase><phrase role="special"><</phrase> <phrase role="identifier">return_t</phrase> <phrase role="special">></phrase> <phrase role="identifier">future_t</phrase><phrase role="special">;</phrase> 12725 <phrase role="keyword">typedef</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">buffered_channel</phrase><phrase role="special"><</phrase> <phrase role="identifier">future_t</phrase> <phrase role="special">></phrase> <phrase role="identifier">channel_t</phrase><phrase role="special">;</phrase> 12726 <phrase role="keyword">auto</phrase> <phrase role="identifier">chanp</phrase><phrase role="special">(</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">make_shared</phrase><phrase role="special"><</phrase> <phrase role="identifier">channel_t</phrase> <phrase role="special">>(</phrase> <phrase role="number">64</phrase><phrase role="special">)</phrase> <phrase role="special">);</phrase> 12727 <phrase role="comment">// launch all the relevant fibers</phrase> 12728 <phrase role="identifier">wait_first_outcome_impl</phrase><phrase role="special"><</phrase> <phrase role="identifier">return_t</phrase> <phrase role="special">>(</phrase> <phrase role="identifier">chanp</phrase><phrase role="special">,</phrase> 12729 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">forward</phrase><phrase role="special"><</phrase> <phrase role="identifier">Fn</phrase> <phrase role="special">>(</phrase> <phrase role="identifier">function</phrase><phrase role="special">),</phrase> 12730 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">forward</phrase><phrase role="special"><</phrase> <phrase role="identifier">Fns</phrase> <phrase role="special">>(</phrase> <phrase role="identifier">functions</phrase><phrase role="special">)</phrase> <phrase role="special">...</phrase> <phrase role="special">);</phrase> 12731 <phrase role="comment">// retrieve the first future</phrase> 12732 <phrase role="identifier">future_t</phrase> <phrase role="identifier">future</phrase><phrase role="special">(</phrase> <phrase role="identifier">chanp</phrase><phrase role="special">-></phrase><phrase role="identifier">value_pop</phrase><phrase role="special">()</phrase> <phrase role="special">);</phrase> 12733 <phrase role="comment">// close the channel: no subsequent push() has to succeed</phrase> 12734 <phrase role="identifier">chanp</phrase><phrase role="special">-></phrase><phrase role="identifier">close</phrase><phrase role="special">();</phrase> 12735 <phrase role="comment">// either return value or throw exception</phrase> 12736 <phrase role="keyword">return</phrase> <phrase role="identifier">future</phrase><phrase role="special">.</phrase><phrase role="identifier">get</phrase><phrase role="special">();</phrase> 12737<phrase role="special">}</phrase> 12738</programlisting> 12739 </para> 12740 <para> 12741 So far so good — but there's a timing issue. How should we obtain the <code><phrase 12742 role="identifier">future</phrase><phrase role="special"><></phrase></code> 12743 to <link linkend="buffered_channel_push"><code>buffered_channel::push()</code></link> on the queue? 12744 </para> 12745 <para> 12746 We could call <link linkend="fibers_async"><code>fibers::async()</code></link>. That would certainly produce 12747 a <code><phrase role="identifier">future</phrase><phrase role="special"><></phrase></code> 12748 for the task function. The trouble is that it would return too quickly! 12749 We only want <code><phrase role="identifier">future</phrase><phrase role="special"><></phrase></code> 12750 items for <emphasis>completed</emphasis> tasks on our <code><phrase role="identifier">queue</phrase><phrase 12751 role="special"><></phrase></code>. In fact, we only want the <code><phrase 12752 role="identifier">future</phrase><phrase role="special"><></phrase></code> 12753 for the one that completes first. If each fiber launched by <code><phrase 12754 role="identifier">wait_first_outcome</phrase><phrase role="special">()</phrase></code> 12755 were to <code><phrase role="identifier">push</phrase><phrase role="special">()</phrase></code> 12756 the result of calling <code><phrase role="identifier">async</phrase><phrase 12757 role="special">()</phrase></code>, the queue would only ever report the 12758 result of the leftmost task item — <emphasis>not</emphasis> the one that 12759 completes most quickly. 12760 </para> 12761 <para> 12762 Calling <link linkend="future_get"><code>future::get()</code></link> on the future returned by <code><phrase 12763 role="identifier">async</phrase><phrase role="special">()</phrase></code> 12764 wouldn't be right. You can only call <code><phrase role="identifier">get</phrase><phrase 12765 role="special">()</phrase></code> once per <code><phrase role="identifier">future</phrase><phrase 12766 role="special"><></phrase></code> instance! And if there were an 12767 exception, it would be rethrown inside the helper fiber at the producer 12768 end of the queue, rather than propagated to the consumer end. 12769 </para> 12770 <para> 12771 We could call <link linkend="future_wait"><code>future::wait()</code></link>. That would block the helper fiber 12772 until the <code><phrase role="identifier">future</phrase><phrase role="special"><></phrase></code> 12773 became ready, at which point we could <code><phrase role="identifier">push</phrase><phrase 12774 role="special">()</phrase></code> it to be retrieved by <code><phrase role="identifier">wait_first_outcome</phrase><phrase 12775 role="special">()</phrase></code>. 12776 </para> 12777 <para> 12778 That would work — but there's a simpler tactic that avoids creating an extra 12779 fiber. We can wrap the task function in a <link linkend="class_packaged_task"><code>packaged_task<></code></link>. 12780 While one naturally thinks of passing a <code><phrase role="identifier">packaged_task</phrase><phrase 12781 role="special"><></phrase></code> to a new fiber — that is, in fact, 12782 what <code><phrase role="identifier">async</phrase><phrase role="special">()</phrase></code> 12783 does — in this case, we're already running in the helper fiber at the producer 12784 end of the queue! We can simply <emphasis>call</emphasis> the <code><phrase 12785 role="identifier">packaged_task</phrase><phrase role="special"><></phrase></code>. 12786 On return from that call, the task function has completed, meaning that 12787 the <code><phrase role="identifier">future</phrase><phrase role="special"><></phrase></code> 12788 obtained from the <code><phrase role="identifier">packaged_task</phrase><phrase 12789 role="special"><></phrase></code> is certain to be ready. At that 12790 point we can simply <code><phrase role="identifier">push</phrase><phrase 12791 role="special">()</phrase></code> it to the queue. 12792 </para> 12793 <para> 12794 <anchor id="wait_first_outcome_impl"/> 12795<programlisting><phrase role="keyword">template</phrase><phrase role="special"><</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">T</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">CHANP</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Fn</phrase> <phrase role="special">></phrase> 12796<phrase role="keyword">void</phrase> <phrase role="identifier">wait_first_outcome_impl</phrase><phrase role="special">(</phrase> <phrase role="identifier">CHANP</phrase> <phrase role="identifier">chan</phrase><phrase role="special">,</phrase> <phrase role="identifier">Fn</phrase> <phrase role="special">&&</phrase> <phrase role="identifier">function</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase> 12797 <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">fiber</phrase><phrase role="special">(</phrase> 12798 <phrase role="comment">// Use std::bind() here for C++11 compatibility. C++11 lambda capture</phrase> 12799 <phrase role="comment">// can't move a move-only Fn type, but bind() can. Let bind() move the</phrase> 12800 <phrase role="comment">// channel pointer and the function into the bound object, passing</phrase> 12801 <phrase role="comment">// references into the lambda.</phrase> 12802 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">bind</phrase><phrase role="special">(</phrase> 12803 <phrase role="special">[](</phrase> <phrase role="identifier">CHANP</phrase> <phrase role="special">&</phrase> <phrase role="identifier">chan</phrase><phrase role="special">,</phrase> 12804 <phrase role="keyword">typename</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">decay</phrase><phrase role="special"><</phrase> <phrase role="identifier">Fn</phrase> <phrase role="special">>::</phrase><phrase role="identifier">type</phrase> <phrase role="special">&</phrase> <phrase role="identifier">function</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase> 12805 <phrase role="comment">// Instantiate a packaged_task to capture any exception thrown by</phrase> 12806 <phrase role="comment">// function.</phrase> 12807 <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">packaged_task</phrase><phrase role="special"><</phrase> <phrase role="identifier">T</phrase><phrase role="special">()</phrase> <phrase role="special">></phrase> <phrase role="identifier">task</phrase><phrase role="special">(</phrase> <phrase role="identifier">function</phrase><phrase role="special">);</phrase> 12808 <phrase role="comment">// Immediately run this packaged_task on same fiber. We want</phrase> 12809 <phrase role="comment">// function() to have completed BEFORE we push the future.</phrase> 12810 <phrase role="identifier">task</phrase><phrase role="special">();</phrase> 12811 <phrase role="comment">// Pass the corresponding future to consumer. Ignore</phrase> 12812 <phrase role="comment">// channel_op_status returned by push(): might be closed; we</phrase> 12813 <phrase role="comment">// simply don't care.</phrase> 12814 <phrase role="identifier">chan</phrase><phrase role="special">-></phrase><phrase role="identifier">push</phrase><phrase role="special">(</phrase> <phrase role="identifier">task</phrase><phrase role="special">.</phrase><phrase role="identifier">get_future</phrase><phrase role="special">()</phrase> <phrase role="special">);</phrase> 12815 <phrase role="special">},</phrase> 12816 <phrase role="identifier">chan</phrase><phrase role="special">,</phrase> 12817 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">forward</phrase><phrase role="special"><</phrase> <phrase role="identifier">Fn</phrase> <phrase role="special">>(</phrase> <phrase role="identifier">function</phrase><phrase role="special">)</phrase> 12818 <phrase role="special">)).</phrase><phrase role="identifier">detach</phrase><phrase role="special">();</phrase> 12819<phrase role="special">}</phrase> 12820</programlisting> 12821 </para> 12822 <para> 12823 Calling it might look like this: 12824 </para> 12825 <para> 12826<programlisting><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="identifier">result</phrase> <phrase role="special">=</phrase> <phrase role="identifier">wait_first_outcome</phrase><phrase role="special">(</phrase> 12827 <phrase role="special">[](){</phrase> <phrase role="keyword">return</phrase> <phrase role="identifier">sleeper</phrase><phrase role="special">(</phrase><phrase role="string">"wfos_first"</phrase><phrase role="special">,</phrase> <phrase role="number">50</phrase><phrase role="special">);</phrase> <phrase role="special">},</phrase> 12828 <phrase role="special">[](){</phrase> <phrase role="keyword">return</phrase> <phrase role="identifier">sleeper</phrase><phrase role="special">(</phrase><phrase role="string">"wfos_second"</phrase><phrase role="special">,</phrase> <phrase role="number">100</phrase><phrase role="special">);</phrase> <phrase role="special">},</phrase> 12829 <phrase role="special">[](){</phrase> <phrase role="keyword">return</phrase> <phrase role="identifier">sleeper</phrase><phrase role="special">(</phrase><phrase role="string">"wfos_third"</phrase><phrase role="special">,</phrase> <phrase role="number">150</phrase><phrase role="special">);</phrase> <phrase role="special">});</phrase> 12830<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cout</phrase> <phrase role="special"><<</phrase> <phrase role="string">"wait_first_outcome(success) => "</phrase> <phrase role="special"><<</phrase> <phrase role="identifier">result</phrase> <phrase role="special"><<</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">endl</phrase><phrase role="special">;</phrase> 12831<phrase role="identifier">assert</phrase><phrase role="special">(</phrase><phrase role="identifier">result</phrase> <phrase role="special">==</phrase> <phrase role="string">"wfos_first"</phrase><phrase role="special">);</phrase> 12832 12833<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="identifier">thrown</phrase><phrase role="special">;</phrase> 12834<phrase role="keyword">try</phrase> <phrase role="special">{</phrase> 12835 <phrase role="identifier">result</phrase> <phrase role="special">=</phrase> <phrase role="identifier">wait_first_outcome</phrase><phrase role="special">(</phrase> 12836 <phrase role="special">[](){</phrase> <phrase role="keyword">return</phrase> <phrase role="identifier">sleeper</phrase><phrase role="special">(</phrase><phrase role="string">"wfof_first"</phrase><phrase role="special">,</phrase> <phrase role="number">50</phrase><phrase role="special">,</phrase> <phrase role="keyword">true</phrase><phrase role="special">);</phrase> <phrase role="special">},</phrase> 12837 <phrase role="special">[](){</phrase> <phrase role="keyword">return</phrase> <phrase role="identifier">sleeper</phrase><phrase role="special">(</phrase><phrase role="string">"wfof_second"</phrase><phrase role="special">,</phrase> <phrase role="number">100</phrase><phrase role="special">);</phrase> <phrase role="special">},</phrase> 12838 <phrase role="special">[](){</phrase> <phrase role="keyword">return</phrase> <phrase role="identifier">sleeper</phrase><phrase role="special">(</phrase><phrase role="string">"wfof_third"</phrase><phrase role="special">,</phrase> <phrase role="number">150</phrase><phrase role="special">);</phrase> <phrase role="special">});</phrase> 12839<phrase role="special">}</phrase> <phrase role="keyword">catch</phrase> <phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">exception</phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">e</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase> 12840 <phrase role="identifier">thrown</phrase> <phrase role="special">=</phrase> <phrase role="identifier">e</phrase><phrase role="special">.</phrase><phrase role="identifier">what</phrase><phrase role="special">();</phrase> 12841<phrase role="special">}</phrase> 12842<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cout</phrase> <phrase role="special"><<</phrase> <phrase role="string">"wait_first_outcome(fail) threw '"</phrase> <phrase role="special"><<</phrase> <phrase role="identifier">thrown</phrase> 12843 <phrase role="special"><<</phrase> <phrase role="string">"'"</phrase> <phrase role="special"><<</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">endl</phrase><phrase role="special">;</phrase> 12844<phrase role="identifier">assert</phrase><phrase role="special">(</phrase><phrase role="identifier">thrown</phrase> <phrase role="special">==</phrase> <phrase role="string">"wfof_first"</phrase><phrase role="special">);</phrase> 12845</programlisting> 12846 </para> 12847 </section> 12848 <section id="fiber.when_any.when_any.when_any__produce_first_success"> 12849 <title><link linkend="fiber.when_any.when_any.when_any__produce_first_success">when_any, 12850 produce first success</link></title> 12851 <para> 12852 One scenario for <quote>when_any</quote> functionality is when we're redundantly 12853 contacting some number of possibly-unreliable web services. Not only might 12854 they be slow — any one of them might produce a failure rather than the desired 12855 result. 12856 </para> 12857 <para> 12858 In such a case, <link linkend="wait_first_outcome"><code><phrase role="identifier">wait_first_outcome</phrase><phrase 12859 role="special">()</phrase></code></link> isn't the right approach. If one 12860 of the services produces an error quickly, while another follows up with 12861 a real answer, we don't want to prefer the error just because it arrived 12862 first! 12863 </para> 12864 <para> 12865 Given the <code><phrase role="identifier">queue</phrase><phrase role="special"><</phrase> 12866 <phrase role="identifier">future</phrase><phrase role="special"><</phrase> 12867 <phrase role="identifier">T</phrase> <phrase role="special">></phrase> 12868 <phrase role="special">></phrase></code> we already constructed for 12869 <code><phrase role="identifier">wait_first_outcome</phrase><phrase role="special">()</phrase></code>, 12870 though, we can readily recast the interface function to deliver the first 12871 <emphasis>successful</emphasis> result. 12872 </para> 12873 <para> 12874 That does beg the question: what if <emphasis>all</emphasis> the task functions 12875 throw an exception? In that case we'd probably better know about it. 12876 </para> 12877 <para> 12878 <anchor id="exception_list"/>The <ulink url="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4407.html#parallel.exceptions.synopsis">C++ 12879 Parallelism Draft Technical Specification</ulink> proposes a <code><phrase 12880 role="identifier">std</phrase><phrase role="special">::</phrase><phrase 12881 role="identifier">exception_list</phrase></code> exception capable of delivering 12882 a collection of <code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase 12883 role="identifier">exception_ptr</phrase></code>s. Until that becomes universally 12884 available, let's fake up an <code><phrase role="identifier">exception_list</phrase></code> 12885 of our own: 12886 </para> 12887 <para> 12888<programlisting><phrase role="keyword">class</phrase> <phrase role="identifier">exception_list</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">runtime_error</phrase> <phrase role="special">{</phrase> 12889<phrase role="keyword">public</phrase><phrase role="special">:</phrase> 12890 <phrase role="identifier">exception_list</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">what</phrase><phrase role="special">)</phrase> <phrase role="special">:</phrase> 12891 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">runtime_error</phrase><phrase role="special">(</phrase> <phrase role="identifier">what</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase> 12892 <phrase role="special">}</phrase> 12893 12894 <phrase role="keyword">typedef</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">vector</phrase><phrase role="special"><</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">exception_ptr</phrase> <phrase role="special">></phrase> <phrase role="identifier">bundle_t</phrase><phrase role="special">;</phrase> 12895 12896 <phrase role="comment">// N4407 proposed std::exception_list API</phrase> 12897 <phrase role="keyword">typedef</phrase> <phrase role="identifier">bundle_t</phrase><phrase role="special">::</phrase><phrase role="identifier">const_iterator</phrase> <phrase role="identifier">iterator</phrase><phrase role="special">;</phrase> 12898 12899 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">size</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase> <phrase role="special">{</phrase> 12900 <phrase role="keyword">return</phrase> <phrase role="identifier">bundle_</phrase><phrase role="special">.</phrase><phrase role="identifier">size</phrase><phrase role="special">();</phrase> 12901 <phrase role="special">}</phrase> 12902 12903 <phrase role="identifier">iterator</phrase> <phrase role="identifier">begin</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase> <phrase role="special">{</phrase> 12904 <phrase role="keyword">return</phrase> <phrase role="identifier">bundle_</phrase><phrase role="special">.</phrase><phrase role="identifier">begin</phrase><phrase role="special">();</phrase> 12905 <phrase role="special">}</phrase> 12906 12907 <phrase role="identifier">iterator</phrase> <phrase role="identifier">end</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase> <phrase role="special">{</phrase> 12908 <phrase role="keyword">return</phrase> <phrase role="identifier">bundle_</phrase><phrase role="special">.</phrase><phrase role="identifier">end</phrase><phrase role="special">();</phrase> 12909 <phrase role="special">}</phrase> 12910 12911 <phrase role="comment">// extension to populate</phrase> 12912 <phrase role="keyword">void</phrase> <phrase role="identifier">add</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">exception_ptr</phrase> <phrase role="identifier">ep</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase> 12913 <phrase role="identifier">bundle_</phrase><phrase role="special">.</phrase><phrase role="identifier">push_back</phrase><phrase role="special">(</phrase> <phrase role="identifier">ep</phrase><phrase role="special">);</phrase> 12914 <phrase role="special">}</phrase> 12915 12916<phrase role="keyword">private</phrase><phrase role="special">:</phrase> 12917 <phrase role="identifier">bundle_t</phrase> <phrase role="identifier">bundle_</phrase><phrase role="special">;</phrase> 12918<phrase role="special">};</phrase> 12919</programlisting> 12920 </para> 12921 <para> 12922 Now we can build <code><phrase role="identifier">wait_first_success</phrase><phrase 12923 role="special">()</phrase></code>, using <link linkend="wait_first_outcome_impl"><code><phrase 12924 role="identifier">wait_first_outcome_impl</phrase><phrase role="special">()</phrase></code></link>. 12925 </para> 12926 <para> 12927 Instead of retrieving only the first <code><phrase role="identifier">future</phrase><phrase 12928 role="special"><></phrase></code> from the queue, we must now loop 12929 over <code><phrase role="identifier">future</phrase><phrase role="special"><></phrase></code> 12930 items. Of course we must limit that iteration! If we launch only <code><phrase 12931 role="identifier">count</phrase></code> producer fibers, the <code><phrase 12932 role="special">(</phrase><phrase role="identifier">count</phrase><phrase 12933 role="special">+</phrase><phrase role="number">1</phrase><phrase role="special">)</phrase></code><superscript>st</superscript> 12934<link linkend="buffered_channel_pop"><code>buffered_channel::pop()</code></link> call 12935 would block forever. 12936 </para> 12937 <para> 12938 Given a ready <code><phrase role="identifier">future</phrase><phrase role="special"><></phrase></code>, 12939 we can distinguish failure by calling <link linkend="future_get_exception_ptr"><code>future::get_exception_ptr()</code></link>. 12940 If the <code><phrase role="identifier">future</phrase><phrase role="special"><></phrase></code> 12941 in fact contains a result rather than an exception, <code><phrase role="identifier">get_exception_ptr</phrase><phrase 12942 role="special">()</phrase></code> returns <code><phrase role="keyword">nullptr</phrase></code>. 12943 In that case, we can confidently call <link linkend="future_get"><code>future::get()</code></link> to return 12944 that result to our caller. 12945 </para> 12946 <para> 12947 If the <code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase 12948 role="identifier">exception_ptr</phrase></code> is <emphasis>not</emphasis> 12949 <code><phrase role="keyword">nullptr</phrase></code>, though, we collect 12950 it into our pending <code><phrase role="identifier">exception_list</phrase></code> 12951 and loop back for the next <code><phrase role="identifier">future</phrase><phrase 12952 role="special"><></phrase></code> from the queue. 12953 </para> 12954 <para> 12955 If we fall out of the loop — if every single task fiber threw an exception 12956 — we throw the <code><phrase role="identifier">exception_list</phrase></code> 12957 exception into which we've been collecting those <code><phrase role="identifier">std</phrase><phrase 12958 role="special">::</phrase><phrase role="identifier">exception_ptr</phrase></code>s. 12959 </para> 12960 <para> 12961 <anchor id="wait_first_success"/> 12962<programlisting><phrase role="keyword">template</phrase><phrase role="special"><</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">></phrase> 12963<phrase role="keyword">typename</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">result_of</phrase><phrase role="special"><</phrase> <phrase role="identifier">Fn</phrase><phrase role="special">()</phrase> <phrase role="special">>::</phrase><phrase role="identifier">type</phrase> 12964<phrase role="identifier">wait_first_success</phrase><phrase role="special">(</phrase> <phrase role="identifier">Fn</phrase> <phrase role="special">&&</phrase> <phrase role="identifier">function</phrase><phrase role="special">,</phrase> <phrase role="identifier">Fns</phrase> <phrase role="special">&&</phrase> <phrase role="special">...</phrase> <phrase role="identifier">functions</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase> 12965 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">count</phrase><phrase role="special">(</phrase> <phrase role="number">1</phrase> <phrase role="special">+</phrase> <phrase role="keyword">sizeof</phrase> <phrase role="special">...</phrase> <phrase role="special">(</phrase> <phrase role="identifier">functions</phrase><phrase role="special">)</phrase> <phrase role="special">);</phrase> 12966 <phrase role="comment">// In this case, the value we pass through the channel is actually a</phrase> 12967 <phrase role="comment">// future -- which is already ready. future can carry either a value or an</phrase> 12968 <phrase role="comment">// exception.</phrase> 12969 <phrase role="keyword">typedef</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">result_of</phrase><phrase role="special"><</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">decay</phrase><phrase role="special"><</phrase> <phrase role="identifier">Fn</phrase> <phrase role="special">>::</phrase><phrase role="identifier">type</phrase><phrase role="special">()</phrase> <phrase role="special">>::</phrase><phrase role="identifier">type</phrase> <phrase role="identifier">return_t</phrase><phrase role="special">;</phrase> 12970 <phrase role="keyword">typedef</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">future</phrase><phrase role="special"><</phrase> <phrase role="identifier">return_t</phrase> <phrase role="special">></phrase> <phrase role="identifier">future_t</phrase><phrase role="special">;</phrase> 12971 <phrase role="keyword">typedef</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">buffered_channel</phrase><phrase role="special"><</phrase> <phrase role="identifier">future_t</phrase> <phrase role="special">></phrase> <phrase role="identifier">channel_t</phrase><phrase role="special">;</phrase> 12972 <phrase role="keyword">auto</phrase> <phrase role="identifier">chanp</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">make_shared</phrase><phrase role="special"><</phrase> <phrase role="identifier">channel_t</phrase> <phrase role="special">>(</phrase> <phrase role="number">64</phrase><phrase role="special">)</phrase> <phrase role="special">);</phrase> 12973 <phrase role="comment">// launch all the relevant fibers</phrase> 12974 <phrase role="identifier">wait_first_outcome_impl</phrase><phrase role="special"><</phrase> <phrase role="identifier">return_t</phrase> <phrase role="special">>(</phrase> <phrase role="identifier">chanp</phrase><phrase role="special">,</phrase> 12975 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">forward</phrase><phrase role="special"><</phrase> <phrase role="identifier">Fn</phrase> <phrase role="special">>(</phrase> <phrase role="identifier">function</phrase><phrase role="special">),</phrase> 12976 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">forward</phrase><phrase role="special"><</phrase> <phrase role="identifier">Fns</phrase> <phrase role="special">>(</phrase> <phrase role="identifier">functions</phrase><phrase role="special">)</phrase> <phrase role="special">...</phrase> <phrase role="special">);</phrase> 12977 <phrase role="comment">// instantiate exception_list, just in case</phrase> 12978 <phrase role="identifier">exception_list</phrase> <phrase role="identifier">exceptions</phrase><phrase role="special">(</phrase><phrase role="string">"wait_first_success() produced only errors"</phrase><phrase role="special">);</phrase> 12979 <phrase role="comment">// retrieve up to 'count' results -- but stop there!</phrase> 12980 <phrase role="keyword">for</phrase> <phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">i</phrase> <phrase role="special">=</phrase> <phrase role="number">0</phrase><phrase role="special">;</phrase> <phrase role="identifier">i</phrase> <phrase role="special"><</phrase> <phrase role="identifier">count</phrase><phrase role="special">;</phrase> <phrase role="special">++</phrase><phrase role="identifier">i</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase> 12981 <phrase role="comment">// retrieve the next future</phrase> 12982 <phrase role="identifier">future_t</phrase> <phrase role="identifier">future</phrase><phrase role="special">(</phrase> <phrase role="identifier">chanp</phrase><phrase role="special">-></phrase><phrase role="identifier">value_pop</phrase><phrase role="special">()</phrase> <phrase role="special">);</phrase> 12983 <phrase role="comment">// retrieve exception_ptr if any</phrase> 12984 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">exception_ptr</phrase> <phrase role="identifier">error</phrase><phrase role="special">(</phrase> <phrase role="identifier">future</phrase><phrase role="special">.</phrase><phrase role="identifier">get_exception_ptr</phrase><phrase role="special">()</phrase> <phrase role="special">);</phrase> 12985 <phrase role="comment">// if no error, then yay, return value</phrase> 12986 <phrase role="keyword">if</phrase> <phrase role="special">(</phrase> <phrase role="special">!</phrase> <phrase role="identifier">error</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase> 12987 <phrase role="comment">// close the channel: no subsequent push() has to succeed</phrase> 12988 <phrase role="identifier">chanp</phrase><phrase role="special">-></phrase><phrase role="identifier">close</phrase><phrase role="special">();</phrase> 12989 <phrase role="comment">// show caller the value we got</phrase> 12990 <phrase role="keyword">return</phrase> <phrase role="identifier">future</phrase><phrase role="special">.</phrase><phrase role="identifier">get</phrase><phrase role="special">();</phrase> 12991 <phrase role="special">}</phrase> 12992 12993 <phrase role="comment">// error is non-null: collect</phrase> 12994 <phrase role="identifier">exceptions</phrase><phrase role="special">.</phrase><phrase role="identifier">add</phrase><phrase role="special">(</phrase> <phrase role="identifier">error</phrase><phrase role="special">);</phrase> 12995 <phrase role="special">}</phrase> 12996 <phrase role="comment">// We only arrive here when every passed function threw an exception.</phrase> 12997 <phrase role="comment">// Throw our collection to inform caller.</phrase> 12998 <phrase role="keyword">throw</phrase> <phrase role="identifier">exceptions</phrase><phrase role="special">;</phrase> 12999<phrase role="special">}</phrase> 13000</programlisting> 13001 </para> 13002 <para> 13003 A call might look like this: 13004 </para> 13005 <para> 13006<programlisting><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="identifier">result</phrase> <phrase role="special">=</phrase> <phrase role="identifier">wait_first_success</phrase><phrase role="special">(</phrase> 13007 <phrase role="special">[](){</phrase> <phrase role="keyword">return</phrase> <phrase role="identifier">sleeper</phrase><phrase role="special">(</phrase><phrase role="string">"wfss_first"</phrase><phrase role="special">,</phrase> <phrase role="number">50</phrase><phrase role="special">,</phrase> <phrase role="keyword">true</phrase><phrase role="special">);</phrase> <phrase role="special">},</phrase> 13008 <phrase role="special">[](){</phrase> <phrase role="keyword">return</phrase> <phrase role="identifier">sleeper</phrase><phrase role="special">(</phrase><phrase role="string">"wfss_second"</phrase><phrase role="special">,</phrase> <phrase role="number">100</phrase><phrase role="special">);</phrase> <phrase role="special">},</phrase> 13009 <phrase role="special">[](){</phrase> <phrase role="keyword">return</phrase> <phrase role="identifier">sleeper</phrase><phrase role="special">(</phrase><phrase role="string">"wfss_third"</phrase><phrase role="special">,</phrase> <phrase role="number">150</phrase><phrase role="special">);</phrase> <phrase role="special">});</phrase> 13010<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cout</phrase> <phrase role="special"><<</phrase> <phrase role="string">"wait_first_success(success) => "</phrase> <phrase role="special"><<</phrase> <phrase role="identifier">result</phrase> <phrase role="special"><<</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">endl</phrase><phrase role="special">;</phrase> 13011<phrase role="identifier">assert</phrase><phrase role="special">(</phrase><phrase role="identifier">result</phrase> <phrase role="special">==</phrase> <phrase role="string">"wfss_second"</phrase><phrase role="special">);</phrase> 13012</programlisting> 13013 </para> 13014 </section> 13015 <section id="fiber.when_any.when_any.when_any__heterogeneous_types"> 13016 <title><link linkend="fiber.when_any.when_any.when_any__heterogeneous_types">when_any, 13017 heterogeneous types</link></title> 13018 <para> 13019 We would be remiss to ignore the case in which the various task functions 13020 have distinct return types. That means that the value returned by the first 13021 of them might have any one of those types. We can express that with <ulink 13022 url="http://www.boost.org/doc/libs/release/doc/html/variant.html">Boost.Variant</ulink>. 13023 </para> 13024 <para> 13025 To keep the example simple, we'll revert to pretending that none of them 13026 can throw an exception. That makes <code><phrase role="identifier">wait_first_value_het</phrase><phrase 13027 role="special">()</phrase></code> strongly resemble <link linkend="wait_first_value"><code><phrase 13028 role="identifier">wait_first_value</phrase><phrase role="special">()</phrase></code></link>. 13029 We can actually reuse <link linkend="wait_first_value_impl"><code><phrase 13030 role="identifier">wait_first_value_impl</phrase><phrase role="special">()</phrase></code></link>, 13031 merely passing <code><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase 13032 role="identifier">variant</phrase><phrase role="special"><</phrase><phrase 13033 role="identifier">T0</phrase><phrase role="special">,</phrase> <phrase 13034 role="identifier">T1</phrase><phrase role="special">,</phrase> <phrase 13035 role="special">...></phrase></code> as the queue's value type rather 13036 than the common <code><phrase role="identifier">T</phrase></code>! 13037 </para> 13038 <para> 13039 Naturally this could be extended to use <link linkend="wait_first_success"><code><phrase 13040 role="identifier">wait_first_success</phrase><phrase role="special">()</phrase></code></link> 13041 semantics instead. 13042 </para> 13043 <para> 13044<programlisting><phrase role="comment">// No need to break out the first Fn for interface function: let the compiler</phrase> 13045<phrase role="comment">// complain if empty.</phrase> 13046<phrase role="comment">// Our functions have different return types, and we might have to return any</phrase> 13047<phrase role="comment">// of them. Use a variant, expanding std::result_of<Fn()>::type for each Fn in</phrase> 13048<phrase role="comment">// parameter pack.</phrase> 13049<phrase role="keyword">template</phrase><phrase role="special"><</phrase> <phrase role="keyword">typename</phrase> <phrase role="special">...</phrase> <phrase role="identifier">Fns</phrase> <phrase role="special">></phrase> 13050<phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">variant</phrase><phrase role="special"><</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">result_of</phrase><phrase role="special"><</phrase> <phrase role="identifier">Fns</phrase><phrase role="special">()</phrase> <phrase role="special">>::</phrase><phrase role="identifier">type</phrase> <phrase role="special">...</phrase> <phrase role="special">></phrase> 13051<phrase role="identifier">wait_first_value_het</phrase><phrase role="special">(</phrase> <phrase role="identifier">Fns</phrase> <phrase role="special">&&</phrase> <phrase role="special">...</phrase> <phrase role="identifier">functions</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase> 13052 <phrase role="comment">// Use buffered_channel<boost::variant<T1, T2, ...>>; see remarks above.</phrase> 13053 <phrase role="keyword">typedef</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">variant</phrase><phrase role="special"><</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">result_of</phrase><phrase role="special"><</phrase> <phrase role="identifier">Fns</phrase><phrase role="special">()</phrase> <phrase role="special">>::</phrase><phrase role="identifier">type</phrase> <phrase role="special">...</phrase> <phrase role="special">></phrase> <phrase role="identifier">return_t</phrase><phrase role="special">;</phrase> 13054 <phrase role="keyword">typedef</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">buffered_channel</phrase><phrase role="special"><</phrase> <phrase role="identifier">return_t</phrase> <phrase role="special">></phrase> <phrase role="identifier">channel_t</phrase><phrase role="special">;</phrase> 13055 <phrase role="keyword">auto</phrase> <phrase role="identifier">chanp</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">make_shared</phrase><phrase role="special"><</phrase> <phrase role="identifier">channel_t</phrase> <phrase role="special">>(</phrase> <phrase role="number">64</phrase><phrase role="special">)</phrase> <phrase role="special">);</phrase> 13056 <phrase role="comment">// launch all the relevant fibers</phrase> 13057 <phrase role="identifier">wait_first_value_impl</phrase><phrase role="special"><</phrase> <phrase role="identifier">return_t</phrase> <phrase role="special">>(</phrase> <phrase role="identifier">chanp</phrase><phrase role="special">,</phrase> 13058 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">forward</phrase><phrase role="special"><</phrase> <phrase role="identifier">Fns</phrase> <phrase role="special">>(</phrase> <phrase role="identifier">functions</phrase><phrase role="special">)</phrase> <phrase role="special">...</phrase> <phrase role="special">);</phrase> 13059 <phrase role="comment">// retrieve the first value</phrase> 13060 <phrase role="identifier">return_t</phrase> <phrase role="identifier">value</phrase><phrase role="special">(</phrase> <phrase role="identifier">chanp</phrase><phrase role="special">-></phrase><phrase role="identifier">value_pop</phrase><phrase role="special">()</phrase> <phrase role="special">);</phrase> 13061 <phrase role="comment">// close the channel: no subsequent push() has to succeed</phrase> 13062 <phrase role="identifier">chanp</phrase><phrase role="special">-></phrase><phrase role="identifier">close</phrase><phrase role="special">();</phrase> 13063 <phrase role="keyword">return</phrase> <phrase role="identifier">value</phrase><phrase role="special">;</phrase> 13064<phrase role="special">}</phrase> 13065</programlisting> 13066 </para> 13067 <para> 13068 It might be called like this: 13069 </para> 13070 <para> 13071<programlisting><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">variant</phrase><phrase role="special"><</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">></phrase> <phrase role="identifier">result</phrase> <phrase role="special">=</phrase> 13072 <phrase role="identifier">wait_first_value_het</phrase><phrase role="special">(</phrase> 13073 <phrase role="special">[](){</phrase> <phrase role="keyword">return</phrase> <phrase role="identifier">sleeper</phrase><phrase role="special">(</phrase><phrase role="string">"wfvh_third"</phrase><phrase role="special">,</phrase> <phrase role="number">150</phrase><phrase role="special">);</phrase> <phrase role="special">},</phrase> 13074 <phrase role="special">[](){</phrase> <phrase role="keyword">return</phrase> <phrase role="identifier">sleeper</phrase><phrase role="special">(</phrase><phrase role="number">3.14</phrase><phrase role="special">,</phrase> <phrase role="number">100</phrase><phrase role="special">);</phrase> <phrase role="special">},</phrase> 13075 <phrase role="special">[](){</phrase> <phrase role="keyword">return</phrase> <phrase role="identifier">sleeper</phrase><phrase role="special">(</phrase><phrase role="number">17</phrase><phrase role="special">,</phrase> <phrase role="number">50</phrase><phrase role="special">);</phrase> <phrase role="special">});</phrase> 13076<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cout</phrase> <phrase role="special"><<</phrase> <phrase role="string">"wait_first_value_het() => "</phrase> <phrase role="special"><<</phrase> <phrase role="identifier">result</phrase> <phrase role="special"><<</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">endl</phrase><phrase role="special">;</phrase> 13077<phrase role="identifier">assert</phrase><phrase role="special">(</phrase><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">get</phrase><phrase role="special"><</phrase> <phrase role="keyword">int</phrase> <phrase role="special">>(</phrase> <phrase role="identifier">result</phrase><phrase role="special">)</phrase> <phrase role="special">==</phrase> <phrase role="number">17</phrase><phrase role="special">);</phrase> 13078</programlisting> 13079 </para> 13080 </section> 13081 <section id="fiber.when_any.when_any.when_any__a_dubious_alternative"> 13082 <title><link linkend="fiber.when_any.when_any.when_any__a_dubious_alternative">when_any, 13083 a dubious alternative</link></title> 13084 <para> 13085 Certain topics in C++ can arouse strong passions, and exceptions are no 13086 exception. We cannot resist mentioning — for purely informational purposes 13087 — that when you need only the <emphasis>first</emphasis> result from some 13088 number of concurrently-running fibers, it would be possible to pass a 13089 <literal>shared_ptr<<link linkend="class_promise"><code>promise<></code></link>></literal> to the 13090 participating fibers, then cause the initiating fiber to call <link linkend="future_get"><code>future::get()</code></link> on 13091 its <link linkend="class_future"><code>future<></code></link>. The first fiber to call <link linkend="promise_set_value"><code>promise::set_value()</code></link> on 13092 that shared <code><phrase role="identifier">promise</phrase></code> will 13093 succeed; subsequent <code><phrase role="identifier">set_value</phrase><phrase 13094 role="special">()</phrase></code> calls on the same <code><phrase role="identifier">promise</phrase></code> 13095 instance will throw <code><phrase role="identifier">future_error</phrase></code>. 13096 </para> 13097 <para> 13098 Use this information at your own discretion. Beware the dark side. 13099 </para> 13100 </section> 13101 </section> 13102 <section id="fiber.when_any.when_all_functionality"> 13103 <title><link linkend="fiber.when_any.when_all_functionality">when_all functionality</link></title> 13104 <section id="fiber.when_any.when_all_functionality.when_all__simple_completion"> 13105 <title><link linkend="fiber.when_any.when_all_functionality.when_all__simple_completion">when_all, 13106 simple completion</link></title> 13107 <para> 13108 For the case in which we must wait for <emphasis>all</emphasis> task functions 13109 to complete — but we don't need results (or expect exceptions) from any of 13110 them — we can write <code><phrase role="identifier">wait_all_simple</phrase><phrase 13111 role="special">()</phrase></code> that looks remarkably like <link linkend="wait_first_simple"><code><phrase 13112 role="identifier">wait_first_simple</phrase><phrase role="special">()</phrase></code></link>. 13113 The difference is that instead of our <link linkend="wait_done"><code><phrase 13114 role="identifier">Done</phrase></code></link> class, we instantiate a <link linkend="class_barrier"><code>barrier</code></link> and 13115 call its <link linkend="barrier_wait"><code>barrier::wait()</code></link>. 13116 </para> 13117 <para> 13118 We initialize the <code><phrase role="identifier">barrier</phrase></code> 13119 with <code><phrase role="special">(</phrase><phrase role="identifier">count</phrase><phrase 13120 role="special">+</phrase><phrase role="number">1</phrase><phrase role="special">)</phrase></code> 13121 because we are launching <code><phrase role="identifier">count</phrase></code> 13122 fibers, plus the <code><phrase role="identifier">wait</phrase><phrase role="special">()</phrase></code> 13123 call within <code><phrase role="identifier">wait_all_simple</phrase><phrase 13124 role="special">()</phrase></code> itself. 13125 </para> 13126 <para> 13127<programlisting><phrase role="keyword">template</phrase><phrase role="special"><</phrase> <phrase role="keyword">typename</phrase> <phrase role="special">...</phrase> <phrase role="identifier">Fns</phrase> <phrase role="special">></phrase> 13128<phrase role="keyword">void</phrase> <phrase role="identifier">wait_all_simple</phrase><phrase role="special">(</phrase> <phrase role="identifier">Fns</phrase> <phrase role="special">&&</phrase> <phrase role="special">...</phrase> <phrase role="identifier">functions</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase> 13129 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">count</phrase><phrase role="special">(</phrase> <phrase role="keyword">sizeof</phrase> <phrase role="special">...</phrase> <phrase role="special">(</phrase> <phrase role="identifier">functions</phrase><phrase role="special">)</phrase> <phrase role="special">);</phrase> 13130 <phrase role="comment">// Initialize a barrier(count+1) because we'll immediately wait on it. We</phrase> 13131 <phrase role="comment">// don't want to wake up until 'count' more fibers wait on it. Even though</phrase> 13132 <phrase role="comment">// we'll stick around until the last of them completes, use shared_ptr</phrase> 13133 <phrase role="comment">// anyway because it's easier to be confident about lifespan issues.</phrase> 13134 <phrase role="keyword">auto</phrase> <phrase role="identifier">barrier</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">make_shared</phrase><phrase role="special"><</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">>(</phrase> <phrase role="identifier">count</phrase> <phrase role="special">+</phrase> <phrase role="number">1</phrase><phrase role="special">)</phrase> <phrase role="special">);</phrase> 13135 <phrase role="identifier">wait_all_simple_impl</phrase><phrase role="special">(</phrase> <phrase role="identifier">barrier</phrase><phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">forward</phrase><phrase role="special"><</phrase> <phrase role="identifier">Fns</phrase> <phrase role="special">>(</phrase> <phrase role="identifier">functions</phrase><phrase role="special">)</phrase> <phrase role="special">...</phrase> <phrase role="special">);</phrase> 13136 <phrase role="identifier">barrier</phrase><phrase role="special">-></phrase><phrase role="identifier">wait</phrase><phrase role="special">();</phrase> 13137<phrase role="special">}</phrase> 13138</programlisting> 13139 </para> 13140 <para> 13141 As stated above, the only difference between <code><phrase role="identifier">wait_all_simple_impl</phrase><phrase 13142 role="special">()</phrase></code> and <link linkend="wait_first_simple_impl"><code><phrase 13143 role="identifier">wait_first_simple_impl</phrase><phrase role="special">()</phrase></code></link> 13144 is that the former calls <code><phrase role="identifier">barrier</phrase><phrase 13145 role="special">::</phrase><phrase role="identifier">wait</phrase><phrase 13146 role="special">()</phrase></code> rather than <code><phrase role="identifier">Done</phrase><phrase 13147 role="special">::</phrase><phrase role="identifier">notify</phrase><phrase 13148 role="special">()</phrase></code>: 13149 </para> 13150 <para> 13151<programlisting><phrase role="keyword">template</phrase><phrase role="special"><</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">></phrase> 13152<phrase role="keyword">void</phrase> <phrase role="identifier">wait_all_simple_impl</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">shared_ptr</phrase><phrase role="special"><</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">></phrase> <phrase role="identifier">barrier</phrase><phrase role="special">,</phrase> 13153 <phrase role="identifier">Fn</phrase> <phrase role="special">&&</phrase> <phrase role="identifier">function</phrase><phrase role="special">,</phrase> <phrase role="identifier">Fns</phrase> <phrase role="special">&&</phrase> <phrase role="special">...</phrase> <phrase role="identifier">functions</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase> 13154 <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">fiber</phrase><phrase role="special">(</phrase> 13155 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">bind</phrase><phrase role="special">(</phrase> 13156 <phrase role="special">[](</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">shared_ptr</phrase><phrase role="special"><</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">></phrase> <phrase role="special">&</phrase> <phrase role="identifier">barrier</phrase><phrase role="special">,</phrase> 13157 <phrase role="keyword">typename</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">decay</phrase><phrase role="special"><</phrase> <phrase role="identifier">Fn</phrase> <phrase role="special">>::</phrase><phrase role="identifier">type</phrase> <phrase role="special">&</phrase> <phrase role="identifier">function</phrase><phrase role="special">)</phrase> <phrase role="keyword">mutable</phrase> <phrase role="special">{</phrase> 13158 <phrase role="identifier">function</phrase><phrase role="special">();</phrase> 13159 <phrase role="identifier">barrier</phrase><phrase role="special">-></phrase><phrase role="identifier">wait</phrase><phrase role="special">();</phrase> 13160 <phrase role="special">},</phrase> 13161 <phrase role="identifier">barrier</phrase><phrase role="special">,</phrase> 13162 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">forward</phrase><phrase role="special"><</phrase> <phrase role="identifier">Fn</phrase> <phrase role="special">>(</phrase> <phrase role="identifier">function</phrase><phrase role="special">)</phrase> 13163 <phrase role="special">)).</phrase><phrase role="identifier">detach</phrase><phrase role="special">();</phrase> 13164 <phrase role="identifier">wait_all_simple_impl</phrase><phrase role="special">(</phrase> <phrase role="identifier">barrier</phrase><phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">forward</phrase><phrase role="special"><</phrase> <phrase role="identifier">Fns</phrase> <phrase role="special">>(</phrase> <phrase role="identifier">functions</phrase><phrase role="special">)</phrase> <phrase role="special">...</phrase> <phrase role="special">);</phrase> 13165<phrase role="special">}</phrase> 13166</programlisting> 13167 </para> 13168 <para> 13169 You might call it like this: 13170 </para> 13171 <para> 13172<programlisting><phrase role="identifier">wait_all_simple</phrase><phrase role="special">(</phrase> 13173 <phrase role="special">[](){</phrase> <phrase role="identifier">sleeper</phrase><phrase role="special">(</phrase><phrase role="string">"was_long"</phrase><phrase role="special">,</phrase> <phrase role="number">150</phrase><phrase role="special">);</phrase> <phrase role="special">},</phrase> 13174 <phrase role="special">[](){</phrase> <phrase role="identifier">sleeper</phrase><phrase role="special">(</phrase><phrase role="string">"was_medium"</phrase><phrase role="special">,</phrase> <phrase role="number">100</phrase><phrase role="special">);</phrase> <phrase role="special">},</phrase> 13175 <phrase role="special">[](){</phrase> <phrase role="identifier">sleeper</phrase><phrase role="special">(</phrase><phrase role="string">"was_short"</phrase><phrase role="special">,</phrase> <phrase role="number">50</phrase><phrase role="special">);</phrase> <phrase role="special">});</phrase> 13176</programlisting> 13177 </para> 13178 <para> 13179 Control will not return from the <code><phrase role="identifier">wait_all_simple</phrase><phrase 13180 role="special">()</phrase></code> call until the last of its task functions 13181 has completed. 13182 </para> 13183 </section> 13184 <section id="fiber.when_any.when_all_functionality.when_all__return_values"> 13185 <title><link linkend="fiber.when_any.when_all_functionality.when_all__return_values">when_all, 13186 return values</link></title> 13187 <para> 13188 As soon as we want to collect return values from all the task functions, 13189 we can see right away how to reuse <link linkend="wait_first_value"><code><phrase 13190 role="identifier">wait_first_value</phrase><phrase role="special">()</phrase></code></link>'s 13191 queue<T> for the purpose. All we have to do is avoid closing it after 13192 the first value! 13193 </para> 13194 <para> 13195 But in fact, collecting multiple values raises an interesting question: 13196 do we <emphasis>really</emphasis> want to wait until the slowest of them 13197 has arrived? Wouldn't we rather process each result as soon as it becomes 13198 available? 13199 </para> 13200 <para> 13201 Fortunately we can present both APIs. Let's define <code><phrase role="identifier">wait_all_values_source</phrase><phrase 13202 role="special">()</phrase></code> to return <code><phrase role="identifier">shared_ptr</phrase><phrase 13203 role="special"><</phrase><phrase role="identifier">buffered_channel</phrase><phrase 13204 role="special"><</phrase><phrase role="identifier">T</phrase><phrase 13205 role="special">>></phrase></code>. 13206 </para> 13207 <para> 13208 <anchor id="wait_all_values"/>Given <code><phrase role="identifier">wait_all_values_source</phrase><phrase 13209 role="special">()</phrase></code>, it's straightforward to implement <code><phrase 13210 role="identifier">wait_all_values</phrase><phrase role="special">()</phrase></code>: 13211 </para> 13212 <para> 13213<programlisting><phrase role="keyword">template</phrase><phrase role="special"><</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">></phrase> 13214<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">vector</phrase><phrase role="special"><</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">result_of</phrase><phrase role="special"><</phrase> <phrase role="identifier">Fn</phrase><phrase role="special">()</phrase> <phrase role="special">>::</phrase><phrase role="identifier">type</phrase> <phrase role="special">></phrase> 13215<phrase role="identifier">wait_all_values</phrase><phrase role="special">(</phrase> <phrase role="identifier">Fn</phrase> <phrase role="special">&&</phrase> <phrase role="identifier">function</phrase><phrase role="special">,</phrase> <phrase role="identifier">Fns</phrase> <phrase role="special">&&</phrase> <phrase role="special">...</phrase> <phrase role="identifier">functions</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase> 13216 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">count</phrase><phrase role="special">(</phrase> <phrase role="number">1</phrase> <phrase role="special">+</phrase> <phrase role="keyword">sizeof</phrase> <phrase role="special">...</phrase> <phrase role="special">(</phrase> <phrase role="identifier">functions</phrase><phrase role="special">)</phrase> <phrase role="special">);</phrase> 13217 <phrase role="keyword">typedef</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">result_of</phrase><phrase role="special"><</phrase> <phrase role="identifier">Fn</phrase><phrase role="special">()</phrase> <phrase role="special">>::</phrase><phrase role="identifier">type</phrase> <phrase role="identifier">return_t</phrase><phrase role="special">;</phrase> 13218 <phrase role="keyword">typedef</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">vector</phrase><phrase role="special"><</phrase> <phrase role="identifier">return_t</phrase> <phrase role="special">></phrase> <phrase role="identifier">vector_t</phrase><phrase role="special">;</phrase> 13219 <phrase role="identifier">vector_t</phrase> <phrase role="identifier">results</phrase><phrase role="special">;</phrase> 13220 <phrase role="identifier">results</phrase><phrase role="special">.</phrase><phrase role="identifier">reserve</phrase><phrase role="special">(</phrase> <phrase role="identifier">count</phrase><phrase role="special">);</phrase> 13221 13222 <phrase role="comment">// get channel</phrase> 13223 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">shared_ptr</phrase><phrase role="special"><</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">buffered_channel</phrase><phrase role="special"><</phrase> <phrase role="identifier">return_t</phrase> <phrase role="special">></phrase> <phrase role="special">></phrase> <phrase role="identifier">chan</phrase> <phrase role="special">=</phrase> 13224 <phrase role="identifier">wait_all_values_source</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">forward</phrase><phrase role="special"><</phrase> <phrase role="identifier">Fn</phrase> <phrase role="special">>(</phrase> <phrase role="identifier">function</phrase><phrase role="special">),</phrase> 13225 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">forward</phrase><phrase role="special"><</phrase> <phrase role="identifier">Fns</phrase> <phrase role="special">>(</phrase> <phrase role="identifier">functions</phrase><phrase role="special">)</phrase> <phrase role="special">...</phrase> <phrase role="special">);</phrase> 13226 <phrase role="comment">// fill results vector</phrase> 13227 <phrase role="identifier">return_t</phrase> <phrase role="identifier">value</phrase><phrase role="special">;</phrase> 13228 <phrase role="keyword">while</phrase> <phrase role="special">(</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">channel_op_status</phrase><phrase role="special">::</phrase><phrase role="identifier">success</phrase> <phrase role="special">==</phrase> <phrase role="identifier">chan</phrase><phrase role="special">-></phrase><phrase role="identifier">pop</phrase><phrase role="special">(</phrase><phrase role="identifier">value</phrase><phrase role="special">)</phrase> <phrase role="special">)</phrase> <phrase role="special">{</phrase> 13229 <phrase role="identifier">results</phrase><phrase role="special">.</phrase><phrase role="identifier">push_back</phrase><phrase role="special">(</phrase> <phrase role="identifier">value</phrase><phrase role="special">);</phrase> 13230 <phrase role="special">}</phrase> 13231 <phrase role="comment">// return vector to caller</phrase> 13232 <phrase role="keyword">return</phrase> <phrase role="identifier">results</phrase><phrase role="special">;</phrase> 13233<phrase role="special">}</phrase> 13234</programlisting> 13235 </para> 13236 <para> 13237 It might be called like this: 13238 </para> 13239 <para> 13240<programlisting><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">vector</phrase><phrase role="special"><</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="special">></phrase> <phrase role="identifier">values</phrase> <phrase role="special">=</phrase> 13241 <phrase role="identifier">wait_all_values</phrase><phrase role="special">(</phrase> 13242 <phrase role="special">[](){</phrase> <phrase role="keyword">return</phrase> <phrase role="identifier">sleeper</phrase><phrase role="special">(</phrase><phrase role="string">"wav_late"</phrase><phrase role="special">,</phrase> <phrase role="number">150</phrase><phrase role="special">);</phrase> <phrase role="special">},</phrase> 13243 <phrase role="special">[](){</phrase> <phrase role="keyword">return</phrase> <phrase role="identifier">sleeper</phrase><phrase role="special">(</phrase><phrase role="string">"wav_middle"</phrase><phrase role="special">,</phrase> <phrase role="number">100</phrase><phrase role="special">);</phrase> <phrase role="special">},</phrase> 13244 <phrase role="special">[](){</phrase> <phrase role="keyword">return</phrase> <phrase role="identifier">sleeper</phrase><phrase role="special">(</phrase><phrase role="string">"wav_early"</phrase><phrase role="special">,</phrase> <phrase role="number">50</phrase><phrase role="special">);</phrase> <phrase role="special">});</phrase> 13245</programlisting> 13246 </para> 13247 <para> 13248 As you can see from the loop in <code><phrase role="identifier">wait_all_values</phrase><phrase 13249 role="special">()</phrase></code>, instead of requiring its caller to count 13250 values, we define <code><phrase role="identifier">wait_all_values_source</phrase><phrase 13251 role="special">()</phrase></code> to <link linkend="buffered_channel_close"><code>buffered_channel::close()</code></link> the 13252 queue when done. But how do we do that? Each producer fiber is independent. 13253 It has no idea whether it is the last one to <link linkend="buffered_channel_push"><code>buffered_channel::push()</code></link> a 13254 value. 13255 </para> 13256 <para> 13257 <anchor id="wait_nqueue"/>We can address that problem with a counting façade 13258 for the <code><phrase role="identifier">queue</phrase><phrase role="special"><></phrase></code>. 13259 In fact, our façade need only support the producer end of the queue. 13260 </para> 13261 <para> 13262 [wait_nqueue] 13263 </para> 13264 <para> 13265 <anchor id="wait_all_values_source"/>Armed with <code><phrase role="identifier">nqueue</phrase><phrase 13266 role="special"><></phrase></code>, we can implement <code><phrase 13267 role="identifier">wait_all_values_source</phrase><phrase role="special">()</phrase></code>. 13268 It starts just like <link linkend="wait_first_value"><code><phrase role="identifier">wait_first_value</phrase><phrase 13269 role="special">()</phrase></code></link>. The difference is that we wrap 13270 the <code><phrase role="identifier">queue</phrase><phrase role="special"><</phrase><phrase 13271 role="identifier">T</phrase><phrase role="special">></phrase></code> 13272 with an <code><phrase role="identifier">nqueue</phrase><phrase role="special"><</phrase><phrase 13273 role="identifier">T</phrase><phrase role="special">></phrase></code> 13274 to pass to the producer fibers. 13275 </para> 13276 <para> 13277 Then, of course, instead of popping the first value, closing the queue 13278 and returning it, we simply return the <code><phrase role="identifier">shared_ptr</phrase><phrase 13279 role="special"><</phrase><phrase role="identifier">queue</phrase><phrase 13280 role="special"><</phrase><phrase role="identifier">T</phrase><phrase 13281 role="special">>></phrase></code>. 13282 </para> 13283 <para> 13284<programlisting><phrase role="comment">// Return a shared_ptr<buffered_channel<T>> from which the caller can</phrase> 13285<phrase role="comment">// retrieve each new result as it arrives, until 'closed'.</phrase> 13286<phrase role="keyword">template</phrase><phrase role="special"><</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">></phrase> 13287<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">shared_ptr</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">buffered_channel</phrase><phrase role="special"><</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">result_of</phrase><phrase role="special"><</phrase> <phrase role="identifier">Fn</phrase><phrase role="special">()</phrase> <phrase role="special">>::</phrase><phrase role="identifier">type</phrase> <phrase role="special">></phrase> <phrase role="special">></phrase> 13288<phrase role="identifier">wait_all_values_source</phrase><phrase role="special">(</phrase> <phrase role="identifier">Fn</phrase> <phrase role="special">&&</phrase> <phrase role="identifier">function</phrase><phrase role="special">,</phrase> <phrase role="identifier">Fns</phrase> <phrase role="special">&&</phrase> <phrase role="special">...</phrase> <phrase role="identifier">functions</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase> 13289 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">count</phrase><phrase role="special">(</phrase> <phrase role="number">1</phrase> <phrase role="special">+</phrase> <phrase role="keyword">sizeof</phrase> <phrase role="special">...</phrase> <phrase role="special">(</phrase> <phrase role="identifier">functions</phrase><phrase role="special">)</phrase> <phrase role="special">);</phrase> 13290 <phrase role="keyword">typedef</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">result_of</phrase><phrase role="special"><</phrase> <phrase role="identifier">Fn</phrase><phrase role="special">()</phrase> <phrase role="special">>::</phrase><phrase role="identifier">type</phrase> <phrase role="identifier">return_t</phrase><phrase role="special">;</phrase> 13291 <phrase role="keyword">typedef</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">buffered_channel</phrase><phrase role="special"><</phrase> <phrase role="identifier">return_t</phrase> <phrase role="special">></phrase> <phrase role="identifier">channel_t</phrase><phrase role="special">;</phrase> 13292 <phrase role="comment">// make the channel</phrase> 13293 <phrase role="keyword">auto</phrase> <phrase role="identifier">chanp</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">make_shared</phrase><phrase role="special"><</phrase> <phrase role="identifier">channel_t</phrase> <phrase role="special">>(</phrase> <phrase role="number">64</phrase><phrase role="special">)</phrase> <phrase role="special">);</phrase> 13294 <phrase role="comment">// and make an nchannel facade to close it after 'count' items</phrase> 13295 <phrase role="keyword">auto</phrase> <phrase role="identifier">ncp</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">make_shared</phrase><phrase role="special"><</phrase> <phrase role="identifier">nchannel</phrase><phrase role="special"><</phrase> <phrase role="identifier">return_t</phrase> <phrase role="special">></phrase> <phrase role="special">>(</phrase> <phrase role="identifier">chanp</phrase><phrase role="special">,</phrase> <phrase role="identifier">count</phrase><phrase role="special">)</phrase> <phrase role="special">);</phrase> 13296 <phrase role="comment">// pass that nchannel facade to all the relevant fibers</phrase> 13297 <phrase role="identifier">wait_all_values_impl</phrase><phrase role="special"><</phrase> <phrase role="identifier">return_t</phrase> <phrase role="special">>(</phrase> <phrase role="identifier">ncp</phrase><phrase role="special">,</phrase> 13298 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">forward</phrase><phrase role="special"><</phrase> <phrase role="identifier">Fn</phrase> <phrase role="special">>(</phrase> <phrase role="identifier">function</phrase><phrase role="special">),</phrase> 13299 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">forward</phrase><phrase role="special"><</phrase> <phrase role="identifier">Fns</phrase> <phrase role="special">>(</phrase> <phrase role="identifier">functions</phrase><phrase role="special">)</phrase> <phrase role="special">...</phrase> <phrase role="special">);</phrase> 13300 <phrase role="comment">// then return the channel for consumer</phrase> 13301 <phrase role="keyword">return</phrase> <phrase role="identifier">chanp</phrase><phrase role="special">;</phrase> 13302<phrase role="special">}</phrase> 13303</programlisting> 13304 </para> 13305 <para> 13306 For example: 13307 </para> 13308 <para> 13309<programlisting><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">shared_ptr</phrase><phrase role="special"><</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">buffered_channel</phrase><phrase role="special"><</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="special">></phrase> <phrase role="special">></phrase> <phrase role="identifier">chan</phrase> <phrase role="special">=</phrase> 13310 <phrase role="identifier">wait_all_values_source</phrase><phrase role="special">(</phrase> 13311 <phrase role="special">[](){</phrase> <phrase role="keyword">return</phrase> <phrase role="identifier">sleeper</phrase><phrase role="special">(</phrase><phrase role="string">"wavs_third"</phrase><phrase role="special">,</phrase> <phrase role="number">150</phrase><phrase role="special">);</phrase> <phrase role="special">},</phrase> 13312 <phrase role="special">[](){</phrase> <phrase role="keyword">return</phrase> <phrase role="identifier">sleeper</phrase><phrase role="special">(</phrase><phrase role="string">"wavs_second"</phrase><phrase role="special">,</phrase> <phrase role="number">100</phrase><phrase role="special">);</phrase> <phrase role="special">},</phrase> 13313 <phrase role="special">[](){</phrase> <phrase role="keyword">return</phrase> <phrase role="identifier">sleeper</phrase><phrase role="special">(</phrase><phrase role="string">"wavs_first"</phrase><phrase role="special">,</phrase> <phrase role="number">50</phrase><phrase role="special">);</phrase> <phrase role="special">});</phrase> 13314<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="identifier">value</phrase><phrase role="special">;</phrase> 13315<phrase role="keyword">while</phrase> <phrase role="special">(</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">channel_op_status</phrase><phrase role="special">::</phrase><phrase role="identifier">success</phrase> <phrase role="special">==</phrase> <phrase role="identifier">chan</phrase><phrase role="special">-></phrase><phrase role="identifier">pop</phrase><phrase role="special">(</phrase><phrase role="identifier">value</phrase><phrase role="special">)</phrase> <phrase role="special">)</phrase> <phrase role="special">{</phrase> 13316 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cout</phrase> <phrase role="special"><<</phrase> <phrase role="string">"wait_all_values_source() => '"</phrase> <phrase role="special"><<</phrase> <phrase role="identifier">value</phrase> 13317 <phrase role="special"><<</phrase> <phrase role="string">"'"</phrase> <phrase role="special"><<</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">endl</phrase><phrase role="special">;</phrase> 13318<phrase role="special">}</phrase> 13319</programlisting> 13320 </para> 13321 <para> 13322 <anchor id="wait_all_values_impl"/><code><phrase role="identifier">wait_all_values_impl</phrase><phrase 13323 role="special">()</phrase></code> really is just like <link linkend="wait_first_value_impl"><code><phrase 13324 role="identifier">wait_first_value_impl</phrase><phrase role="special">()</phrase></code></link> 13325 except for the use of <code><phrase role="identifier">nqueue</phrase><phrase 13326 role="special"><</phrase><phrase role="identifier">T</phrase><phrase 13327 role="special">></phrase></code> rather than <code><phrase role="identifier">queue</phrase><phrase 13328 role="special"><</phrase><phrase role="identifier">T</phrase><phrase 13329 role="special">></phrase></code>: 13330 </para> 13331 <para> 13332<programlisting><phrase role="keyword">template</phrase><phrase role="special"><</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">></phrase> 13333<phrase role="keyword">void</phrase> <phrase role="identifier">wait_all_values_impl</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">shared_ptr</phrase><phrase role="special"><</phrase> <phrase role="identifier">nchannel</phrase><phrase role="special"><</phrase> <phrase role="identifier">T</phrase> <phrase role="special">></phrase> <phrase role="special">></phrase> <phrase role="identifier">chan</phrase><phrase role="special">,</phrase> 13334 <phrase role="identifier">Fn</phrase> <phrase role="special">&&</phrase> <phrase role="identifier">function</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase> 13335 <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">fiber</phrase><phrase role="special">(</phrase> <phrase role="special">[</phrase><phrase role="identifier">chan</phrase><phrase role="special">,</phrase> <phrase role="identifier">function</phrase><phrase role="special">](){</phrase> 13336 <phrase role="identifier">chan</phrase><phrase role="special">-></phrase><phrase role="identifier">push</phrase><phrase role="special">(</phrase><phrase role="identifier">function</phrase><phrase role="special">());</phrase> 13337 <phrase role="special">}).</phrase><phrase role="identifier">detach</phrase><phrase role="special">();</phrase> 13338<phrase role="special">}</phrase> 13339</programlisting> 13340 </para> 13341 </section> 13342 <section id="fiber.when_any.when_all_functionality.when_all_until_first_exception"> 13343 <title><link linkend="fiber.when_any.when_all_functionality.when_all_until_first_exception">when_all 13344 until first exception</link></title> 13345 <para> 13346 Naturally, just as with <link linkend="wait_first_outcome"><code><phrase 13347 role="identifier">wait_first_outcome</phrase><phrase role="special">()</phrase></code></link>, 13348 we can elaborate <link linkend="wait_all_values"><code><phrase role="identifier">wait_all_values</phrase><phrase 13349 role="special">()</phrase></code></link> and <link linkend="wait_all_values_source"><code><phrase 13350 role="identifier">wait_all_values_source</phrase><phrase role="special">()</phrase></code></link> 13351 by passing <code><phrase role="identifier">future</phrase><phrase role="special"><</phrase> 13352 <phrase role="identifier">T</phrase> <phrase role="special">></phrase></code> 13353 instead of plain <code><phrase role="identifier">T</phrase></code>. 13354 </para> 13355 <para> 13356 <anchor id="wait_all_until_error"/><code><phrase role="identifier">wait_all_until_error</phrase><phrase 13357 role="special">()</phrase></code> pops that <code><phrase role="identifier">future</phrase><phrase 13358 role="special"><</phrase> <phrase role="identifier">T</phrase> <phrase 13359 role="special">></phrase></code> and calls its <link linkend="future_get"><code>future::get()</code></link>: 13360 </para> 13361 <para> 13362<programlisting><phrase role="keyword">template</phrase><phrase role="special"><</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">></phrase> 13363<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">vector</phrase><phrase role="special"><</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">result_of</phrase><phrase role="special"><</phrase> <phrase role="identifier">Fn</phrase><phrase role="special">()</phrase> <phrase role="special">>::</phrase><phrase role="identifier">type</phrase> <phrase role="special">></phrase> 13364<phrase role="identifier">wait_all_until_error</phrase><phrase role="special">(</phrase> <phrase role="identifier">Fn</phrase> <phrase role="special">&&</phrase> <phrase role="identifier">function</phrase><phrase role="special">,</phrase> <phrase role="identifier">Fns</phrase> <phrase role="special">&&</phrase> <phrase role="special">...</phrase> <phrase role="identifier">functions</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase> 13365 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">count</phrase><phrase role="special">(</phrase> <phrase role="number">1</phrase> <phrase role="special">+</phrase> <phrase role="keyword">sizeof</phrase> <phrase role="special">...</phrase> <phrase role="special">(</phrase> <phrase role="identifier">functions</phrase><phrase role="special">)</phrase> <phrase role="special">);</phrase> 13366 <phrase role="keyword">typedef</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">result_of</phrase><phrase role="special"><</phrase> <phrase role="identifier">Fn</phrase><phrase role="special">()</phrase> <phrase role="special">>::</phrase><phrase role="identifier">type</phrase> <phrase role="identifier">return_t</phrase><phrase role="special">;</phrase> 13367 <phrase role="keyword">typedef</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">future</phrase><phrase role="special"><</phrase> <phrase role="identifier">return_t</phrase> <phrase role="special">></phrase> <phrase role="identifier">future_t</phrase><phrase role="special">;</phrase> 13368 <phrase role="keyword">typedef</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">vector</phrase><phrase role="special"><</phrase> <phrase role="identifier">return_t</phrase> <phrase role="special">></phrase> <phrase role="identifier">vector_t</phrase><phrase role="special">;</phrase> 13369 <phrase role="identifier">vector_t</phrase> <phrase role="identifier">results</phrase><phrase role="special">;</phrase> 13370 <phrase role="identifier">results</phrase><phrase role="special">.</phrase><phrase role="identifier">reserve</phrase><phrase role="special">(</phrase> <phrase role="identifier">count</phrase><phrase role="special">);</phrase> 13371 13372 <phrase role="comment">// get channel</phrase> 13373 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">shared_ptr</phrase><phrase role="special"><</phrase> 13374 <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">buffered_channel</phrase><phrase role="special"><</phrase> <phrase role="identifier">future_t</phrase> <phrase role="special">></phrase> <phrase role="special">></phrase> <phrase role="identifier">chan</phrase><phrase role="special">(</phrase> 13375 <phrase role="identifier">wait_all_until_error_source</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">forward</phrase><phrase role="special"><</phrase> <phrase role="identifier">Fn</phrase> <phrase role="special">>(</phrase> <phrase role="identifier">function</phrase><phrase role="special">),</phrase> 13376 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">forward</phrase><phrase role="special"><</phrase> <phrase role="identifier">Fns</phrase> <phrase role="special">>(</phrase> <phrase role="identifier">functions</phrase><phrase role="special">)</phrase> <phrase role="special">...</phrase> <phrase role="special">)</phrase> <phrase role="special">);</phrase> 13377 <phrase role="comment">// fill results vector</phrase> 13378 <phrase role="identifier">future_t</phrase> <phrase role="identifier">future</phrase><phrase role="special">;</phrase> 13379 <phrase role="keyword">while</phrase> <phrase role="special">(</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">channel_op_status</phrase><phrase role="special">::</phrase><phrase role="identifier">success</phrase> <phrase role="special">==</phrase> <phrase role="identifier">chan</phrase><phrase role="special">-></phrase><phrase role="identifier">pop</phrase><phrase role="special">(</phrase> <phrase role="identifier">future</phrase><phrase role="special">)</phrase> <phrase role="special">)</phrase> <phrase role="special">{</phrase> 13380 <phrase role="identifier">results</phrase><phrase role="special">.</phrase><phrase role="identifier">push_back</phrase><phrase role="special">(</phrase> <phrase role="identifier">future</phrase><phrase role="special">.</phrase><phrase role="identifier">get</phrase><phrase role="special">()</phrase> <phrase role="special">);</phrase> 13381 <phrase role="special">}</phrase> 13382 <phrase role="comment">// return vector to caller</phrase> 13383 <phrase role="keyword">return</phrase> <phrase role="identifier">results</phrase><phrase role="special">;</phrase> 13384<phrase role="special">}</phrase> 13385</programlisting> 13386 </para> 13387 <para> 13388 For example: 13389 </para> 13390 <para> 13391<programlisting><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="identifier">thrown</phrase><phrase role="special">;</phrase> 13392<phrase role="keyword">try</phrase> <phrase role="special">{</phrase> 13393 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">vector</phrase><phrase role="special"><</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="special">></phrase> <phrase role="identifier">values</phrase> <phrase role="special">=</phrase> <phrase role="identifier">wait_all_until_error</phrase><phrase role="special">(</phrase> 13394 <phrase role="special">[](){</phrase> <phrase role="keyword">return</phrase> <phrase role="identifier">sleeper</phrase><phrase role="special">(</phrase><phrase role="string">"waue_late"</phrase><phrase role="special">,</phrase> <phrase role="number">150</phrase><phrase role="special">);</phrase> <phrase role="special">},</phrase> 13395 <phrase role="special">[](){</phrase> <phrase role="keyword">return</phrase> <phrase role="identifier">sleeper</phrase><phrase role="special">(</phrase><phrase role="string">"waue_middle"</phrase><phrase role="special">,</phrase> <phrase role="number">100</phrase><phrase role="special">,</phrase> <phrase role="keyword">true</phrase><phrase role="special">);</phrase> <phrase role="special">},</phrase> 13396 <phrase role="special">[](){</phrase> <phrase role="keyword">return</phrase> <phrase role="identifier">sleeper</phrase><phrase role="special">(</phrase><phrase role="string">"waue_early"</phrase><phrase role="special">,</phrase> <phrase role="number">50</phrase><phrase role="special">);</phrase> <phrase role="special">});</phrase> 13397<phrase role="special">}</phrase> <phrase role="keyword">catch</phrase> <phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">exception</phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">e</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase> 13398 <phrase role="identifier">thrown</phrase> <phrase role="special">=</phrase> <phrase role="identifier">e</phrase><phrase role="special">.</phrase><phrase role="identifier">what</phrase><phrase role="special">();</phrase> 13399<phrase role="special">}</phrase> 13400<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cout</phrase> <phrase role="special"><<</phrase> <phrase role="string">"wait_all_until_error(fail) threw '"</phrase> <phrase role="special"><<</phrase> <phrase role="identifier">thrown</phrase> 13401 <phrase role="special"><<</phrase> <phrase role="string">"'"</phrase> <phrase role="special"><<</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">endl</phrase><phrase role="special">;</phrase> 13402</programlisting> 13403 </para> 13404 <para> 13405 <anchor id="wait_all_until_error_source"/>Naturally this complicates the 13406 API for <code><phrase role="identifier">wait_all_until_error_source</phrase><phrase 13407 role="special">()</phrase></code>. The caller must both retrieve a <code><phrase 13408 role="identifier">future</phrase><phrase role="special"><</phrase> 13409 <phrase role="identifier">T</phrase> <phrase role="special">></phrase></code> 13410 and call its <code><phrase role="identifier">get</phrase><phrase role="special">()</phrase></code> 13411 method. It would, of course, be possible to return a façade over the consumer 13412 end of the queue that would implicitly perform the <code><phrase role="identifier">get</phrase><phrase 13413 role="special">()</phrase></code> and return a simple <code><phrase role="identifier">T</phrase></code> 13414 (or throw). 13415 </para> 13416 <para> 13417 The implementation is just as you would expect. Notice, however, that we 13418 can reuse <link linkend="wait_first_outcome_impl"><code><phrase role="identifier">wait_first_outcome_impl</phrase><phrase 13419 role="special">()</phrase></code></link>, passing the <code><phrase role="identifier">nqueue</phrase><phrase 13420 role="special"><</phrase><phrase role="identifier">T</phrase><phrase 13421 role="special">></phrase></code> rather than <code><phrase role="identifier">queue</phrase><phrase 13422 role="special"><</phrase><phrase role="identifier">T</phrase><phrase 13423 role="special">></phrase></code>. 13424 </para> 13425 <para> 13426<programlisting><phrase role="comment">// Return a shared_ptr<buffered_channel<future<T>>> from which the caller can</phrase> 13427<phrase role="comment">// get() each new result as it arrives, until 'closed'.</phrase> 13428<phrase role="keyword">template</phrase><phrase role="special"><</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">></phrase> 13429<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">shared_ptr</phrase><phrase role="special"><</phrase> 13430 <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">buffered_channel</phrase><phrase role="special"><</phrase> 13431 <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">future</phrase><phrase role="special"><</phrase> 13432 <phrase role="keyword">typename</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">result_of</phrase><phrase role="special"><</phrase> <phrase role="identifier">Fn</phrase><phrase role="special">()</phrase> <phrase role="special">>::</phrase><phrase role="identifier">type</phrase> <phrase role="special">></phrase> <phrase role="special">></phrase> <phrase role="special">></phrase> 13433<phrase role="identifier">wait_all_until_error_source</phrase><phrase role="special">(</phrase> <phrase role="identifier">Fn</phrase> <phrase role="special">&&</phrase> <phrase role="identifier">function</phrase><phrase role="special">,</phrase> <phrase role="identifier">Fns</phrase> <phrase role="special">&&</phrase> <phrase role="special">...</phrase> <phrase role="identifier">functions</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase> 13434 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">count</phrase><phrase role="special">(</phrase> <phrase role="number">1</phrase> <phrase role="special">+</phrase> <phrase role="keyword">sizeof</phrase> <phrase role="special">...</phrase> <phrase role="special">(</phrase> <phrase role="identifier">functions</phrase><phrase role="special">)</phrase> <phrase role="special">);</phrase> 13435 <phrase role="keyword">typedef</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">result_of</phrase><phrase role="special"><</phrase> <phrase role="identifier">Fn</phrase><phrase role="special">()</phrase> <phrase role="special">>::</phrase><phrase role="identifier">type</phrase> <phrase role="identifier">return_t</phrase><phrase role="special">;</phrase> 13436 <phrase role="keyword">typedef</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">future</phrase><phrase role="special"><</phrase> <phrase role="identifier">return_t</phrase> <phrase role="special">></phrase> <phrase role="identifier">future_t</phrase><phrase role="special">;</phrase> 13437 <phrase role="keyword">typedef</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">buffered_channel</phrase><phrase role="special"><</phrase> <phrase role="identifier">future_t</phrase> <phrase role="special">></phrase> <phrase role="identifier">channel_t</phrase><phrase role="special">;</phrase> 13438 <phrase role="comment">// make the channel</phrase> 13439 <phrase role="keyword">auto</phrase> <phrase role="identifier">chanp</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">make_shared</phrase><phrase role="special"><</phrase> <phrase role="identifier">channel_t</phrase> <phrase role="special">>(</phrase> <phrase role="number">64</phrase><phrase role="special">)</phrase> <phrase role="special">);</phrase> 13440 <phrase role="comment">// and make an nchannel facade to close it after 'count' items</phrase> 13441 <phrase role="keyword">auto</phrase> <phrase role="identifier">ncp</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">make_shared</phrase><phrase role="special"><</phrase> <phrase role="identifier">nchannel</phrase><phrase role="special"><</phrase> <phrase role="identifier">future_t</phrase> <phrase role="special">></phrase> <phrase role="special">>(</phrase> <phrase role="identifier">chanp</phrase><phrase role="special">,</phrase> <phrase role="identifier">count</phrase><phrase role="special">)</phrase> <phrase role="special">);</phrase> 13442 <phrase role="comment">// pass that nchannel facade to all the relevant fibers</phrase> 13443 <phrase role="identifier">wait_first_outcome_impl</phrase><phrase role="special"><</phrase> <phrase role="identifier">return_t</phrase> <phrase role="special">>(</phrase> <phrase role="identifier">ncp</phrase><phrase role="special">,</phrase> 13444 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">forward</phrase><phrase role="special"><</phrase> <phrase role="identifier">Fn</phrase> <phrase role="special">>(</phrase> <phrase role="identifier">function</phrase><phrase role="special">),</phrase> 13445 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">forward</phrase><phrase role="special"><</phrase> <phrase role="identifier">Fns</phrase> <phrase role="special">>(</phrase> <phrase role="identifier">functions</phrase><phrase role="special">)</phrase> <phrase role="special">...</phrase> <phrase role="special">);</phrase> 13446 <phrase role="comment">// then return the channel for consumer</phrase> 13447 <phrase role="keyword">return</phrase> <phrase role="identifier">chanp</phrase><phrase role="special">;</phrase> 13448<phrase role="special">}</phrase> 13449</programlisting> 13450 </para> 13451 <para> 13452 For example: 13453 </para> 13454 <para> 13455<programlisting><phrase role="keyword">typedef</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">future</phrase><phrase role="special"><</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="special">></phrase> <phrase role="identifier">future_t</phrase><phrase role="special">;</phrase> 13456<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">shared_ptr</phrase><phrase role="special"><</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">buffered_channel</phrase><phrase role="special"><</phrase> <phrase role="identifier">future_t</phrase> <phrase role="special">></phrase> <phrase role="special">></phrase> <phrase role="identifier">chan</phrase> <phrase role="special">=</phrase> 13457 <phrase role="identifier">wait_all_until_error_source</phrase><phrase role="special">(</phrase> 13458 <phrase role="special">[](){</phrase> <phrase role="keyword">return</phrase> <phrase role="identifier">sleeper</phrase><phrase role="special">(</phrase><phrase role="string">"wauess_third"</phrase><phrase role="special">,</phrase> <phrase role="number">150</phrase><phrase role="special">);</phrase> <phrase role="special">},</phrase> 13459 <phrase role="special">[](){</phrase> <phrase role="keyword">return</phrase> <phrase role="identifier">sleeper</phrase><phrase role="special">(</phrase><phrase role="string">"wauess_second"</phrase><phrase role="special">,</phrase> <phrase role="number">100</phrase><phrase role="special">);</phrase> <phrase role="special">},</phrase> 13460 <phrase role="special">[](){</phrase> <phrase role="keyword">return</phrase> <phrase role="identifier">sleeper</phrase><phrase role="special">(</phrase><phrase role="string">"wauess_first"</phrase><phrase role="special">,</phrase> <phrase role="number">50</phrase><phrase role="special">);</phrase> <phrase role="special">});</phrase> 13461<phrase role="identifier">future_t</phrase> <phrase role="identifier">future</phrase><phrase role="special">;</phrase> 13462<phrase role="keyword">while</phrase> <phrase role="special">(</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">channel_op_status</phrase><phrase role="special">::</phrase><phrase role="identifier">success</phrase> <phrase role="special">==</phrase> <phrase role="identifier">chan</phrase><phrase role="special">-></phrase><phrase role="identifier">pop</phrase><phrase role="special">(</phrase> <phrase role="identifier">future</phrase><phrase role="special">)</phrase> <phrase role="special">)</phrase> <phrase role="special">{</phrase> 13463 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="identifier">value</phrase><phrase role="special">(</phrase> <phrase role="identifier">future</phrase><phrase role="special">.</phrase><phrase role="identifier">get</phrase><phrase role="special">()</phrase> <phrase role="special">);</phrase> 13464 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cout</phrase> <phrase role="special"><<</phrase> <phrase role="string">"wait_all_until_error_source(success) => '"</phrase> <phrase role="special"><<</phrase> <phrase role="identifier">value</phrase> 13465 <phrase role="special"><<</phrase> <phrase role="string">"'"</phrase> <phrase role="special"><<</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">endl</phrase><phrase role="special">;</phrase> 13466<phrase role="special">}</phrase> 13467</programlisting> 13468 </para> 13469 </section> 13470 <section id="fiber.when_any.when_all_functionality.wait_all__collecting_all_exceptions"> 13471 <title><link linkend="fiber.when_any.when_all_functionality.wait_all__collecting_all_exceptions">wait_all, 13472 collecting all exceptions</link></title> 13473 <para> 13474 <anchor id="wait_all_collect_errors"/>Given <link linkend="wait_all_until_error_source"><code><phrase 13475 role="identifier">wait_all_until_error_source</phrase><phrase role="special">()</phrase></code></link>, 13476 it might be more reasonable to make a <code><phrase role="identifier">wait_all_</phrase><phrase 13477 role="special">...()</phrase></code> that collects <emphasis>all</emphasis> 13478 errors instead of presenting only the first: 13479 </para> 13480 <para> 13481<programlisting><phrase role="keyword">template</phrase><phrase role="special"><</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">></phrase> 13482<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">vector</phrase><phrase role="special"><</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">result_of</phrase><phrase role="special"><</phrase> <phrase role="identifier">Fn</phrase><phrase role="special">()</phrase> <phrase role="special">>::</phrase><phrase role="identifier">type</phrase> <phrase role="special">></phrase> 13483<phrase role="identifier">wait_all_collect_errors</phrase><phrase role="special">(</phrase> <phrase role="identifier">Fn</phrase> <phrase role="special">&&</phrase> <phrase role="identifier">function</phrase><phrase role="special">,</phrase> <phrase role="identifier">Fns</phrase> <phrase role="special">&&</phrase> <phrase role="special">...</phrase> <phrase role="identifier">functions</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase> 13484 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">count</phrase><phrase role="special">(</phrase> <phrase role="number">1</phrase> <phrase role="special">+</phrase> <phrase role="keyword">sizeof</phrase> <phrase role="special">...</phrase> <phrase role="special">(</phrase> <phrase role="identifier">functions</phrase><phrase role="special">)</phrase> <phrase role="special">);</phrase> 13485 <phrase role="keyword">typedef</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">result_of</phrase><phrase role="special"><</phrase> <phrase role="identifier">Fn</phrase><phrase role="special">()</phrase> <phrase role="special">>::</phrase><phrase role="identifier">type</phrase> <phrase role="identifier">return_t</phrase><phrase role="special">;</phrase> 13486 <phrase role="keyword">typedef</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">future</phrase><phrase role="special"><</phrase> <phrase role="identifier">return_t</phrase> <phrase role="special">></phrase> <phrase role="identifier">future_t</phrase><phrase role="special">;</phrase> 13487 <phrase role="keyword">typedef</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">vector</phrase><phrase role="special"><</phrase> <phrase role="identifier">return_t</phrase> <phrase role="special">></phrase> <phrase role="identifier">vector_t</phrase><phrase role="special">;</phrase> 13488 <phrase role="identifier">vector_t</phrase> <phrase role="identifier">results</phrase><phrase role="special">;</phrase> 13489 <phrase role="identifier">results</phrase><phrase role="special">.</phrase><phrase role="identifier">reserve</phrase><phrase role="special">(</phrase> <phrase role="identifier">count</phrase><phrase role="special">);</phrase> 13490 <phrase role="identifier">exception_list</phrase> <phrase role="identifier">exceptions</phrase><phrase role="special">(</phrase><phrase role="string">"wait_all_collect_errors() exceptions"</phrase><phrase role="special">);</phrase> 13491 13492 <phrase role="comment">// get channel</phrase> 13493 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">shared_ptr</phrase><phrase role="special"><</phrase> 13494 <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">buffered_channel</phrase><phrase role="special"><</phrase> <phrase role="identifier">future_t</phrase> <phrase role="special">></phrase> <phrase role="special">></phrase> <phrase role="identifier">chan</phrase><phrase role="special">(</phrase> 13495 <phrase role="identifier">wait_all_until_error_source</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">forward</phrase><phrase role="special"><</phrase> <phrase role="identifier">Fn</phrase> <phrase role="special">>(</phrase> <phrase role="identifier">function</phrase><phrase role="special">),</phrase> 13496 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">forward</phrase><phrase role="special"><</phrase> <phrase role="identifier">Fns</phrase> <phrase role="special">>(</phrase> <phrase role="identifier">functions</phrase><phrase role="special">)</phrase> <phrase role="special">...</phrase> <phrase role="special">)</phrase> <phrase role="special">);</phrase> 13497 <phrase role="comment">// fill results and/or exceptions vectors</phrase> 13498 <phrase role="identifier">future_t</phrase> <phrase role="identifier">future</phrase><phrase role="special">;</phrase> 13499 <phrase role="keyword">while</phrase> <phrase role="special">(</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">channel_op_status</phrase><phrase role="special">::</phrase><phrase role="identifier">success</phrase> <phrase role="special">==</phrase> <phrase role="identifier">chan</phrase><phrase role="special">-></phrase><phrase role="identifier">pop</phrase><phrase role="special">(</phrase> <phrase role="identifier">future</phrase><phrase role="special">)</phrase> <phrase role="special">)</phrase> <phrase role="special">{</phrase> 13500 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">exception_ptr</phrase> <phrase role="identifier">exp</phrase> <phrase role="special">=</phrase> <phrase role="identifier">future</phrase><phrase role="special">.</phrase><phrase role="identifier">get_exception_ptr</phrase><phrase role="special">();</phrase> 13501 <phrase role="keyword">if</phrase> <phrase role="special">(</phrase> <phrase role="special">!</phrase> <phrase role="identifier">exp</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase> 13502 <phrase role="identifier">results</phrase><phrase role="special">.</phrase><phrase role="identifier">push_back</phrase><phrase role="special">(</phrase> <phrase role="identifier">future</phrase><phrase role="special">.</phrase><phrase role="identifier">get</phrase><phrase role="special">()</phrase> <phrase role="special">);</phrase> 13503 <phrase role="special">}</phrase> <phrase role="keyword">else</phrase> <phrase role="special">{</phrase> 13504 <phrase role="identifier">exceptions</phrase><phrase role="special">.</phrase><phrase role="identifier">add</phrase><phrase role="special">(</phrase> <phrase role="identifier">exp</phrase><phrase role="special">);</phrase> 13505 <phrase role="special">}</phrase> 13506 <phrase role="special">}</phrase> 13507 <phrase role="comment">// if there were any exceptions, throw</phrase> 13508 <phrase role="keyword">if</phrase> <phrase role="special">(</phrase> <phrase role="identifier">exceptions</phrase><phrase role="special">.</phrase><phrase role="identifier">size</phrase><phrase role="special">()</phrase> <phrase role="special">)</phrase> <phrase role="special">{</phrase> 13509 <phrase role="keyword">throw</phrase> <phrase role="identifier">exceptions</phrase><phrase role="special">;</phrase> 13510 <phrase role="special">}</phrase> 13511 <phrase role="comment">// no exceptions: return vector to caller</phrase> 13512 <phrase role="keyword">return</phrase> <phrase role="identifier">results</phrase><phrase role="special">;</phrase> 13513<phrase role="special">}</phrase> 13514</programlisting> 13515 </para> 13516 <para> 13517 The implementation is a simple variation on <link linkend="wait_first_success"><code><phrase 13518 role="identifier">wait_first_success</phrase><phrase role="special">()</phrase></code></link>, 13519 using the same <link linkend="exception_list"><code><phrase role="identifier">exception_list</phrase></code></link> 13520 exception class. 13521 </para> 13522 </section> 13523 <section id="fiber.when_any.when_all_functionality.when_all__heterogeneous_types"> 13524 <title><link linkend="fiber.when_any.when_all_functionality.when_all__heterogeneous_types">when_all, 13525 heterogeneous types</link></title> 13526 <para> 13527 But what about the case when we must wait for all results of different 13528 types? 13529 </para> 13530 <para> 13531 We can present an API that is frankly quite cool. Consider a sample struct: 13532 </para> 13533 <para> 13534<programlisting><phrase role="keyword">struct</phrase> <phrase role="identifier">Data</phrase> <phrase role="special">{</phrase> 13535 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="identifier">str</phrase><phrase role="special">;</phrase> 13536 <phrase role="keyword">double</phrase> <phrase role="identifier">inexact</phrase><phrase role="special">;</phrase> 13537 <phrase role="keyword">int</phrase> <phrase role="identifier">exact</phrase><phrase role="special">;</phrase> 13538 13539 <phrase role="keyword">friend</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">ostream</phrase><phrase role="special">&</phrase> <phrase role="keyword">operator</phrase><phrase role="special"><<(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">ostream</phrase><phrase role="special">&</phrase> <phrase role="identifier">out</phrase><phrase role="special">,</phrase> <phrase role="identifier">Data</phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">data</phrase><phrase role="special">);</phrase> 13540 <phrase role="special">...</phrase> 13541<phrase role="special">};</phrase> 13542</programlisting> 13543 </para> 13544 <para> 13545 Let's fill its members from task functions all running concurrently: 13546 </para> 13547 <para> 13548<programlisting><phrase role="identifier">Data</phrase> <phrase role="identifier">data</phrase> <phrase role="special">=</phrase> <phrase role="identifier">wait_all_members</phrase><phrase role="special"><</phrase> <phrase role="identifier">Data</phrase> <phrase role="special">>(</phrase> 13549 <phrase role="special">[](){</phrase> <phrase role="keyword">return</phrase> <phrase role="identifier">sleeper</phrase><phrase role="special">(</phrase><phrase role="string">"wams_left"</phrase><phrase role="special">,</phrase> <phrase role="number">100</phrase><phrase role="special">);</phrase> <phrase role="special">},</phrase> 13550 <phrase role="special">[](){</phrase> <phrase role="keyword">return</phrase> <phrase role="identifier">sleeper</phrase><phrase role="special">(</phrase><phrase role="number">3.14</phrase><phrase role="special">,</phrase> <phrase role="number">150</phrase><phrase role="special">);</phrase> <phrase role="special">},</phrase> 13551 <phrase role="special">[](){</phrase> <phrase role="keyword">return</phrase> <phrase role="identifier">sleeper</phrase><phrase role="special">(</phrase><phrase role="number">17</phrase><phrase role="special">,</phrase> <phrase role="number">50</phrase><phrase role="special">);</phrase> <phrase role="special">});</phrase> 13552<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cout</phrase> <phrase role="special"><<</phrase> <phrase role="string">"wait_all_members<Data>(success) => "</phrase> <phrase role="special"><<</phrase> <phrase role="identifier">data</phrase> <phrase role="special"><<</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">endl</phrase><phrase role="special">;</phrase> 13553</programlisting> 13554 </para> 13555 <para> 13556 Note that for this case, we abandon the notion of capturing the earliest 13557 result first, and so on: we must fill exactly the passed struct in left-to-right 13558 order. 13559 </para> 13560 <para> 13561 That permits a beautifully simple implementation: 13562 </para> 13563 <para> 13564<programlisting><phrase role="comment">// Explicitly pass Result. This can be any type capable of being initialized</phrase> 13565<phrase role="comment">// from the results of the passed functions, such as a struct.</phrase> 13566<phrase role="keyword">template</phrase><phrase role="special"><</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">></phrase> 13567<phrase role="identifier">Result</phrase> <phrase role="identifier">wait_all_members</phrase><phrase role="special">(</phrase> <phrase role="identifier">Fns</phrase> <phrase role="special">&&</phrase> <phrase role="special">...</phrase> <phrase role="identifier">functions</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase> 13568 <phrase role="comment">// Run each of the passed functions on a separate fiber, passing all their</phrase> 13569 <phrase role="comment">// futures to helper function for processing.</phrase> 13570 <phrase role="keyword">return</phrase> <phrase role="identifier">wait_all_members_get</phrase><phrase role="special"><</phrase> <phrase role="identifier">Result</phrase> <phrase role="special">>(</phrase> 13571 <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">async</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">forward</phrase><phrase role="special"><</phrase> <phrase role="identifier">Fns</phrase> <phrase role="special">>(</phrase> <phrase role="identifier">functions</phrase><phrase role="special">)</phrase> <phrase role="special">)</phrase> <phrase role="special">...</phrase> <phrase role="special">);</phrase> 13572<phrase role="special">}</phrase> 13573</programlisting> 13574 </para> 13575 <para> 13576<programlisting><phrase role="keyword">template</phrase><phrase role="special"><</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">></phrase> 13577<phrase role="identifier">Result</phrase> <phrase role="identifier">wait_all_members_get</phrase><phrase role="special">(</phrase> <phrase role="identifier">Futures</phrase> <phrase role="special">&&</phrase> <phrase role="special">...</phrase> <phrase role="identifier">futures</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase> 13578 <phrase role="comment">// Fetch the results from the passed futures into Result's initializer</phrase> 13579 <phrase role="comment">// list. It's true that the get() calls here will block the implicit</phrase> 13580 <phrase role="comment">// iteration over futures -- but that doesn't matter because we won't be</phrase> 13581 <phrase role="comment">// done until the slowest of them finishes anyway. As results are</phrase> 13582 <phrase role="comment">// processed in argument-list order rather than order of completion, the</phrase> 13583 <phrase role="comment">// leftmost get() to throw an exception will cause that exception to</phrase> 13584 <phrase role="comment">// propagate to the caller.</phrase> 13585 <phrase role="keyword">return</phrase> <phrase role="identifier">Result</phrase><phrase role="special">{</phrase> <phrase role="identifier">futures</phrase><phrase role="special">.</phrase><phrase role="identifier">get</phrase><phrase role="special">()</phrase> <phrase role="special">...</phrase> <phrase role="special">};</phrase> 13586<phrase role="special">}</phrase> 13587</programlisting> 13588 </para> 13589 <para> 13590 It is tempting to try to implement <code><phrase role="identifier">wait_all_members</phrase><phrase 13591 role="special">()</phrase></code> as a one-liner like this: 13592 </para> 13593<programlisting><phrase role="keyword">return</phrase> <phrase role="identifier">Result</phrase><phrase role="special">{</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">async</phrase><phrase role="special">(</phrase><phrase role="identifier">functions</phrase><phrase role="special">).</phrase><phrase role="identifier">get</phrase><phrase role="special">()...</phrase> <phrase role="special">};</phrase> 13594</programlisting> 13595 <para> 13596 The trouble with this tactic is that it would serialize all the task functions. 13597 The runtime makes a single pass through <code><phrase role="identifier">functions</phrase></code>, 13598 calling <link linkend="fibers_async"><code>fibers::async()</code></link> for each and then immediately calling 13599 <link linkend="future_get"><code>future::get()</code></link> on its returned <code><phrase role="identifier">future</phrase><phrase 13600 role="special"><></phrase></code>. That blocks the implicit loop. 13601 The above is almost equivalent to writing: 13602 </para> 13603<programlisting><phrase role="keyword">return</phrase> <phrase role="identifier">Result</phrase><phrase role="special">{</phrase> <phrase role="identifier">functions</phrase><phrase role="special">()...</phrase> <phrase role="special">};</phrase> 13604</programlisting> 13605 <para> 13606 in which, of course, there is no concurrency at all. 13607 </para> 13608 <para> 13609 Passing the argument pack through a function-call boundary (<code><phrase 13610 role="identifier">wait_all_members_get</phrase><phrase role="special">()</phrase></code>) 13611 forces the runtime to make <emphasis>two</emphasis> passes: one in <code><phrase 13612 role="identifier">wait_all_members</phrase><phrase role="special">()</phrase></code> 13613 to collect the <code><phrase role="identifier">future</phrase><phrase role="special"><></phrase></code>s 13614 from all the <code><phrase role="identifier">async</phrase><phrase role="special">()</phrase></code> 13615 calls, the second in <code><phrase role="identifier">wait_all_members_get</phrase><phrase 13616 role="special">()</phrase></code> to fetch each of the results. 13617 </para> 13618 <para> 13619 As noted in comments, within the <code><phrase role="identifier">wait_all_members_get</phrase><phrase 13620 role="special">()</phrase></code> parameter pack expansion pass, the blocking 13621 behavior of <code><phrase role="identifier">get</phrase><phrase role="special">()</phrase></code> 13622 becomes irrelevant. Along the way, we will hit the <code><phrase role="identifier">get</phrase><phrase 13623 role="special">()</phrase></code> for the slowest task function; after 13624 that every subsequent <code><phrase role="identifier">get</phrase><phrase 13625 role="special">()</phrase></code> will complete in trivial time. 13626 </para> 13627 <para> 13628 By the way, we could also use this same API to fill a vector or other collection: 13629 </para> 13630 <para> 13631<programlisting><phrase role="comment">// If we don't care about obtaining results as soon as they arrive, and we</phrase> 13632<phrase role="comment">// prefer a result vector in passed argument order rather than completion</phrase> 13633<phrase role="comment">// order, wait_all_members() is another possible implementation of</phrase> 13634<phrase role="comment">// wait_all_until_error().</phrase> 13635<phrase role="keyword">auto</phrase> <phrase role="identifier">strings</phrase> <phrase role="special">=</phrase> <phrase role="identifier">wait_all_members</phrase><phrase role="special"><</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">vector</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="special">>(</phrase> 13636 <phrase role="special">[](){</phrase> <phrase role="keyword">return</phrase> <phrase role="identifier">sleeper</phrase><phrase role="special">(</phrase><phrase role="string">"wamv_left"</phrase><phrase role="special">,</phrase> <phrase role="number">150</phrase><phrase role="special">);</phrase> <phrase role="special">},</phrase> 13637 <phrase role="special">[](){</phrase> <phrase role="keyword">return</phrase> <phrase role="identifier">sleeper</phrase><phrase role="special">(</phrase><phrase role="string">"wamv_middle"</phrase><phrase role="special">,</phrase> <phrase role="number">100</phrase><phrase role="special">);</phrase> <phrase role="special">},</phrase> 13638 <phrase role="special">[](){</phrase> <phrase role="keyword">return</phrase> <phrase role="identifier">sleeper</phrase><phrase role="special">(</phrase><phrase role="string">"wamv_right"</phrase><phrase role="special">,</phrase> <phrase role="number">50</phrase><phrase role="special">);</phrase> <phrase role="special">});</phrase> 13639<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cout</phrase> <phrase role="special"><<</phrase> <phrase role="string">"wait_all_members<vector>() =>"</phrase><phrase role="special">;</phrase> 13640<phrase role="keyword">for</phrase> <phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">str</phrase> <phrase role="special">:</phrase> <phrase role="identifier">strings</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase> 13641 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cout</phrase> <phrase role="special"><<</phrase> <phrase role="string">" '"</phrase> <phrase role="special"><<</phrase> <phrase role="identifier">str</phrase> <phrase role="special"><<</phrase> <phrase role="string">"'"</phrase><phrase role="special">;</phrase> 13642<phrase role="special">}</phrase> 13643<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cout</phrase> <phrase role="special"><<</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">endl</phrase><phrase role="special">;</phrase> 13644</programlisting> 13645 </para> 13646 </section> 13647 </section> 13648 </section> 13649 <section id="fiber.integration"> 13650 <title><anchor id="integration"/><link linkend="fiber.integration">Sharing a 13651 Thread with Another Main Loop</link></title> 13652 <section id="fiber.integration.overview"> 13653 <title><link linkend="fiber.integration.overview">Overview</link></title> 13654 <para> 13655 As always with cooperative concurrency, it is important not to let any one 13656 fiber monopolize the processor too long: that could <quote>starve</quote> 13657 other ready fibers. This section discusses a couple of solutions. 13658 </para> 13659 </section> 13660 <section id="fiber.integration.event_driven_program"> 13661 <title><link linkend="fiber.integration.event_driven_program">Event-Driven 13662 Program</link></title> 13663 <para> 13664 Consider a classic event-driven program, organized around a main loop that 13665 fetches and dispatches incoming I/O events. You are introducing <emphasis 13666 role="bold">Boost.Fiber</emphasis> because certain asynchronous I/O sequences 13667 are logically sequential, and for those you want to write and maintain code 13668 that looks and acts sequential. 13669 </para> 13670 <para> 13671 You are launching fibers on the application’s main thread because certain 13672 of their actions will affect its user interface, and the application’s UI 13673 framework permits UI operations only on the main thread. Or perhaps those 13674 fibers need access to main-thread data, and it would be too expensive in 13675 runtime (or development time) to robustly defend every such data item with 13676 thread synchronization primitives. 13677 </para> 13678 <para> 13679 You must ensure that the application’s main loop <emphasis>itself</emphasis> 13680 doesn’t monopolize the processor: that the fibers it launches will get the 13681 CPU cycles they need. 13682 </para> 13683 <para> 13684 The solution is the same as for any fiber that might claim the CPU for an 13685 extended time: introduce calls to <link linkend="this_fiber_yield"><code>this_fiber::yield()</code></link>. The 13686 most straightforward approach is to call <code><phrase role="identifier">yield</phrase><phrase 13687 role="special">()</phrase></code> on every iteration of your existing main 13688 loop. In effect, this unifies the application’s main loop with <emphasis role="bold">Boost.Fiber</emphasis>’s 13689 internal main loop. <code><phrase role="identifier">yield</phrase><phrase 13690 role="special">()</phrase></code> allows the fiber manager to run any fibers 13691 that have become ready since the previous iteration of the application’s main 13692 loop. When these fibers have had a turn, control passes to the thread’s main 13693 fiber, which returns from <code><phrase role="identifier">yield</phrase><phrase 13694 role="special">()</phrase></code> and resumes the application’s main loop. 13695 </para> 13696 </section> 13697 <section id="fiber.integration.embedded_main_loop"> 13698 <title><anchor id="embedded_main_loop"/><link linkend="fiber.integration.embedded_main_loop">Embedded 13699 Main Loop</link></title> 13700 <para> 13701 More challenging is when the application’s main loop is embedded in some other 13702 library or framework. Such an application will typically, after performing 13703 all necessary setup, pass control to some form of <code><phrase role="identifier">run</phrase><phrase 13704 role="special">()</phrase></code> function from which control does not return 13705 until application shutdown. 13706 </para> 13707 <para> 13708 A <ulink url="http://www.boost.org/doc/libs/release/libs/asio/index.html">Boost.Asio</ulink> 13709 program might call <ulink url="http://www.boost.org/doc/libs/release/doc/html/boost_asio/reference/io_service/run.html"><code><phrase 13710 role="identifier">io_service</phrase><phrase role="special">::</phrase><phrase 13711 role="identifier">run</phrase><phrase role="special">()</phrase></code></ulink> 13712 in this way. 13713 </para> 13714 <para> 13715 In general, the trick is to arrange to pass control to <link linkend="this_fiber_yield"><code>this_fiber::yield()</code></link> frequently. 13716 You could use an <ulink url="http://www.boost.org/doc/libs/release/doc/html/boost_asio/reference/high_resolution_timer.html">Asio 13717 timer</ulink> for that purpose. You could instantiate the timer, arranging 13718 to call a handler function when the timer expires. The handler function could 13719 call <code><phrase role="identifier">yield</phrase><phrase role="special">()</phrase></code>, 13720 then reset the timer and arrange to wake up again on its next expiration. 13721 </para> 13722 <para> 13723 Since, in this thought experiment, we always pass control to the fiber manager 13724 via <code><phrase role="identifier">yield</phrase><phrase role="special">()</phrase></code>, 13725 the calling fiber is never blocked. Therefore there is always at least one 13726 ready fiber. Therefore the fiber manager never calls <link linkend="algorithm_suspend_until"><code>algorithm::suspend_until()</code></link>. 13727 </para> 13728 <para> 13729 Using <ulink url="http://www.boost.org/doc/libs/release/doc/html/boost_asio/reference/io_service/post.html"><code><phrase 13730 role="identifier">io_service</phrase><phrase role="special">::</phrase><phrase 13731 role="identifier">post</phrase><phrase role="special">()</phrase></code></ulink> 13732 instead of setting a timer for some nonzero interval would be unfriendly 13733 to other threads. When all I/O is pending and all fibers are blocked, the 13734 io_service and the fiber manager would simply spin the CPU, passing control 13735 back and forth to each other. Using a timer allows tuning the responsiveness 13736 of this thread relative to others. 13737 </para> 13738 </section> 13739 <section id="fiber.integration.deeper_dive_into___boost_asio__"> 13740 <title><link linkend="fiber.integration.deeper_dive_into___boost_asio__">Deeper 13741 Dive into <ulink url="http://www.boost.org/doc/libs/release/libs/asio/index.html">Boost.Asio</ulink></link></title> 13742 <para> 13743 By now the alert reader is thinking: but surely, with Asio in particular, 13744 we ought to be able to do much better than periodic polling pings! 13745 </para> 13746 <para> 13747 This turns out to be surprisingly tricky. We present a possible approach 13748 in <ulink url="../../examples/asio/round_robin.hpp"><code><phrase role="identifier">examples</phrase><phrase 13749 role="special">/</phrase><phrase role="identifier">asio</phrase><phrase role="special">/</phrase><phrase 13750 role="identifier">round_robin</phrase><phrase role="special">.</phrase><phrase 13751 role="identifier">hpp</phrase></code></ulink>. 13752 </para> 13753 <para> 13754 One consequence of using <ulink url="http://www.boost.org/doc/libs/release/libs/asio/index.html">Boost.Asio</ulink> 13755 is that you must always let Asio suspend the running thread. Since Asio is 13756 aware of pending I/O requests, it can arrange to suspend the thread in such 13757 a way that the OS will wake it on I/O completion. No one else has sufficient 13758 knowledge. 13759 </para> 13760 <para> 13761 So the fiber scheduler must depend on Asio for suspension and resumption. 13762 It requires Asio handler calls to wake it. 13763 </para> 13764 <para> 13765 One dismaying implication is that we cannot support multiple threads calling 13766 <ulink url="http://www.boost.org/doc/libs/release/doc/html/boost_asio/reference/io_service/run.html"><code><phrase 13767 role="identifier">io_service</phrase><phrase role="special">::</phrase><phrase 13768 role="identifier">run</phrase><phrase role="special">()</phrase></code></ulink> 13769 on the same <code><phrase role="identifier">io_service</phrase></code> instance. 13770 The reason is that Asio provides no way to constrain a particular handler 13771 to be called only on a specified thread. A fiber scheduler instance is locked 13772 to a particular thread: that instance cannot manage any other thread’s fibers. 13773 Yet if we allow multiple threads to call <code><phrase role="identifier">io_service</phrase><phrase 13774 role="special">::</phrase><phrase role="identifier">run</phrase><phrase role="special">()</phrase></code> 13775 on the same <code><phrase role="identifier">io_service</phrase></code> instance, 13776 a fiber scheduler which needs to sleep can have no guarantee that it will 13777 reawaken in a timely manner. It can set an Asio timer, as described above 13778 — but that timer’s handler may well execute on a different thread! 13779 </para> 13780 <para> 13781 Another implication is that since an Asio-aware fiber scheduler (not to mention 13782 <link linkend="callbacks_asio"><code><phrase role="identifier">boost</phrase><phrase 13783 role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase 13784 role="special">::</phrase><phrase role="identifier">asio</phrase><phrase 13785 role="special">::</phrase><phrase role="identifier">yield</phrase></code></link>) 13786 depends on handler calls from the <code><phrase role="identifier">io_service</phrase></code>, 13787 it is the application’s responsibility to ensure that <ulink url="http://www.boost.org/doc/libs/release/doc/html/boost_asio/reference/io_service/stop.html"><code><phrase 13788 role="identifier">io_service</phrase><phrase role="special">::</phrase><phrase 13789 role="identifier">stop</phrase><phrase role="special">()</phrase></code></ulink> 13790 is not called until every fiber has terminated. 13791 </para> 13792 <para> 13793 It is easier to reason about the behavior of the presented <code><phrase 13794 role="identifier">asio</phrase><phrase role="special">::</phrase><phrase 13795 role="identifier">round_robin</phrase></code> scheduler if we require that 13796 after initial setup, the thread’s main fiber is the fiber that calls <code><phrase 13797 role="identifier">io_service</phrase><phrase role="special">::</phrase><phrase 13798 role="identifier">run</phrase><phrase role="special">()</phrase></code>, 13799 so let’s impose that requirement. 13800 </para> 13801 <para> 13802 Naturally, the first thing we must do on each thread using a custom fiber 13803 scheduler is call <link linkend="use_scheduling_algorithm"><code>use_scheduling_algorithm()</code></link>. However, 13804 since <code><phrase role="identifier">asio</phrase><phrase role="special">::</phrase><phrase 13805 role="identifier">round_robin</phrase></code> requires an <code><phrase role="identifier">io_service</phrase></code> 13806 instance, we must first declare that. 13807 </para> 13808 <para> 13809<programlisting><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">shared_ptr</phrase><phrase role="special"><</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">io_svc</phrase> <phrase role="special">=</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">make_shared</phrase><phrase role="special"><</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> 13810<phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">use_scheduling_algorithm</phrase><phrase role="special"><</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">>(</phrase> <phrase role="identifier">io_svc</phrase><phrase role="special">);</phrase> 13811</programlisting> 13812 </para> 13813 <para> 13814 <code><phrase role="identifier">use_scheduling_algorithm</phrase><phrase 13815 role="special">()</phrase></code> instantiates <code><phrase role="identifier">asio</phrase><phrase 13816 role="special">::</phrase><phrase role="identifier">round_robin</phrase></code>, 13817 which naturally calls its constructor: 13818 </para> 13819 <para> 13820<programlisting><phrase role="identifier">round_robin</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">shared_ptr</phrase><phrase role="special"><</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="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">io_svc</phrase><phrase role="special">)</phrase> <phrase role="special">:</phrase> 13821 <phrase role="identifier">io_svc_</phrase><phrase role="special">(</phrase> <phrase role="identifier">io_svc</phrase><phrase role="special">),</phrase> 13822 <phrase role="identifier">suspend_timer_</phrase><phrase role="special">(</phrase> <phrase role="special">*</phrase> <phrase role="identifier">io_svc_</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase> 13823 <phrase role="comment">// We use add_service() very deliberately. This will throw</phrase> 13824 <phrase role="comment">// service_already_exists if you pass the same io_service instance to</phrase> 13825 <phrase role="comment">// more than one round_robin instance.</phrase> 13826 <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">asio</phrase><phrase role="special">::</phrase><phrase role="identifier">add_service</phrase><phrase role="special">(</phrase> <phrase role="special">*</phrase> <phrase role="identifier">io_svc_</phrase><phrase role="special">,</phrase> <phrase role="keyword">new</phrase> <phrase role="identifier">service</phrase><phrase role="special">(</phrase> <phrase role="special">*</phrase> <phrase role="identifier">io_svc_</phrase><phrase role="special">)</phrase> <phrase role="special">);</phrase> 13827 <phrase role="identifier">io_svc_</phrase><phrase role="special">-></phrase><phrase role="identifier">post</phrase><phrase role="special">([</phrase><phrase role="keyword">this</phrase><phrase role="special">]()</phrase> <phrase role="keyword">mutable</phrase> <phrase role="special">{</phrase> 13828</programlisting> 13829 </para> 13830 <para> 13831 <code><phrase role="identifier">asio</phrase><phrase role="special">::</phrase><phrase 13832 role="identifier">round_robin</phrase></code> binds the passed <code><phrase 13833 role="identifier">io_service</phrase></code> pointer and initializes a <ulink 13834 url="http://www.boost.org/doc/libs/release/doc/html/boost_asio/reference/steady_timer.html"><code><phrase 13835 role="identifier">boost</phrase><phrase role="special">::</phrase><phrase 13836 role="identifier">asio</phrase><phrase role="special">::</phrase><phrase 13837 role="identifier">steady_timer</phrase></code></ulink>: 13838 </para> 13839 <para> 13840<programlisting><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">shared_ptr</phrase><phrase role="special"><</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">io_svc_</phrase><phrase role="special">;</phrase> 13841<phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">asio</phrase><phrase role="special">::</phrase><phrase role="identifier">steady_timer</phrase> <phrase role="identifier">suspend_timer_</phrase><phrase role="special">;</phrase> 13842</programlisting> 13843 </para> 13844 <para> 13845 Then it calls <ulink url="http://www.boost.org/doc/libs/release/doc/html/boost_asio/reference/add_service.html"><code><phrase 13846 role="identifier">boost</phrase><phrase role="special">::</phrase><phrase 13847 role="identifier">asio</phrase><phrase role="special">::</phrase><phrase 13848 role="identifier">add_service</phrase><phrase role="special">()</phrase></code></ulink> 13849 with a nested <code><phrase role="identifier">service</phrase></code> struct: 13850 </para> 13851 <para> 13852<programlisting><phrase role="keyword">struct</phrase> <phrase role="identifier">service</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">asio</phrase><phrase role="special">::</phrase><phrase role="identifier">io_service</phrase><phrase role="special">::</phrase><phrase role="identifier">service</phrase> <phrase role="special">{</phrase> 13853 <phrase role="keyword">static</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">asio</phrase><phrase role="special">::</phrase><phrase role="identifier">io_service</phrase><phrase role="special">::</phrase><phrase role="identifier">id</phrase> <phrase role="identifier">id</phrase><phrase role="special">;</phrase> 13854 13855 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">unique_ptr</phrase><phrase role="special"><</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">work_</phrase><phrase role="special">;</phrase> 13856 13857 <phrase role="identifier">service</phrase><phrase role="special">(</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">asio</phrase><phrase role="special">::</phrase><phrase role="identifier">io_service</phrase> <phrase role="special">&</phrase> <phrase role="identifier">io_svc</phrase><phrase role="special">)</phrase> <phrase role="special">:</phrase> 13858 <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">asio</phrase><phrase role="special">::</phrase><phrase role="identifier">io_service</phrase><phrase role="special">::</phrase><phrase role="identifier">service</phrase><phrase role="special">(</phrase> <phrase role="identifier">io_svc</phrase><phrase role="special">),</phrase> 13859 <phrase role="identifier">work_</phrase><phrase role="special">{</phrase> <phrase role="keyword">new</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">asio</phrase><phrase role="special">::</phrase><phrase role="identifier">io_service</phrase><phrase role="special">::</phrase><phrase role="identifier">work</phrase><phrase role="special">(</phrase> <phrase role="identifier">io_svc</phrase><phrase role="special">)</phrase> <phrase role="special">}</phrase> <phrase role="special">{</phrase> 13860 <phrase role="special">}</phrase> 13861 13862 <phrase role="keyword">virtual</phrase> <phrase role="special">~</phrase><phrase role="identifier">service</phrase><phrase role="special">()</phrase> <phrase role="special">{}</phrase> 13863 13864 <phrase role="identifier">service</phrase><phrase role="special">(</phrase> <phrase role="identifier">service</phrase> <phrase role="keyword">const</phrase><phrase role="special">&)</phrase> <phrase role="special">=</phrase> <phrase role="keyword">delete</phrase><phrase role="special">;</phrase> 13865 <phrase role="identifier">service</phrase> <phrase role="special">&</phrase> <phrase role="keyword">operator</phrase><phrase role="special">=(</phrase> <phrase role="identifier">service</phrase> <phrase role="keyword">const</phrase><phrase role="special">&)</phrase> <phrase role="special">=</phrase> <phrase role="keyword">delete</phrase><phrase role="special">;</phrase> 13866 13867 <phrase role="keyword">void</phrase> <phrase role="identifier">shutdown_service</phrase><phrase role="special">()</phrase> <phrase role="identifier">override</phrase> <phrase role="identifier">final</phrase> <phrase role="special">{</phrase> 13868 <phrase role="identifier">work_</phrase><phrase role="special">.</phrase><phrase role="identifier">reset</phrase><phrase role="special">();</phrase> 13869 <phrase role="special">}</phrase> 13870<phrase role="special">};</phrase> 13871</programlisting> 13872 </para> 13873 <para> 13874 ... [asio_rr_service_bottom] 13875 </para> 13876 <para> 13877 The <code><phrase role="identifier">service</phrase></code> struct has a 13878 couple of roles. 13879 </para> 13880 <para> 13881 Its foremost role is to manage a <literal>std::unique_ptr<<ulink url="http://www.boost.org/doc/libs/release/doc/html/boost_asio/reference/io_service__work.html"><code><phrase 13882 role="identifier">boost</phrase><phrase role="special">::</phrase><phrase 13883 role="identifier">asio</phrase><phrase role="special">::</phrase><phrase 13884 role="identifier">io_service</phrase><phrase role="special">::</phrase><phrase 13885 role="identifier">work</phrase></code></ulink>></literal>. We want the 13886 <code><phrase role="identifier">io_service</phrase></code> instance to continue 13887 its main loop even when there is no pending Asio I/O. 13888 </para> 13889 <para> 13890 But when <ulink url="http://www.boost.org/doc/libs/release/doc/html/boost_asio/reference/io_service__service/shutdown_service.html"><code><phrase 13891 role="identifier">boost</phrase><phrase role="special">::</phrase><phrase 13892 role="identifier">asio</phrase><phrase role="special">::</phrase><phrase 13893 role="identifier">io_service</phrase><phrase role="special">::</phrase><phrase 13894 role="identifier">service</phrase><phrase role="special">::</phrase><phrase 13895 role="identifier">shutdown_service</phrase><phrase role="special">()</phrase></code></ulink> 13896 is called, we discard the <code><phrase role="identifier">io_service</phrase><phrase 13897 role="special">::</phrase><phrase role="identifier">work</phrase></code> 13898 instance so the <code><phrase role="identifier">io_service</phrase></code> 13899 can shut down properly. 13900 </para> 13901 <para> 13902 Its other purpose is to <ulink url="http://www.boost.org/doc/libs/release/doc/html/boost_asio/reference/io_service/post.html"><code><phrase 13903 role="identifier">post</phrase><phrase role="special">()</phrase></code></ulink> 13904 a lambda (not yet shown). Let’s walk further through the example program before 13905 coming back to explain that lambda. 13906 </para> 13907 <para> 13908 The <code><phrase role="identifier">service</phrase></code> constructor returns 13909 to <code><phrase role="identifier">asio</phrase><phrase role="special">::</phrase><phrase 13910 role="identifier">round_robin</phrase></code>’s constructor, which returns 13911 to <code><phrase role="identifier">use_scheduling_algorithm</phrase><phrase 13912 role="special">()</phrase></code>, which returns to the application code. 13913 </para> 13914 <para> 13915 Once it has called <code><phrase role="identifier">use_scheduling_algorithm</phrase><phrase 13916 role="special">()</phrase></code>, the application may now launch some number 13917 of fibers: 13918 </para> 13919 <para> 13920<programlisting><phrase role="comment">// server</phrase> 13921<phrase role="identifier">tcp</phrase><phrase role="special">::</phrase><phrase role="identifier">acceptor</phrase> <phrase role="identifier">a</phrase><phrase role="special">(</phrase> <phrase role="special">*</phrase> <phrase role="identifier">io_svc</phrase><phrase role="special">,</phrase> <phrase role="identifier">tcp</phrase><phrase role="special">::</phrase><phrase role="identifier">endpoint</phrase><phrase role="special">(</phrase> <phrase role="identifier">tcp</phrase><phrase role="special">::</phrase><phrase role="identifier">v4</phrase><phrase role="special">(),</phrase> <phrase role="number">9999</phrase><phrase role="special">)</phrase> <phrase role="special">);</phrase> 13922<phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">fiber</phrase><phrase role="special">(</phrase> <phrase role="identifier">server</phrase><phrase role="special">,</phrase> <phrase role="identifier">io_svc</phrase><phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">ref</phrase><phrase role="special">(</phrase> <phrase role="identifier">a</phrase><phrase role="special">)</phrase> <phrase role="special">).</phrase><phrase role="identifier">detach</phrase><phrase role="special">();</phrase> 13923<phrase role="comment">// client</phrase> 13924<phrase role="keyword">const</phrase> <phrase role="keyword">unsigned</phrase> <phrase role="identifier">iterations</phrase> <phrase role="special">=</phrase> <phrase role="number">2</phrase><phrase role="special">;</phrase> 13925<phrase role="keyword">const</phrase> <phrase role="keyword">unsigned</phrase> <phrase role="identifier">clients</phrase> <phrase role="special">=</phrase> <phrase role="number">3</phrase><phrase role="special">;</phrase> 13926<phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">barrier</phrase> <phrase role="identifier">b</phrase><phrase role="special">(</phrase> <phrase role="identifier">clients</phrase><phrase role="special">);</phrase> 13927<phrase role="keyword">for</phrase> <phrase role="special">(</phrase> <phrase role="keyword">unsigned</phrase> <phrase role="identifier">i</phrase> <phrase role="special">=</phrase> <phrase role="number">0</phrase><phrase role="special">;</phrase> <phrase role="identifier">i</phrase> <phrase role="special"><</phrase> <phrase role="identifier">clients</phrase><phrase role="special">;</phrase> <phrase role="special">++</phrase><phrase role="identifier">i</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase> 13928 <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">fiber</phrase><phrase role="special">(</phrase> 13929 <phrase role="identifier">client</phrase><phrase role="special">,</phrase> <phrase role="identifier">io_svc</phrase><phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">ref</phrase><phrase role="special">(</phrase> <phrase role="identifier">a</phrase><phrase role="special">),</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">ref</phrase><phrase role="special">(</phrase> <phrase role="identifier">b</phrase><phrase role="special">),</phrase> <phrase role="identifier">iterations</phrase><phrase role="special">).</phrase><phrase role="identifier">detach</phrase><phrase role="special">();</phrase> 13930<phrase role="special">}</phrase> 13931</programlisting> 13932 </para> 13933 <para> 13934 Since we don’t specify a <link linkend="class_launch"><code>launch</code></link>, these fibers are ready to run, 13935 but have not yet been entered. 13936 </para> 13937 <para> 13938 Having set everything up, the application calls <ulink url="http://www.boost.org/doc/libs/release/doc/html/boost_asio/reference/io_service/run.html"><code><phrase 13939 role="identifier">io_service</phrase><phrase role="special">::</phrase><phrase 13940 role="identifier">run</phrase><phrase role="special">()</phrase></code></ulink>: 13941 </para> 13942 <para> 13943<programlisting><phrase role="identifier">io_svc</phrase><phrase role="special">-></phrase><phrase role="identifier">run</phrase><phrase role="special">();</phrase> 13944</programlisting> 13945 </para> 13946 <para> 13947 Now what? 13948 </para> 13949 <para> 13950 Because this <code><phrase role="identifier">io_service</phrase></code> instance 13951 owns an <code><phrase role="identifier">io_service</phrase><phrase role="special">::</phrase><phrase 13952 role="identifier">work</phrase></code> instance, <code><phrase role="identifier">run</phrase><phrase 13953 role="special">()</phrase></code> does not immediately return. But — none of 13954 the fibers that will perform actual work has even been entered yet! 13955 </para> 13956 <para> 13957 Without that initial <code><phrase role="identifier">post</phrase><phrase 13958 role="special">()</phrase></code> call in <code><phrase role="identifier">service</phrase></code>’s 13959 constructor, <emphasis>nothing</emphasis> would happen. The application would 13960 hang right here. 13961 </para> 13962 <para> 13963 So, what should the <code><phrase role="identifier">post</phrase><phrase 13964 role="special">()</phrase></code> handler execute? Simply <link linkend="this_fiber_yield"><code>this_fiber::yield()</code></link>? 13965 </para> 13966 <para> 13967 That would be a promising start. But we have no guarantee that any of the 13968 other fibers will initiate any Asio operations to keep the ball rolling. 13969 For all we know, every other fiber could reach a similar <code><phrase role="identifier">boost</phrase><phrase 13970 role="special">::</phrase><phrase role="identifier">this_fiber</phrase><phrase 13971 role="special">::</phrase><phrase role="identifier">yield</phrase><phrase 13972 role="special">()</phrase></code> call first. Control would return to the 13973 <code><phrase role="identifier">post</phrase><phrase role="special">()</phrase></code> 13974 handler, which would return to Asio, and... the application would hang. 13975 </para> 13976 <para> 13977 The <code><phrase role="identifier">post</phrase><phrase role="special">()</phrase></code> 13978 handler could <code><phrase role="identifier">post</phrase><phrase role="special">()</phrase></code> 13979 itself again. But as discussed in <link linkend="embedded_main_loop">the 13980 previous section</link>, once there are actual I/O operations in flight — once 13981 we reach a state in which no fiber is ready — 13982that would cause the thread to 13983 spin. 13984 </para> 13985 <para> 13986 We could, of course, set an Asio timer — again as <link linkend="embedded_main_loop">previously 13987 discussed</link>. But in this <quote>deeper dive,</quote> we’re trying to 13988 do a little better. 13989 </para> 13990 <para> 13991 The key to doing better is that since we’re in a fiber, we can run an actual 13992 loop — not just a chain of callbacks. We can wait for <quote>something to happen</quote> 13993 by calling <ulink url="http://www.boost.org/doc/libs/release/doc/html/boost_asio/reference/io_service/run_one.html"><code><phrase 13994 role="identifier">io_service</phrase><phrase role="special">::</phrase><phrase 13995 role="identifier">run_one</phrase><phrase role="special">()</phrase></code></ulink> 13996 — or we can execute already-queued Asio handlers by calling <ulink url="http://www.boost.org/doc/libs/release/doc/html/boost_asio/reference/io_service/poll.html"><code><phrase 13997 role="identifier">io_service</phrase><phrase role="special">::</phrase><phrase 13998 role="identifier">poll</phrase><phrase role="special">()</phrase></code></ulink>. 13999 </para> 14000 <para> 14001 Here’s the body of the lambda passed to the <code><phrase role="identifier">post</phrase><phrase 14002 role="special">()</phrase></code> call. 14003 </para> 14004 <para> 14005<programlisting> <phrase role="keyword">while</phrase> <phrase role="special">(</phrase> <phrase role="special">!</phrase> <phrase role="identifier">io_svc_</phrase><phrase role="special">-></phrase><phrase role="identifier">stopped</phrase><phrase role="special">()</phrase> <phrase role="special">)</phrase> <phrase role="special">{</phrase> 14006 <phrase role="keyword">if</phrase> <phrase role="special">(</phrase> <phrase role="identifier">has_ready_fibers</phrase><phrase role="special">()</phrase> <phrase role="special">)</phrase> <phrase role="special">{</phrase> 14007 <phrase role="comment">// run all pending handlers in round_robin</phrase> 14008 <phrase role="keyword">while</phrase> <phrase role="special">(</phrase> <phrase role="identifier">io_svc_</phrase><phrase role="special">-></phrase><phrase role="identifier">poll</phrase><phrase role="special">()</phrase> <phrase role="special">);</phrase> 14009 <phrase role="comment">// block this fiber till all pending (ready) fibers are processed</phrase> 14010 <phrase role="comment">// == round_robin::suspend_until() has been called</phrase> 14011 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">unique_lock</phrase><phrase role="special"><</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">></phrase> <phrase role="identifier">lk</phrase><phrase role="special">(</phrase> <phrase role="identifier">mtx_</phrase><phrase role="special">);</phrase> 14012 <phrase role="identifier">cnd_</phrase><phrase role="special">.</phrase><phrase role="identifier">wait</phrase><phrase role="special">(</phrase> <phrase role="identifier">lk</phrase><phrase role="special">);</phrase> 14013 <phrase role="special">}</phrase> <phrase role="keyword">else</phrase> <phrase role="special">{</phrase> 14014 <phrase role="comment">// run one handler inside io_service</phrase> 14015 <phrase role="comment">// if no handler available, block this thread</phrase> 14016 <phrase role="keyword">if</phrase> <phrase role="special">(</phrase> <phrase role="special">!</phrase> <phrase role="identifier">io_svc_</phrase><phrase role="special">-></phrase><phrase role="identifier">run_one</phrase><phrase role="special">()</phrase> <phrase role="special">)</phrase> <phrase role="special">{</phrase> 14017 <phrase role="keyword">break</phrase><phrase role="special">;</phrase> 14018 <phrase role="special">}</phrase> 14019 <phrase role="special">}</phrase> 14020<phrase role="special">}</phrase> 14021</programlisting> 14022 </para> 14023 <para> 14024 We want this loop to exit once the <code><phrase role="identifier">io_service</phrase></code> 14025 instance has been <ulink url="http://www.boost.org/doc/libs/release/doc/html/boost_asio/reference/io_service/stopped.html"><code><phrase 14026 role="identifier">stopped</phrase><phrase role="special">()</phrase></code></ulink>. 14027 </para> 14028 <para> 14029 As long as there are ready fibers, we interleave running ready Asio handlers 14030 with running ready fibers. 14031 </para> 14032 <para> 14033 If there are no ready fibers, we wait by calling <code><phrase role="identifier">run_one</phrase><phrase 14034 role="special">()</phrase></code>. Once any Asio handler has been called 14035 — no matter which — <code><phrase role="identifier">run_one</phrase><phrase role="special">()</phrase></code> 14036 returns. That handler may have transitioned some fiber to ready state, so 14037 we loop back to check again. 14038 </para> 14039 <para> 14040 (We won’t describe <code><phrase role="identifier">awakened</phrase><phrase 14041 role="special">()</phrase></code>, <code><phrase role="identifier">pick_next</phrase><phrase 14042 role="special">()</phrase></code> or <code><phrase role="identifier">has_ready_fibers</phrase><phrase 14043 role="special">()</phrase></code>, as these are just like <link linkend="round_robin_awakened"><code>round_robin::awakened()</code></link>, 14044 <link linkend="round_robin_pick_next"><code>round_robin::pick_next()</code></link> and <link linkend="round_robin_has_ready_fibers"><code>round_robin::has_ready_fibers()</code></link>.) 14045 </para> 14046 <para> 14047 That leaves <code><phrase role="identifier">suspend_until</phrase><phrase 14048 role="special">()</phrase></code> and <code><phrase role="identifier">notify</phrase><phrase 14049 role="special">()</phrase></code>. 14050 </para> 14051 <para> 14052 Doubtless you have been asking yourself: why are we calling <code><phrase 14053 role="identifier">io_service</phrase><phrase role="special">::</phrase><phrase 14054 role="identifier">run_one</phrase><phrase role="special">()</phrase></code> 14055 in the lambda loop? Why not call it in <code><phrase role="identifier">suspend_until</phrase><phrase 14056 role="special">()</phrase></code>, whose very API was designed for just such 14057 a purpose? 14058 </para> 14059 <para> 14060 Under normal circumstances, when the fiber manager finds no ready fibers, 14061 it calls <link linkend="algorithm_suspend_until"><code>algorithm::suspend_until()</code></link>. Why test <code><phrase 14062 role="identifier">has_ready_fibers</phrase><phrase role="special">()</phrase></code> 14063 in the lambda loop? Why not leverage the normal mechanism? 14064 </para> 14065 <para> 14066 The answer is: it matters who’s asking. 14067 </para> 14068 <para> 14069 Consider the lambda loop shown above. The only <emphasis role="bold">Boost.Fiber</emphasis> 14070 APIs it engages are <code><phrase role="identifier">has_ready_fibers</phrase><phrase 14071 role="special">()</phrase></code> and <link linkend="this_fiber_yield"><code>this_fiber::yield()</code></link>. 14072 <code><phrase role="identifier">yield</phrase><phrase role="special">()</phrase></code> 14073 does not <emphasis>block</emphasis> the calling fiber: the calling fiber 14074 does not become unready. It is immediately passed back to <link linkend="algorithm_awakened"><code>algorithm::awakened()</code></link>, 14075 to be resumed in its turn when all other ready fibers have had a chance to 14076 run. In other words: during a <code><phrase role="identifier">yield</phrase><phrase 14077 role="special">()</phrase></code> call, <emphasis>there is always at least 14078 one ready fiber.</emphasis> 14079 </para> 14080 <para> 14081 As long as this lambda loop is still running, the fiber manager does not 14082 call <code><phrase role="identifier">suspend_until</phrase><phrase role="special">()</phrase></code> 14083 because it always has a fiber ready to run. 14084 </para> 14085 <para> 14086 However, the lambda loop <emphasis>itself</emphasis> can detect the case 14087 when no <emphasis>other</emphasis> fibers are ready to run: the running fiber 14088 is not <emphasis>ready</emphasis> but <emphasis>running.</emphasis> 14089 </para> 14090 <para> 14091 That said, <code><phrase role="identifier">suspend_until</phrase><phrase 14092 role="special">()</phrase></code> and <code><phrase role="identifier">notify</phrase><phrase 14093 role="special">()</phrase></code> are in fact called during orderly shutdown 14094 processing, so let’s try a plausible implementation. 14095 </para> 14096 <para> 14097<programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">suspend_until</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">steady_clock</phrase><phrase role="special">::</phrase><phrase role="identifier">time_point</phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">abs_time</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase> <phrase role="special">{</phrase> 14098 <phrase role="comment">// Set a timer so at least one handler will eventually fire, causing</phrase> 14099 <phrase role="comment">// run_one() to eventually return.</phrase> 14100 <phrase role="keyword">if</phrase> <phrase role="special">(</phrase> <phrase role="special">(</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">steady_clock</phrase><phrase role="special">::</phrase><phrase role="identifier">time_point</phrase><phrase role="special">::</phrase><phrase role="identifier">max</phrase><phrase role="special">)()</phrase> <phrase role="special">!=</phrase> <phrase role="identifier">abs_time</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase> 14101 <phrase role="comment">// Each expires_at(time_point) call cancels any previous pending</phrase> 14102 <phrase role="comment">// call. We could inadvertently spin like this:</phrase> 14103 <phrase role="comment">// dispatcher calls suspend_until() with earliest wake time</phrase> 14104 <phrase role="comment">// suspend_until() sets suspend_timer_</phrase> 14105 <phrase role="comment">// lambda loop calls run_one()</phrase> 14106 <phrase role="comment">// some other asio handler runs before timer expires</phrase> 14107 <phrase role="comment">// run_one() returns to lambda loop</phrase> 14108 <phrase role="comment">// lambda loop yields to dispatcher</phrase> 14109 <phrase role="comment">// dispatcher finds no ready fibers</phrase> 14110 <phrase role="comment">// dispatcher calls suspend_until() with SAME wake time</phrase> 14111 <phrase role="comment">// suspend_until() sets suspend_timer_ to same time, canceling</phrase> 14112 <phrase role="comment">// previous async_wait()</phrase> 14113 <phrase role="comment">// lambda loop calls run_one()</phrase> 14114 <phrase role="comment">// asio calls suspend_timer_ handler with operation_aborted</phrase> 14115 <phrase role="comment">// run_one() returns to lambda loop... etc. etc.</phrase> 14116 <phrase role="comment">// So only actually set the timer when we're passed a DIFFERENT</phrase> 14117 <phrase role="comment">// abs_time value.</phrase> 14118 <phrase role="identifier">suspend_timer_</phrase><phrase role="special">.</phrase><phrase role="identifier">expires_at</phrase><phrase role="special">(</phrase> <phrase role="identifier">abs_time</phrase><phrase role="special">);</phrase> 14119 <phrase role="identifier">suspend_timer_</phrase><phrase role="special">.</phrase><phrase role="identifier">async_wait</phrase><phrase role="special">([](</phrase><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">system</phrase><phrase role="special">::</phrase><phrase role="identifier">error_code</phrase> <phrase role="keyword">const</phrase><phrase role="special">&){</phrase> 14120 <phrase role="identifier">this_fiber</phrase><phrase role="special">::</phrase><phrase role="identifier">yield</phrase><phrase role="special">();</phrase> 14121 <phrase role="special">});</phrase> 14122 <phrase role="special">}</phrase> 14123 <phrase role="identifier">cnd_</phrase><phrase role="special">.</phrase><phrase role="identifier">notify_one</phrase><phrase role="special">();</phrase> 14124<phrase role="special">}</phrase> 14125</programlisting> 14126 </para> 14127 <para> 14128 As you might expect, <code><phrase role="identifier">suspend_until</phrase><phrase 14129 role="special">()</phrase></code> sets an <ulink url="http://www.boost.org/doc/libs/release/doc/html/boost_asio/reference/steady_timer.html"><code><phrase 14130 role="identifier">asio</phrase><phrase role="special">::</phrase><phrase 14131 role="identifier">steady_timer</phrase></code></ulink> to <ulink url="http://www.boost.org/doc/libs/release/doc/html/boost_asio/reference/basic_waitable_timer/expires_at.html"><code><phrase 14132 role="identifier">expires_at</phrase><phrase role="special">()</phrase></code></ulink> 14133 the passed <ulink url="http://en.cppreference.com/w/cpp/chrono/steady_clock"><code><phrase 14134 role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase 14135 role="special">::</phrase><phrase role="identifier">steady_clock</phrase><phrase 14136 role="special">::</phrase><phrase role="identifier">time_point</phrase></code></ulink>. 14137 Usually. 14138 </para> 14139 <para> 14140 As indicated in comments, we avoid setting <code><phrase role="identifier">suspend_timer_</phrase></code> 14141 multiple times to the <emphasis>same</emphasis> <code><phrase role="identifier">time_point</phrase></code> 14142 value since every <code><phrase role="identifier">expires_at</phrase><phrase 14143 role="special">()</phrase></code> call cancels any previous <ulink url="http://www.boost.org/doc/libs/release/doc/html/boost_asio/reference/basic_waitable_timer/async_wait.html"><code><phrase 14144 role="identifier">async_wait</phrase><phrase role="special">()</phrase></code></ulink> 14145 call. There is a chance that we could spin. Reaching <code><phrase role="identifier">suspend_until</phrase><phrase 14146 role="special">()</phrase></code> means the fiber manager intends to yield 14147 the processor to Asio. Cancelling the previous <code><phrase role="identifier">async_wait</phrase><phrase 14148 role="special">()</phrase></code> call would fire its handler, causing <code><phrase 14149 role="identifier">run_one</phrase><phrase role="special">()</phrase></code> 14150 to return, potentially causing the fiber manager to call <code><phrase role="identifier">suspend_until</phrase><phrase 14151 role="special">()</phrase></code> again with the same <code><phrase role="identifier">time_point</phrase></code> 14152 value... 14153 </para> 14154 <para> 14155 Given that we suspend the thread by calling <code><phrase role="identifier">io_service</phrase><phrase 14156 role="special">::</phrase><phrase role="identifier">run_one</phrase><phrase 14157 role="special">()</phrase></code>, what’s important is that our <code><phrase 14158 role="identifier">async_wait</phrase><phrase role="special">()</phrase></code> 14159 call will cause a handler to run, which will cause <code><phrase role="identifier">run_one</phrase><phrase 14160 role="special">()</phrase></code> to return. It’s not so important specifically 14161 what that handler does. 14162 </para> 14163 <para> 14164<programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">notify</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase> <phrase role="special">{</phrase> 14165 <phrase role="comment">// Something has happened that should wake one or more fibers BEFORE</phrase> 14166 <phrase role="comment">// suspend_timer_ expires. Reset the timer to cause it to fire</phrase> 14167 <phrase role="comment">// immediately, causing the run_one() call to return. In theory we</phrase> 14168 <phrase role="comment">// could use cancel() because we don't care whether suspend_timer_'s</phrase> 14169 <phrase role="comment">// handler is called with operation_aborted or success. However --</phrase> 14170 <phrase role="comment">// cancel() doesn't change the expiration time, and we use</phrase> 14171 <phrase role="comment">// suspend_timer_'s expiration time to decide whether it's already</phrase> 14172 <phrase role="comment">// set. If suspend_until() set some specific wake time, then notify()</phrase> 14173 <phrase role="comment">// canceled it, then suspend_until() was called again with the same</phrase> 14174 <phrase role="comment">// wake time, it would match suspend_timer_'s expiration time and we'd</phrase> 14175 <phrase role="comment">// refrain from setting the timer. So instead of simply calling</phrase> 14176 <phrase role="comment">// cancel(), reset the timer, which cancels the pending sleep AND sets</phrase> 14177 <phrase role="comment">// a new expiration time. This will cause us to spin the loop twice --</phrase> 14178 <phrase role="comment">// once for the operation_aborted handler, once for timer expiration</phrase> 14179 <phrase role="comment">// -- but that shouldn't be a big problem.</phrase> 14180 <phrase role="identifier">suspend_timer_</phrase><phrase role="special">.</phrase><phrase role="identifier">async_wait</phrase><phrase role="special">([](</phrase><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">system</phrase><phrase role="special">::</phrase><phrase role="identifier">error_code</phrase> <phrase role="keyword">const</phrase><phrase role="special">&){</phrase> 14181 <phrase role="identifier">this_fiber</phrase><phrase role="special">::</phrase><phrase role="identifier">yield</phrase><phrase role="special">();</phrase> 14182 <phrase role="special">});</phrase> 14183 <phrase role="identifier">suspend_timer_</phrase><phrase role="special">.</phrase><phrase role="identifier">expires_at</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">steady_clock</phrase><phrase role="special">::</phrase><phrase role="identifier">now</phrase><phrase role="special">()</phrase> <phrase role="special">);</phrase> 14184<phrase role="special">}</phrase> 14185</programlisting> 14186 </para> 14187 <para> 14188 Since an <code><phrase role="identifier">expires_at</phrase><phrase role="special">()</phrase></code> 14189 call cancels any previous <code><phrase role="identifier">async_wait</phrase><phrase 14190 role="special">()</phrase></code> call, we can make <code><phrase role="identifier">notify</phrase><phrase 14191 role="special">()</phrase></code> simply call <code><phrase role="identifier">steady_timer</phrase><phrase 14192 role="special">::</phrase><phrase role="identifier">expires_at</phrase><phrase 14193 role="special">()</phrase></code>. That should cause the <code><phrase role="identifier">io_service</phrase></code> 14194 to call the <code><phrase role="identifier">async_wait</phrase><phrase role="special">()</phrase></code> 14195 handler with <code><phrase role="identifier">operation_aborted</phrase></code>. 14196 </para> 14197 <para> 14198 The comments in <code><phrase role="identifier">notify</phrase><phrase role="special">()</phrase></code> 14199 explain why we call <code><phrase role="identifier">expires_at</phrase><phrase 14200 role="special">()</phrase></code> rather than <ulink url="http://www.boost.org/doc/libs/release/doc/html/boost_asio/reference/basic_waitable_timer/cancel.html"><code><phrase 14201 role="identifier">cancel</phrase><phrase role="special">()</phrase></code></ulink>. 14202 </para> 14203 <para> 14204 This <code><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase 14205 role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase 14206 role="identifier">asio</phrase><phrase role="special">::</phrase><phrase 14207 role="identifier">round_robin</phrase></code> implementation is used in 14208 <ulink url="../../examples/asio/autoecho.cpp"><code><phrase role="identifier">examples</phrase><phrase 14209 role="special">/</phrase><phrase role="identifier">asio</phrase><phrase role="special">/</phrase><phrase 14210 role="identifier">autoecho</phrase><phrase role="special">.</phrase><phrase 14211 role="identifier">cpp</phrase></code></ulink>. 14212 </para> 14213 <para> 14214 It seems possible that you could put together a more elegant Fiber / Asio 14215 integration. But as noted at the outset: it’s tricky. 14216 </para> 14217 </section> 14218 </section> 14219 <section id="fiber.speculation"> 14220 <title><anchor id="speculation"/><link linkend="fiber.speculation">Specualtive 14221 execution</link></title> 14222 <bridgehead renderas="sect3" id="fiber.speculation.h0"> 14223 <phrase id="fiber.speculation.hardware_transactional_memory"/><link linkend="fiber.speculation.hardware_transactional_memory">Hardware 14224 transactional memory</link> 14225 </bridgehead> 14226 <para> 14227 With help of hardware transactional memory multiple logical processors execute 14228 a critical region speculatively, e.g. without explicit synchronization.<sbr/> 14229 If the transactional execution completes successfully, then all memory operations 14230 performed within the transactional region are commited without any inter-thread 14231 serialization.<sbr/> When the optimistic execution fails, the processor aborts 14232 the transaction and discards all performed modifications.<sbr/> In non-transactional 14233 code a single lock serializes the access to a critical region. With a transactional 14234 memory, multiple logical processor start a transaction and update the memory 14235 (the data) inside the ciritical region. Unless some logical processors try 14236 to update the same data, the transactions would always succeed. 14237 </para> 14238 <bridgehead renderas="sect3" id="fiber.speculation.h1"> 14239 <phrase id="fiber.speculation.intel_transactional_synchronisation_extensions__tsx_"/><link 14240 linkend="fiber.speculation.intel_transactional_synchronisation_extensions__tsx_">Intel 14241 Transactional Synchronisation Extensions (TSX)</link> 14242 </bridgehead> 14243 <para> 14244 TSX is Intel's implementation of hardware transactional memory in modern Intel 14245 processors<footnote id="fiber.speculation.f0"> 14246 <para> 14247 intel.com: <ulink url="https://software.intel.com/en-us/node/695149">Intel 14248 Transactional Synchronization Extensions</ulink> 14249 </para> 14250 </footnote>.<sbr/> In TSX the hardware keeps track of which cachelines have 14251 been read from and which have been written to in a transaction. The cache-line 14252 size (64-byte) and the n-way set associative cache determine the maximum size 14253 of memory in a transaction. For instance if a transaction modifies 9 cache-lines 14254 at a processor with a 8-way set associative cache, the transaction will always 14255 be aborted. 14256 </para> 14257 <note> 14258 <para> 14259 TXS is enabled if property <code><phrase role="identifier">htm</phrase><phrase 14260 role="special">=</phrase><phrase role="identifier">tsx</phrase></code> is 14261 specified at b2 command-line and <code><phrase role="identifier">BOOST_USE_TSX</phrase></code> 14262 is applied to the compiler. 14263 </para> 14264 </note> 14265 <note> 14266 <para> 14267 A TSX-transaction will be aborted if the floating point state is modified 14268 inside a critical region. As a consequence floating point operations, e.g. 14269 store/load of floating point related registers during a fiber (context) switch 14270 are disabled. 14271 </para> 14272 </note> 14273 <important> 14274 <para> 14275 TSX can not be used together with MSVC at this time! 14276 </para> 14277 </important> 14278 <para> 14279 Boost.Fiber uses TSX-enabled spinlocks to protect critical regions (see section 14280 <link linkend="tuning">Tuning</link>). 14281 </para> 14282 </section> 14283 <section id="fiber.numa"> 14284 <title><anchor id="numa"/><link linkend="fiber.numa">NUMA</link></title> 14285 <para> 14286 Modern micro-processors contain integrated memory controllers that are connected 14287 via channels to the memory. Accessing the memory can be organized in two kinds:<sbr/> 14288 Uniform Memory Access (UMA) and Non-Uniform Memory Access (NUMA). 14289 </para> 14290 <para> 14291 In contrast to UMA, that provides a centralized pool of memory (and thus does 14292 not scale after a certain number of processors), a NUMA architecture divides 14293 the memory into local and remote memory relative to the micro-processor.<sbr/> 14294 Local memory is directly attached to the processor's integrated memory controller. 14295 Memory connected to the memory controller of another micro-processor (multi-socket 14296 systems) is considered as remote memory. If a memory controller access remote 14297 memory it has to traverse the interconnect<footnote id="fiber.numa.f0"> 14298 <para> 14299 On x86 the interconnection is implemented by Intel's Quick Path Interconnect 14300 (QPI) and AMD's HyperTransport. 14301 </para> 14302 </footnote> and connect to the remote memory controller.<sbr/> Thus accessing 14303 remote memory adds additional latency overhead to local memory access. Because 14304 of the different memory locations, a NUMA-system experiences <emphasis>non-uniform</emphasis> 14305 memory access time.<sbr/> As a consequence the best performance is achieved 14306 by keeping the memory access local. 14307 </para> 14308 <para> 14309 <inlinemediaobject><imageobject><imagedata align="center" fileref="../../../../libs/fiber/doc/NUMA.png"></imagedata></imageobject> 14310 <textobject> 14311 <phrase>NUMA</phrase> 14312 </textobject> 14313 </inlinemediaobject> 14314 </para> 14315 <bridgehead renderas="sect3" id="fiber.numa.h0"> 14316 <phrase id="fiber.numa.numa_support_in_boost_fiber"/><link linkend="fiber.numa.numa_support_in_boost_fiber">NUMA 14317 support in Boost.Fiber</link> 14318 </bridgehead> 14319 <para> 14320 Because only a subset of the NUMA-functionality is exposed by several operating 14321 systems, Boost.Fiber provides only a minimalistic NUMA API. 14322 </para> 14323 <important> 14324 <para> 14325 In order to enable NUMA support, b2 property <code><phrase role="identifier">numa</phrase><phrase 14326 role="special">=</phrase><phrase role="identifier">on</phrase></code> must 14327 be specified and linked against additional library <code><phrase role="identifier">libboost_fiber_numa</phrase><phrase 14328 role="special">.</phrase><phrase role="identifier">so</phrase></code>. 14329 </para> 14330 </important> 14331 <important> 14332 <para> 14333 MinGW using pthread implementation is not supported on Windows. 14334 </para> 14335 </important> 14336 <table frame="all" id="fiber.numa.supported_functionality_operating_systems"> 14337 <title>Supported functionality/operating systems</title> 14338 <tgroup cols="7"> 14339 <thead> 14340 <row> 14341 <entry> 14342 </entry> 14343 <entry> 14344 <para> 14345 AIX 14346 </para> 14347 </entry> 14348 <entry> 14349 <para> 14350 FreeBSD 14351 </para> 14352 </entry> 14353 <entry> 14354 <para> 14355 HP/UX 14356 </para> 14357 </entry> 14358 <entry> 14359 <para> 14360 Linux 14361 </para> 14362 </entry> 14363 <entry> 14364 <para> 14365 Solaris 14366 </para> 14367 </entry> 14368 <entry> 14369 <para> 14370 Windows 14371 </para> 14372 </entry> 14373 </row> 14374 </thead> 14375 <tbody> 14376 <row> 14377 <entry> 14378 <para> 14379 pin thread 14380 </para> 14381 </entry> 14382 <entry> 14383 <para> 14384 + 14385 </para> 14386 </entry> 14387 <entry> 14388 <para> 14389 + 14390 </para> 14391 </entry> 14392 <entry> 14393 <para> 14394 + 14395 </para> 14396 </entry> 14397 <entry> 14398 <para> 14399 + 14400 </para> 14401 </entry> 14402 <entry> 14403 <para> 14404 + 14405 </para> 14406 </entry> 14407 <entry> 14408 <para> 14409 + 14410 </para> 14411 </entry> 14412 </row> 14413 <row> 14414 <entry> 14415 <para> 14416 logical CPUs/NUMA nodes 14417 </para> 14418 </entry> 14419 <entry> 14420 <para> 14421 + 14422 </para> 14423 </entry> 14424 <entry> 14425 <para> 14426 + 14427 </para> 14428 </entry> 14429 <entry> 14430 <para> 14431 + 14432 </para> 14433 </entry> 14434 <entry> 14435 <para> 14436 + 14437 </para> 14438 </entry> 14439 <entry> 14440 <para> 14441 + 14442 </para> 14443 </entry> 14444 <entry> 14445 <para> 14446 +<footnote id="fiber.numa.f1"> 14447 <para> 14448 Windows organizes logical cpus in groups of 64; boost.fiber maps 14449 {group-id,cpud-id} to a scalar equivalent to cpu ID of Linux (64 14450 * group ID + cpu ID). 14451 </para> 14452 </footnote> 14453 </para> 14454 </entry> 14455 </row> 14456 <row> 14457 <entry> 14458 <para> 14459 NUMA node distance 14460 </para> 14461 </entry> 14462 <entry> 14463 <para> 14464 - 14465 </para> 14466 </entry> 14467 <entry> 14468 <para> 14469 - 14470 </para> 14471 </entry> 14472 <entry> 14473 <para> 14474 - 14475 </para> 14476 </entry> 14477 <entry> 14478 <para> 14479 + 14480 </para> 14481 </entry> 14482 <entry> 14483 <para> 14484 - 14485 </para> 14486 </entry> 14487 <entry> 14488 <para> 14489 - 14490 </para> 14491 </entry> 14492 </row> 14493 <row> 14494 <entry> 14495 <para> 14496 tested on 14497 </para> 14498 </entry> 14499 <entry> 14500 <para> 14501 AIX 7.2 14502 </para> 14503 </entry> 14504 <entry> 14505 <para> 14506 FreeBSD 11 14507 </para> 14508 </entry> 14509 <entry> 14510 <para> 14511 - 14512 </para> 14513 </entry> 14514 <entry> 14515 <para> 14516 Arch Linux (4.10.13) 14517 </para> 14518 </entry> 14519 <entry> 14520 <para> 14521 OpenIndiana HIPSTER 14522 </para> 14523 </entry> 14524 <entry> 14525 <para> 14526 Windows 10 14527 </para> 14528 </entry> 14529 </row> 14530 </tbody> 14531 </tgroup> 14532 </table> 14533 <para> 14534 In order to keep the memory access local as possible, the NUMA topology must 14535 be evaluated. 14536 </para> 14537<programlisting><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">vector</phrase><phrase role="special"><</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">numa</phrase><phrase role="special">::</phrase><phrase role="identifier">node</phrase> <phrase role="special">></phrase> <phrase role="identifier">topo</phrase> <phrase role="special">=</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">numa</phrase><phrase role="special">::</phrase><phrase role="identifier">topology</phrase><phrase role="special">();</phrase> 14538<phrase role="keyword">for</phrase> <phrase role="special">(</phrase> <phrase role="keyword">auto</phrase> <phrase role="identifier">n</phrase> <phrase role="special">:</phrase> <phrase role="identifier">topo</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase> 14539 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cout</phrase> <phrase role="special"><<</phrase> <phrase role="string">"node: "</phrase> <phrase role="special"><<</phrase> <phrase role="identifier">n</phrase><phrase role="special">.</phrase><phrase role="identifier">id</phrase> <phrase role="special"><<</phrase> <phrase role="string">" | "</phrase><phrase role="special">;</phrase> 14540 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cout</phrase> <phrase role="special"><<</phrase> <phrase role="string">"cpus: "</phrase><phrase role="special">;</phrase> 14541 <phrase role="keyword">for</phrase> <phrase role="special">(</phrase> <phrase role="keyword">auto</phrase> <phrase role="identifier">cpu_id</phrase> <phrase role="special">:</phrase> <phrase role="identifier">n</phrase><phrase role="special">.</phrase><phrase role="identifier">logical_cpus</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase> 14542 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cout</phrase> <phrase role="special"><<</phrase> <phrase role="identifier">cpu_id</phrase> <phrase role="special"><<</phrase> <phrase role="string">" "</phrase><phrase role="special">;</phrase> 14543 <phrase role="special">}</phrase> 14544 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cout</phrase> <phrase role="special"><<</phrase> <phrase role="string">"| distance: "</phrase><phrase role="special">;</phrase> 14545 <phrase role="keyword">for</phrase> <phrase role="special">(</phrase> <phrase role="keyword">auto</phrase> <phrase role="identifier">d</phrase> <phrase role="special">:</phrase> <phrase role="identifier">n</phrase><phrase role="special">.</phrase><phrase role="identifier">distance</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase> 14546 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cout</phrase> <phrase role="special"><<</phrase> <phrase role="identifier">d</phrase> <phrase role="special"><<</phrase> <phrase role="string">" "</phrase><phrase role="special">;</phrase> 14547 <phrase role="special">}</phrase> 14548 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cout</phrase> <phrase role="special"><<</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">endl</phrase><phrase role="special">;</phrase> 14549<phrase role="special">}</phrase> 14550<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cout</phrase> <phrase role="special"><<</phrase> <phrase role="string">"done"</phrase> <phrase role="special"><<</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">endl</phrase><phrase role="special">;</phrase> 14551 14552<phrase role="identifier">output</phrase><phrase role="special">:</phrase> 14553 <phrase role="identifier">node</phrase><phrase role="special">:</phrase> <phrase role="number">0</phrase> <phrase role="special">|</phrase> <phrase role="identifier">cpus</phrase><phrase role="special">:</phrase> <phrase role="number">0</phrase> <phrase role="number">1</phrase> <phrase role="number">2</phrase> <phrase role="number">3</phrase> <phrase role="number">4</phrase> <phrase role="number">5</phrase> <phrase role="number">6</phrase> <phrase role="number">7</phrase> <phrase role="number">16</phrase> <phrase role="number">17</phrase> <phrase role="number">18</phrase> <phrase role="number">19</phrase> <phrase role="number">20</phrase> <phrase role="number">21</phrase> <phrase role="number">22</phrase> <phrase role="number">23</phrase> <phrase role="special">|</phrase> <phrase role="identifier">distance</phrase><phrase role="special">:</phrase> <phrase role="number">10</phrase> <phrase role="number">21</phrase> 14554 <phrase role="identifier">node</phrase><phrase role="special">:</phrase> <phrase role="number">1</phrase> <phrase role="special">|</phrase> <phrase role="identifier">cpus</phrase><phrase role="special">:</phrase> <phrase role="number">8</phrase> <phrase role="number">9</phrase> <phrase role="number">10</phrase> <phrase role="number">11</phrase> <phrase role="number">12</phrase> <phrase role="number">13</phrase> <phrase role="number">14</phrase> <phrase role="number">15</phrase> <phrase role="number">24</phrase> <phrase role="number">25</phrase> <phrase role="number">26</phrase> <phrase role="number">27</phrase> <phrase role="number">28</phrase> <phrase role="number">29</phrase> <phrase role="number">30</phrase> <phrase role="number">31</phrase> <phrase role="special">|</phrase> <phrase role="identifier">distance</phrase><phrase role="special">:</phrase> <phrase role="number">21</phrase> <phrase role="number">10</phrase> 14555 <phrase role="identifier">done</phrase> 14556</programlisting> 14557 <para> 14558 The example shows that the systems consits out of 2 NUMA-nodes, to each NUMA-node 14559 belong 16 logical cpus. The distance measures the costs to access the memory 14560 of another NUMA-node. A NUMA-node has always a distance <code><phrase role="number">10</phrase></code> 14561 to itself (lowest possible value).<sbr/> The position in the array corresponds 14562 with the NUMA-node ID. 14563 </para> 14564 <para> 14565 Some work-loads benefit from pinning threads to a logical cpus. For instance 14566 scheduling algorithm <link linkend="class_numa_work_stealing"><code>numa::work_stealing</code></link> pins the thread 14567 that runs the fiber scheduler to a logical cpu. This prevents the operating 14568 system scheduler to move the thread to another logical cpu that might run other 14569 fiber scheduler(s) or migrating the thread to a logical cpu part of another 14570 NUMA-node. 14571 </para> 14572<programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">thread</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">uint32_t</phrase> <phrase role="identifier">cpu_id</phrase><phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">uint32_t</phrase> <phrase role="identifier">node_id</phrase><phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">vector</phrase><phrase role="special"><</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">numa</phrase><phrase role="special">::</phrase><phrase role="identifier">node</phrase> <phrase role="special">></phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">topo</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase> 14573 <phrase role="comment">// thread registers itself at work-stealing scheduler</phrase> 14574 <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">use_scheduling_algorithm</phrase><phrase role="special"><</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">algo</phrase><phrase role="special">::</phrase><phrase role="identifier">numa</phrase><phrase role="special">::</phrase><phrase role="identifier">work_stealing</phrase> <phrase role="special">>(</phrase> <phrase role="identifier">cpu_id</phrase><phrase role="special">,</phrase> <phrase role="identifier">node_id</phrase><phrase role="special">,</phrase> <phrase role="identifier">topo</phrase><phrase role="special">);</phrase> 14575 <phrase role="special">...</phrase> 14576<phrase role="special">}</phrase> 14577 14578<phrase role="comment">// evaluate the NUMA topology</phrase> 14579<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">vector</phrase><phrase role="special"><</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">numa</phrase><phrase role="special">::</phrase><phrase role="identifier">node</phrase> <phrase role="special">></phrase> <phrase role="identifier">topo</phrase> <phrase role="special">=</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">numa</phrase><phrase role="special">::</phrase><phrase role="identifier">topology</phrase><phrase role="special">();</phrase> 14580<phrase role="comment">// start-thread runs on NUMA-node `0`</phrase> 14581<phrase role="keyword">auto</phrase> <phrase role="identifier">node</phrase> <phrase role="special">=</phrase> <phrase role="identifier">topo</phrase><phrase role="special">[</phrase><phrase role="number">0</phrase><phrase role="special">];</phrase> 14582<phrase role="comment">// start-thread is pinnded to first cpu ID in the list of logical cpus of NUMA-node `0`</phrase> 14583<phrase role="keyword">auto</phrase> <phrase role="identifier">start_cpu_id</phrase> <phrase role="special">=</phrase> <phrase role="special">*</phrase> <phrase role="identifier">node</phrase><phrase role="special">.</phrase><phrase role="identifier">logical_cpus</phrase><phrase role="special">.</phrase><phrase role="identifier">begin</phrase><phrase role="special">();</phrase> 14584<phrase role="comment">// start worker-threads first</phrase> 14585<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">vector</phrase><phrase role="special"><</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">thread</phrase> <phrase role="special">></phrase> <phrase role="identifier">threads</phrase><phrase role="special">;</phrase> 14586<phrase role="keyword">for</phrase> <phrase role="special">(</phrase> <phrase role="keyword">auto</phrase> <phrase role="special">&</phrase> <phrase role="identifier">node</phrase> <phrase role="special">:</phrase> <phrase role="identifier">topo</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase> 14587 <phrase role="keyword">for</phrase> <phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">uint32_t</phrase> <phrase role="identifier">cpu_id</phrase> <phrase role="special">:</phrase> <phrase role="identifier">node</phrase><phrase role="special">.</phrase><phrase role="identifier">logical_cpus</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase> 14588 <phrase role="comment">// exclude start-thread</phrase> 14589 <phrase role="keyword">if</phrase> <phrase role="special">(</phrase> <phrase role="identifier">start_cpu_id</phrase> <phrase role="special">!=</phrase> <phrase role="identifier">cpu_id</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase> 14590 <phrase role="comment">// spawn thread</phrase> 14591 <phrase role="identifier">threads</phrase><phrase role="special">.</phrase><phrase role="identifier">emplace_back</phrase><phrase role="special">(</phrase> <phrase role="identifier">thread</phrase><phrase role="special">,</phrase> <phrase role="identifier">cpu_id</phrase><phrase role="special">,</phrase> <phrase role="identifier">node</phrase><phrase role="special">.</phrase><phrase role="identifier">id</phrase><phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cref</phrase><phrase role="special">(</phrase> <phrase role="identifier">topo</phrase><phrase role="special">)</phrase> <phrase role="special">);</phrase> 14592 <phrase role="special">}</phrase> 14593 <phrase role="special">}</phrase> 14594<phrase role="special">}</phrase> 14595<phrase role="comment">// start-thread registers itself on work-stealing scheduler</phrase> 14596<phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">use_scheduling_algorithm</phrase><phrase role="special"><</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">algo</phrase><phrase role="special">::</phrase><phrase role="identifier">numa</phrase><phrase role="special">::</phrase><phrase role="identifier">work_stealing</phrase> <phrase role="special">>(</phrase> <phrase role="identifier">start_cpu_id</phrase><phrase role="special">,</phrase> <phrase role="identifier">node</phrase><phrase role="special">.</phrase><phrase role="identifier">id</phrase><phrase role="special">,</phrase> <phrase role="identifier">topo</phrase><phrase role="special">);</phrase> 14597<phrase role="special">...</phrase> 14598</programlisting> 14599 <para> 14600 The example evaluates the NUMA topology with <code><phrase role="identifier">boost</phrase><phrase 14601 role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase 14602 role="special">::</phrase><phrase role="identifier">numa</phrase><phrase role="special">::</phrase><phrase 14603 role="identifier">topology</phrase><phrase role="special">()</phrase></code> 14604 and spawns for each logical cpu a thread. Each spawned thread installs the 14605 NUMA-aware work-stealing scheduler. The scheduler pins the thread to the logical 14606 cpu that was specified at construction.<sbr/> If the local queue of one thread 14607 runs out of ready fibers, the thread tries to steal a ready fiber from another 14608 thread running at logical cpu that belong to the same NUMA-node (local memory 14609 access). If no fiber could be stolen, the thread tries to steal fibers from 14610 logical cpus part of other NUMA-nodes (remote memory access). 14611 </para> 14612 <bridgehead renderas="sect3" id="fiber.numa.h1"> 14613 <phrase id="fiber.numa.synopsis"/><link linkend="fiber.numa.synopsis">Synopsis</link> 14614 </bridgehead> 14615<programlisting><phrase role="preprocessor">#include</phrase> <phrase role="special"><</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">fiber</phrase><phrase role="special">/</phrase><phrase role="identifier">numa</phrase><phrase role="special">/</phrase><phrase role="identifier">pin_thread</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">></phrase> 14616<phrase role="preprocessor">#include</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">numa</phrase><phrase role="special">/</phrase><phrase role="identifier">topology</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">></phrase> 14617 14618<phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase> 14619<phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase> 14620<phrase role="keyword">namespace</phrase> <phrase role="identifier">numa</phrase> <phrase role="special">{</phrase> 14621 14622<phrase role="keyword">struct</phrase> <phrase role="identifier">node</phrase> <phrase role="special">{</phrase> 14623 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">uint32_t</phrase> <phrase role="identifier">id</phrase><phrase role="special">;</phrase> 14624 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">set</phrase><phrase role="special"><</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">uint32_t</phrase> <phrase role="special">></phrase> <phrase role="identifier">logical_cpus</phrase><phrase role="special">;</phrase> 14625 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">vector</phrase><phrase role="special"><</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">uint32_t</phrase> <phrase role="special">></phrase> <phrase role="identifier">distance</phrase><phrase role="special">;</phrase> 14626<phrase role="special">};</phrase> 14627<phrase role="keyword">bool</phrase> <phrase role="keyword">operator</phrase><phrase role="special"><(</phrase> <phrase role="identifier">node</phrase> <phrase role="keyword">const</phrase><phrase role="special">&,</phrase> <phrase role="identifier">node</phrase> <phrase role="keyword">const</phrase><phrase role="special">&)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 14628 14629<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">vector</phrase><phrase role="special"><</phrase> <phrase role="identifier">node</phrase> <phrase role="special">></phrase> <phrase role="identifier">topology</phrase><phrase role="special">();</phrase> 14630 14631<phrase role="keyword">void</phrase> <phrase role="identifier">pin_thread</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">uint32_t</phrase><phrase role="special">);</phrase> 14632<phrase role="keyword">void</phrase> <phrase role="identifier">pin_thread</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">uint32_t</phrase><phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">thread</phrase><phrase role="special">::</phrase><phrase role="identifier">native_handle_type</phrase><phrase role="special">);</phrase> 14633 14634<phrase role="special">}}}</phrase> 14635 14636<phrase role="preprocessor">#include</phrase> <phrase role="special"><</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">fiber</phrase><phrase role="special">/</phrase><phrase role="identifier">numa</phrase><phrase role="special">/</phrase><phrase role="identifier">algo</phrase><phrase role="special">/</phrase><phrase role="identifier">work_stealing</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">></phrase> 14637 14638<phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase> 14639<phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase> 14640<phrase role="keyword">namespace</phrase> <phrase role="identifier">numa</phrase> <phrase role="special">{</phrase> 14641<phrase role="keyword">namespace</phrase> <phrase role="identifier">algo</phrase> <phrase role="special">{</phrase> 14642 14643<phrase role="keyword">class</phrase> <phrase role="identifier">work_stealing</phrase><phrase role="special">;</phrase> 14644 14645<phrase role="special">}}}</phrase> 14646</programlisting> 14647 <para> 14648 <bridgehead renderas="sect4" id="class_numa_node_bridgehead"> 14649 <phrase id="class_numa_node"/> 14650 <link linkend="class_numa_node">Class <code>numa::node</code></link> 14651</bridgehead> 14652 </para> 14653<programlisting><phrase role="preprocessor">#include</phrase> <phrase role="special"><</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">fiber</phrase><phrase role="special">/</phrase><phrase role="identifier">numa</phrase><phrase role="special">/</phrase><phrase role="identifier">topology</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">></phrase> 14654 14655<phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase> 14656<phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase> 14657<phrase role="keyword">namespace</phrase> <phrase role="identifier">numa</phrase> <phrase role="special">{</phrase> 14658 14659<phrase role="keyword">struct</phrase> <phrase role="identifier">node</phrase> <phrase role="special">{</phrase> 14660 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">uint32_t</phrase> <phrase role="identifier">id</phrase><phrase role="special">;</phrase> 14661 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">set</phrase><phrase role="special"><</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">uint32_t</phrase> <phrase role="special">></phrase> <phrase role="identifier">logical_cpus</phrase><phrase role="special">;</phrase> 14662 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">vector</phrase><phrase role="special"><</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">uint32_t</phrase> <phrase role="special">></phrase> <phrase role="identifier">distance</phrase><phrase role="special">;</phrase> 14663<phrase role="special">};</phrase> 14664<phrase role="keyword">bool</phrase> <phrase role="keyword">operator</phrase><phrase role="special"><(</phrase> <phrase role="identifier">node</phrase> <phrase role="keyword">const</phrase><phrase role="special">&,</phrase> <phrase role="identifier">node</phrase> <phrase role="keyword">const</phrase><phrase role="special">&)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 14665 14666<phrase role="special">}}}</phrase> 14667</programlisting> 14668 <para> 14669 <bridgehead renderas="sect4" id="numa_node_id_bridgehead"> 14670 <phrase id="numa_node_id"/> 14671 <link linkend="numa_node_id">Data member <code>id</code></link> 14672</bridgehead> 14673 </para> 14674<programlisting><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">uint32_t</phrase> <phrase role="identifier">id</phrase><phrase role="special">;</phrase> 14675</programlisting> 14676 <variablelist> 14677 <title></title> 14678 <varlistentry> 14679 <term>Effects:</term> 14680 <listitem> 14681 <para> 14682 ID of the NUMA-node 14683 </para> 14684 </listitem> 14685 </varlistentry> 14686 </variablelist> 14687 <para> 14688 <bridgehead renderas="sect4" id="numa_node_logical_cpus_bridgehead"> 14689 <phrase id="numa_node_logical_cpus"/> 14690 <link linkend="numa_node_logical_cpus">Data 14691 member <code>logical_cpus</code></link> 14692</bridgehead> 14693 </para> 14694<programlisting><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">set</phrase><phrase role="special"><</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">uint32_t</phrase> <phrase role="special">></phrase> <phrase role="identifier">logical_cpus</phrase><phrase role="special">;</phrase> 14695</programlisting> 14696 <variablelist> 14697 <title></title> 14698 <varlistentry> 14699 <term>Effects:</term> 14700 <listitem> 14701 <para> 14702 set of logical cpu IDs belonging to the NUMA-node 14703 </para> 14704 </listitem> 14705 </varlistentry> 14706 </variablelist> 14707 <para> 14708 <bridgehead renderas="sect4" id="numa_node_distance_bridgehead"> 14709 <phrase id="numa_node_distance"/> 14710 <link linkend="numa_node_distance">Data member 14711 <code>distance</code></link> 14712</bridgehead> 14713 </para> 14714<programlisting><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">vector</phrase><phrase role="special"><</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">uint32_t</phrase> <phrase role="special">></phrase> <phrase role="identifier">distance</phrase><phrase role="special">;</phrase> 14715</programlisting> 14716 <variablelist> 14717 <title></title> 14718 <varlistentry> 14719 <term>Effects:</term> 14720 <listitem> 14721 <para> 14722 The distance between NUMA-nodes describe the cots of accessing the remote 14723 memory. 14724 </para> 14725 </listitem> 14726 </varlistentry> 14727 <varlistentry> 14728 <term>Note:</term> 14729 <listitem> 14730 <para> 14731 A NUMA-node has a distance of <code><phrase role="number">10</phrase></code> 14732 to itself, remote NUMA-nodes have a distance > <code><phrase role="number">10</phrase></code>. 14733 The index in the array corresponds to the ID <code><phrase role="identifier">id</phrase></code> 14734 of the NUMA-node. At the moment only Linux returns the correct distances, 14735 for all other operating systems remote NUMA-nodes get a default value 14736 of <code><phrase role="number">20</phrase></code>. 14737 </para> 14738 </listitem> 14739 </varlistentry> 14740 </variablelist> 14741 <para> 14742 <bridgehead renderas="sect4" id="numa_node_operator_less_bridgehead"> 14743 <phrase id="numa_node_operator_less"/> 14744 <link linkend="numa_node_operator_less">Member 14745 function <code>operator<</code>()</link> 14746</bridgehead> 14747 </para> 14748<programlisting><phrase role="keyword">bool</phrase> <phrase role="keyword">operator</phrase><phrase role="special"><(</phrase> <phrase role="identifier">node</phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">lhs</phrase><phrase role="special">,</phrase> <phrase role="identifier">node</phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">rhs</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 14749</programlisting> 14750 <variablelist> 14751 <title></title> 14752 <varlistentry> 14753 <term>Returns:</term> 14754 <listitem> 14755 <para> 14756 <code><phrase role="keyword">true</phrase></code> if <code><phrase role="identifier">lhs</phrase> 14757 <phrase role="special">!=</phrase> <phrase role="identifier">rhs</phrase></code> 14758 is true and the implementation-defined total order of <code><phrase role="identifier">node</phrase><phrase 14759 role="special">::</phrase><phrase role="identifier">id</phrase></code> 14760 values places <code><phrase role="identifier">lhs</phrase></code> before 14761 <code><phrase role="identifier">rhs</phrase></code>, false otherwise. 14762 </para> 14763 </listitem> 14764 </varlistentry> 14765 <varlistentry> 14766 <term>Throws:</term> 14767 <listitem> 14768 <para> 14769 Nothing. 14770 </para> 14771 </listitem> 14772 </varlistentry> 14773 </variablelist> 14774 <para> 14775 <bridgehead renderas="sect4" id="numa_topology_bridgehead"> 14776 <phrase id="numa_topology"/> 14777 <link linkend="numa_topology">Non-member function <code>numa::topology()</code></link> 14778</bridgehead> 14779 </para> 14780<programlisting><phrase role="preprocessor">#include</phrase> <phrase role="special"><</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">fiber</phrase><phrase role="special">/</phrase><phrase role="identifier">numa</phrase><phrase role="special">/</phrase><phrase role="identifier">topology</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">></phrase> 14781 14782<phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase> 14783<phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase> 14784<phrase role="keyword">namespace</phrase> <phrase role="identifier">numa</phrase> <phrase role="special">{</phrase> 14785 14786<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">vector</phrase><phrase role="special"><</phrase> <phrase role="identifier">node</phrase> <phrase role="special">></phrase> <phrase role="identifier">topology</phrase><phrase role="special">();</phrase> 14787 14788<phrase role="special">}}}</phrase> 14789</programlisting> 14790 <variablelist> 14791 <title></title> 14792 <varlistentry> 14793 <term>Effects:</term> 14794 <listitem> 14795 <para> 14796 Evaluates the NUMA topology. 14797 </para> 14798 </listitem> 14799 </varlistentry> 14800 <varlistentry> 14801 <term>Returns:</term> 14802 <listitem> 14803 <para> 14804 a vector of NUMA-nodes describing the NUMA architecture of the system 14805 (each element represents a NUMA-node). 14806 </para> 14807 </listitem> 14808 </varlistentry> 14809 <varlistentry> 14810 <term>Throws:</term> 14811 <listitem> 14812 <para> 14813 <code><phrase role="identifier">system_error</phrase></code> 14814 </para> 14815 </listitem> 14816 </varlistentry> 14817 </variablelist> 14818 <para> 14819 <bridgehead renderas="sect4" id="numa_pin_thread_bridgehead"> 14820 <phrase id="numa_pin_thread"/> 14821 <link linkend="numa_pin_thread">Non-member function 14822 <code>numa::pin_thread()</code></link> 14823</bridgehead> 14824 </para> 14825<programlisting><phrase role="preprocessor">#include</phrase> <phrase role="special"><</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">fiber</phrase><phrase role="special">/</phrase><phrase role="identifier">numa</phrase><phrase role="special">/</phrase><phrase role="identifier">pin_thread</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">></phrase> 14826 14827<phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase> 14828<phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase> 14829<phrase role="keyword">namespace</phrase> <phrase role="identifier">numa</phrase> <phrase role="special">{</phrase> 14830 14831<phrase role="keyword">void</phrase> <phrase role="identifier">pin_thread</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">uint32_t</phrase> <phrase role="identifier">cpu_id</phrase><phrase role="special">);</phrase> 14832<phrase role="keyword">void</phrase> <phrase role="identifier">pin_thread</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">uint32_t</phrase> <phrase role="identifier">cpu_id</phrase><phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">thread</phrase><phrase role="special">::</phrase><phrase role="identifier">native_handle_type</phrase> <phrase role="identifier">h</phrase><phrase role="special">);</phrase> 14833 14834<phrase role="special">}}}</phrase> 14835</programlisting> 14836 <variablelist> 14837 <title></title> 14838 <varlistentry> 14839 <term>Effects:</term> 14840 <listitem> 14841 <para> 14842 First version pins <code><phrase role="keyword">this</phrase> <phrase 14843 role="identifier">thread</phrase></code> to the logical cpu with ID 14844 <code><phrase role="identifier">cpu_id</phrase></code>, e.g. the operating 14845 system scheduler will not migrate the thread to another logical cpu. 14846 The second variant pins the thread with the native ID <code><phrase role="identifier">h</phrase></code> 14847 to logical cpu with ID <code><phrase role="identifier">cpu_id</phrase></code>. 14848 </para> 14849 </listitem> 14850 </varlistentry> 14851 <varlistentry> 14852 <term>Throws:</term> 14853 <listitem> 14854 <para> 14855 <code><phrase role="identifier">system_error</phrase></code> 14856 </para> 14857 </listitem> 14858 </varlistentry> 14859 </variablelist> 14860 <para> 14861 <bridgehead renderas="sect4" id="class_numa_work_stealing_bridgehead"> 14862 <phrase id="class_numa_work_stealing"/> 14863 <link linkend="class_numa_work_stealing">Class 14864 <code>numa::work_stealing</code></link> 14865</bridgehead> 14866 </para> 14867 <para> 14868 This class implements <link linkend="class_algorithm"><code>algorithm</code></link>; the thread running this scheduler 14869 is pinned to the given logical cpu. If the local ready-queue runs out of ready 14870 fibers, ready fibers are stolen from other schedulers that run on logical cpus 14871 that belong to the same NUMA-node (local memory access).<sbr/> If no ready 14872 fibers can be stolen from the local NUMA-node, the algorithm selects schedulers 14873 running on other NUMA-nodes (remote memory access).<sbr/> The victim scheduler 14874 (from which a ready fiber is stolen) is selected at random. 14875 </para> 14876<programlisting><phrase role="preprocessor">#include</phrase> <phrase role="special"><</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">fiber</phrase><phrase role="special">/</phrase><phrase role="identifier">numa</phrase><phrase role="special">/</phrase><phrase role="identifier">algo</phrase><phrase role="special">/</phrase><phrase role="identifier">work_stealing</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">></phrase> 14877 14878<phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase> 14879<phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase> 14880<phrase role="keyword">namespace</phrase> <phrase role="identifier">numa</phrase> <phrase role="special">{</phrase> 14881<phrase role="keyword">namespace</phrase> <phrase role="identifier">algo</phrase> <phrase role="special">{</phrase> 14882 14883<phrase role="keyword">class</phrase> <phrase role="identifier">work_stealing</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <phrase role="identifier">algorithm</phrase> <phrase role="special">{</phrase> 14884<phrase role="keyword">public</phrase><phrase role="special">:</phrase> 14885 <phrase role="identifier">work_stealing</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">uint32_t</phrase> <phrase role="identifier">cpu_id</phrase><phrase role="special">,</phrase> 14886 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">uint32_t</phrase> <phrase role="identifier">node_id</phrase><phrase role="special">,</phrase> 14887 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">vector</phrase><phrase role="special"><</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">numa</phrase><phrase role="special">::</phrase><phrase role="identifier">node</phrase> <phrase role="special">></phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">topo</phrase><phrase role="special">,</phrase> 14888 <phrase role="keyword">bool</phrase> <phrase role="identifier">suspend</phrase> <phrase role="special">=</phrase> <phrase role="keyword">false</phrase><phrase role="special">);</phrase> 14889 14890 <phrase role="identifier">work_stealing</phrase><phrase role="special">(</phrase> <phrase role="identifier">work_stealing</phrase> <phrase role="keyword">const</phrase><phrase role="special">&)</phrase> <phrase role="special">=</phrase> <phrase role="keyword">delete</phrase><phrase role="special">;</phrase> 14891 <phrase role="identifier">work_stealing</phrase><phrase role="special">(</phrase> <phrase role="identifier">work_stealing</phrase> <phrase role="special">&&)</phrase> <phrase role="special">=</phrase> <phrase role="keyword">delete</phrase><phrase role="special">;</phrase> 14892 14893 <phrase role="identifier">work_stealing</phrase> <phrase role="special">&</phrase> <phrase role="keyword">operator</phrase><phrase role="special">=(</phrase> <phrase role="identifier">work_stealing</phrase> <phrase role="keyword">const</phrase><phrase role="special">&)</phrase> <phrase role="special">=</phrase> <phrase role="keyword">delete</phrase><phrase role="special">;</phrase> 14894 <phrase role="identifier">work_stealing</phrase> <phrase role="special">&</phrase> <phrase role="keyword">operator</phrase><phrase role="special">=(</phrase> <phrase role="identifier">work_stealing</phrase> <phrase role="special">&&)</phrase> <phrase role="special">=</phrase> <phrase role="keyword">delete</phrase><phrase role="special">;</phrase> 14895 14896 <phrase role="keyword">virtual</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">awakened</phrase><phrase role="special">(</phrase> <phrase role="identifier">context</phrase> <phrase role="special">*)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 14897 14898 <phrase role="keyword">virtual</phrase> <phrase role="identifier">context</phrase> <phrase role="special">*</phrase> <phrase role="identifier">pick_next</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 14899 14900 <phrase role="keyword">virtual</phrase> <phrase role="keyword">bool</phrase> <phrase role="identifier">has_ready_fibers</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 14901 14902 <phrase role="keyword">virtual</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">suspend_until</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">steady_clock</phrase><phrase role="special">::</phrase><phrase role="identifier">time_point</phrase> <phrase role="keyword">const</phrase><phrase role="special">&)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 14903 14904 <phrase role="keyword">virtual</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">notify</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 14905<phrase role="special">};</phrase> 14906 14907<phrase role="special">}}}}</phrase> 14908</programlisting> 14909 <bridgehead renderas="sect3" id="fiber.numa.h2"> 14910 <phrase id="fiber.numa.constructor"/><link linkend="fiber.numa.constructor">Constructor</link> 14911 </bridgehead> 14912<programlisting><phrase role="identifier">work_stealing</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">uint32_t</phrase> <phrase role="identifier">cpu_id</phrase><phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">uint32_t</phrase> <phrase role="identifier">node_id</phrase><phrase role="special">,</phrase> 14913 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">vector</phrase><phrase role="special"><</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">numa</phrase><phrase role="special">::</phrase><phrase role="identifier">node</phrase> <phrase role="special">></phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">topo</phrase><phrase role="special">,</phrase> 14914 <phrase role="keyword">bool</phrase> <phrase role="identifier">suspend</phrase> <phrase role="special">=</phrase> <phrase role="keyword">false</phrase><phrase role="special">);</phrase> 14915</programlisting> 14916 <variablelist> 14917 <title></title> 14918 <varlistentry> 14919 <term>Effects:</term> 14920 <listitem> 14921 <para> 14922 Constructs work-stealing scheduling algorithm. The thread is pinned to 14923 logical cpu with ID <code><phrase role="identifier">cpu_id</phrase></code>. 14924 If local ready-queue runs out of ready fibers, ready fibers are stolen 14925 from other schedulers using <code><phrase role="identifier">topology</phrase></code> 14926 (represents the NUMA-topology of the system). 14927 </para> 14928 </listitem> 14929 </varlistentry> 14930 <varlistentry> 14931 <term>Throws:</term> 14932 <listitem> 14933 <para> 14934 <code><phrase role="identifier">system_error</phrase></code> 14935 </para> 14936 </listitem> 14937 </varlistentry> 14938 <varlistentry> 14939 <term>Note:</term> 14940 <listitem> 14941 <para> 14942 If <code><phrase role="identifier">suspend</phrase></code> is set to 14943 <code><phrase role="keyword">true</phrase></code>, then the scheduler 14944 suspends if no ready fiber could be stolen. The scheduler will by woken 14945 up if a sleeping fiber times out or it was notified from remote (other 14946 thread or fiber scheduler). 14947 </para> 14948 </listitem> 14949 </varlistentry> 14950 </variablelist> 14951 <para> 14952 <bridgehead renderas="sect4" id="numa_work_stealing_awakened_bridgehead"> 14953 <phrase id="numa_work_stealing_awakened"/> 14954 <link linkend="numa_work_stealing_awakened">Member 14955 function <code>awakened</code>()</link> 14956</bridgehead> 14957 </para> 14958<programlisting><phrase role="keyword">virtual</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">awakened</phrase><phrase role="special">(</phrase> <phrase role="identifier">context</phrase> <phrase role="special">*</phrase> <phrase role="identifier">f</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 14959</programlisting> 14960 <variablelist> 14961 <title></title> 14962 <varlistentry> 14963 <term>Effects:</term> 14964 <listitem> 14965 <para> 14966 Enqueues fiber <code><phrase role="identifier">f</phrase></code> onto 14967 the shared ready queue. 14968 </para> 14969 </listitem> 14970 </varlistentry> 14971 <varlistentry> 14972 <term>Throws:</term> 14973 <listitem> 14974 <para> 14975 Nothing. 14976 </para> 14977 </listitem> 14978 </varlistentry> 14979 </variablelist> 14980 <para> 14981 <bridgehead renderas="sect4" id="numa_work_stealing_pick_next_bridgehead"> 14982 <phrase id="numa_work_stealing_pick_next"/> 14983 <link linkend="numa_work_stealing_pick_next">Member 14984 function <code>pick_next</code>()</link> 14985</bridgehead> 14986 </para> 14987<programlisting><phrase role="keyword">virtual</phrase> <phrase role="identifier">context</phrase> <phrase role="special">*</phrase> <phrase role="identifier">pick_next</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 14988</programlisting> 14989 <variablelist> 14990 <title></title> 14991 <varlistentry> 14992 <term>Returns:</term> 14993 <listitem> 14994 <para> 14995 the fiber at the head of the ready queue, or <code><phrase role="keyword">nullptr</phrase></code> 14996 if the queue is empty. 14997 </para> 14998 </listitem> 14999 </varlistentry> 15000 <varlistentry> 15001 <term>Throws:</term> 15002 <listitem> 15003 <para> 15004 Nothing. 15005 </para> 15006 </listitem> 15007 </varlistentry> 15008 <varlistentry> 15009 <term>Note:</term> 15010 <listitem> 15011 <para> 15012 Placing ready fibers onto the tail of the sahred queue, and returning 15013 them from the head of that queue, shares the thread between ready fibers 15014 in round-robin fashion. 15015 </para> 15016 </listitem> 15017 </varlistentry> 15018 </variablelist> 15019 <para> 15020 <bridgehead renderas="sect4" id="numa_work_stealing_has_ready_fibers_bridgehead"> 15021 <phrase id="numa_work_stealing_has_ready_fibers"/> 15022 <link linkend="numa_work_stealing_has_ready_fibers">Member 15023 function <code>has_ready_fibers</code>()</link> 15024</bridgehead> 15025 </para> 15026<programlisting><phrase role="keyword">virtual</phrase> <phrase role="keyword">bool</phrase> <phrase role="identifier">has_ready_fibers</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 15027</programlisting> 15028 <variablelist> 15029 <title></title> 15030 <varlistentry> 15031 <term>Returns:</term> 15032 <listitem> 15033 <para> 15034 <code><phrase role="keyword">true</phrase></code> if scheduler has fibers 15035 ready to run. 15036 </para> 15037 </listitem> 15038 </varlistentry> 15039 <varlistentry> 15040 <term>Throws:</term> 15041 <listitem> 15042 <para> 15043 Nothing. 15044 </para> 15045 </listitem> 15046 </varlistentry> 15047 </variablelist> 15048 <para> 15049 <bridgehead renderas="sect4" id="numa_work_stealing_suspend_until_bridgehead"> 15050 <phrase id="numa_work_stealing_suspend_until"/> 15051 <link linkend="numa_work_stealing_suspend_until">Member 15052 function <code>suspend_until</code>()</link> 15053</bridgehead> 15054 </para> 15055<programlisting><phrase role="keyword">virtual</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">suspend_until</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">steady_clock</phrase><phrase role="special">::</phrase><phrase role="identifier">time_point</phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">abs_time</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase><phrase role="special">;</phrase> 15056</programlisting> 15057 <variablelist> 15058 <title></title> 15059 <varlistentry> 15060 <term>Effects:</term> 15061 <listitem> 15062 <para> 15063 Informs <code><phrase role="identifier">work_stealing</phrase></code> 15064 that no ready fiber will be available until time-point <code><phrase 15065 role="identifier">abs_time</phrase></code>. This implementation blocks 15066 in <ulink url="http://en.cppreference.com/w/cpp/thread/condition_variable/wait_until"><code><phrase 15067 role="identifier">std</phrase><phrase role="special">::</phrase><phrase 15068 role="identifier">condition_variable</phrase><phrase role="special">::</phrase><phrase 15069 role="identifier">wait_until</phrase><phrase role="special">()</phrase></code></ulink>. 15070 </para> 15071 </listitem> 15072 </varlistentry> 15073 <varlistentry> 15074 <term>Throws:</term> 15075 <listitem> 15076 <para> 15077 Nothing. 15078 </para> 15079 </listitem> 15080 </varlistentry> 15081 </variablelist> 15082 <para> 15083 <bridgehead renderas="sect4" id="numa_work_stealing_notify_bridgehead"> 15084 <phrase id="numa_work_stealing_notify"/> 15085 <link linkend="numa_work_stealing_notify">Member 15086 function <code>notify</code>()</link> 15087</bridgehead> 15088 </para> 15089<programlisting><phrase role="keyword">virtual</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">notify</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase> <phrase role="special">=</phrase> <phrase role="number">0</phrase><phrase role="special">;</phrase> 15090</programlisting> 15091 <variablelist> 15092 <title></title> 15093 <varlistentry> 15094 <term>Effects:</term> 15095 <listitem> 15096 <para> 15097 Wake up a pending call to <link linkend="work_stealing_suspend_until"><code>work_stealing::suspend_until()</code></link>, 15098 some fibers might be ready. This implementation wakes <code><phrase role="identifier">suspend_until</phrase><phrase 15099 role="special">()</phrase></code> via <ulink url="http://en.cppreference.com/w/cpp/thread/condition_variable/notify_all"><code><phrase 15100 role="identifier">std</phrase><phrase role="special">::</phrase><phrase 15101 role="identifier">condition_variable</phrase><phrase role="special">::</phrase><phrase 15102 role="identifier">notify_all</phrase><phrase role="special">()</phrase></code></ulink>. 15103 </para> 15104 </listitem> 15105 </varlistentry> 15106 <varlistentry> 15107 <term>Throws:</term> 15108 <listitem> 15109 <para> 15110 Nothing. 15111 </para> 15112 </listitem> 15113 </varlistentry> 15114 </variablelist> 15115 </section> 15116 <section id="fiber.gpu_computing"> 15117 <title><link linkend="fiber.gpu_computing">GPU computing</link></title> 15118 <section id="fiber.gpu_computing.cuda"> 15119 <title><anchor id="cuda"/><link linkend="fiber.gpu_computing.cuda">CUDA</link></title> 15120 <para> 15121 <ulink url="http://developer.nvidia.com/cuda-zone/">CUDA (Compute Unified 15122 Device Architecture)</ulink> is a platform for parallel computing on NVIDIA 15123 GPUs. The application programming interface of CUDA gives access to GPU's 15124 instruction set and computation resources (Execution of compute kernels). 15125 </para> 15126 <bridgehead renderas="sect4" id="fiber.gpu_computing.cuda.h0"> 15127 <phrase id="fiber.gpu_computing.cuda.synchronization_with_cuda_streams"/><link 15128 linkend="fiber.gpu_computing.cuda.synchronization_with_cuda_streams">Synchronization 15129 with CUDA streams</link> 15130 </bridgehead> 15131 <para> 15132 CUDA operation such as compute kernels or memory transfer (between host and 15133 device) can be grouped/queued by CUDA streams. are executed on the GPUs. 15134 Boost.Fiber enables a fiber to sleep (suspend) till a CUDA stream has completed 15135 its operations. This enables applications to run other fibers on the CPU 15136 without the need to spawn an additional OS-threads. And resume the fiber 15137 when the CUDA streams has finished. 15138 </para> 15139<programlisting><phrase role="identifier">__global__</phrase> 15140<phrase role="keyword">void</phrase> <phrase role="identifier">kernel</phrase><phrase role="special">(</phrase> <phrase role="keyword">int</phrase> <phrase role="identifier">size</phrase><phrase role="special">,</phrase> <phrase role="keyword">int</phrase> <phrase role="special">*</phrase> <phrase role="identifier">a</phrase><phrase role="special">,</phrase> <phrase role="keyword">int</phrase> <phrase role="special">*</phrase> <phrase role="identifier">b</phrase><phrase role="special">,</phrase> <phrase role="keyword">int</phrase> <phrase role="special">*</phrase> <phrase role="identifier">c</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase> 15141 <phrase role="keyword">int</phrase> <phrase role="identifier">idx</phrase> <phrase role="special">=</phrase> <phrase role="identifier">threadIdx</phrase><phrase role="special">.</phrase><phrase role="identifier">x</phrase> <phrase role="special">+</phrase> <phrase role="identifier">blockIdx</phrase><phrase role="special">.</phrase><phrase role="identifier">x</phrase> <phrase role="special">*</phrase> <phrase role="identifier">blockDim</phrase><phrase role="special">.</phrase><phrase role="identifier">x</phrase><phrase role="special">;</phrase> 15142 <phrase role="keyword">if</phrase> <phrase role="special">(</phrase> <phrase role="identifier">idx</phrase> <phrase role="special"><</phrase> <phrase role="identifier">size</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase> 15143 <phrase role="keyword">int</phrase> <phrase role="identifier">idx1</phrase> <phrase role="special">=</phrase> <phrase role="special">(</phrase><phrase role="identifier">idx</phrase> <phrase role="special">+</phrase> <phrase role="number">1</phrase><phrase role="special">)</phrase> <phrase role="special">%</phrase> <phrase role="number">256</phrase><phrase role="special">;</phrase> 15144 <phrase role="keyword">int</phrase> <phrase role="identifier">idx2</phrase> <phrase role="special">=</phrase> <phrase role="special">(</phrase><phrase role="identifier">idx</phrase> <phrase role="special">+</phrase> <phrase role="number">2</phrase><phrase role="special">)</phrase> <phrase role="special">%</phrase> <phrase role="number">256</phrase><phrase role="special">;</phrase> 15145 <phrase role="keyword">float</phrase> <phrase role="identifier">as</phrase> <phrase role="special">=</phrase> <phrase role="special">(</phrase><phrase role="identifier">a</phrase><phrase role="special">[</phrase><phrase role="identifier">idx</phrase><phrase role="special">]</phrase> <phrase role="special">+</phrase> <phrase role="identifier">a</phrase><phrase role="special">[</phrase><phrase role="identifier">idx1</phrase><phrase role="special">]</phrase> <phrase role="special">+</phrase> <phrase role="identifier">a</phrase><phrase role="special">[</phrase><phrase role="identifier">idx2</phrase><phrase role="special">])</phrase> <phrase role="special">/</phrase> <phrase role="number">3.0f</phrase><phrase role="special">;</phrase> 15146 <phrase role="keyword">float</phrase> <phrase role="identifier">bs</phrase> <phrase role="special">=</phrase> <phrase role="special">(</phrase><phrase role="identifier">b</phrase><phrase role="special">[</phrase><phrase role="identifier">idx</phrase><phrase role="special">]</phrase> <phrase role="special">+</phrase> <phrase role="identifier">b</phrase><phrase role="special">[</phrase><phrase role="identifier">idx1</phrase><phrase role="special">]</phrase> <phrase role="special">+</phrase> <phrase role="identifier">b</phrase><phrase role="special">[</phrase><phrase role="identifier">idx2</phrase><phrase role="special">])</phrase> <phrase role="special">/</phrase> <phrase role="number">3.0f</phrase><phrase role="special">;</phrase> 15147 <phrase role="identifier">c</phrase><phrase role="special">[</phrase><phrase role="identifier">idx</phrase><phrase role="special">]</phrase> <phrase role="special">=</phrase> <phrase role="special">(</phrase><phrase role="identifier">as</phrase> <phrase role="special">+</phrase> <phrase role="identifier">bs</phrase><phrase role="special">)</phrase> <phrase role="special">/</phrase> <phrase role="number">2</phrase><phrase role="special">;</phrase> 15148 <phrase role="special">}</phrase> 15149<phrase role="special">}</phrase> 15150 15151<phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">fiber</phrase> <phrase role="identifier">f</phrase><phrase role="special">([&</phrase><phrase role="identifier">done</phrase><phrase role="special">]{</phrase> 15152 <phrase role="identifier">cudaStream_t</phrase> <phrase role="identifier">stream</phrase><phrase role="special">;</phrase> 15153 <phrase role="identifier">cudaStreamCreate</phrase><phrase role="special">(</phrase> <phrase role="special">&</phrase> <phrase role="identifier">stream</phrase><phrase role="special">);</phrase> 15154 <phrase role="keyword">int</phrase> <phrase role="identifier">size</phrase> <phrase role="special">=</phrase> <phrase role="number">1024</phrase> <phrase role="special">*</phrase> <phrase role="number">1024</phrase><phrase role="special">;</phrase> 15155 <phrase role="keyword">int</phrase> <phrase role="identifier">full_size</phrase> <phrase role="special">=</phrase> <phrase role="number">20</phrase> <phrase role="special">*</phrase> <phrase role="identifier">size</phrase><phrase role="special">;</phrase> 15156 <phrase role="keyword">int</phrase> <phrase role="special">*</phrase> <phrase role="identifier">host_a</phrase><phrase role="special">,</phrase> <phrase role="special">*</phrase> <phrase role="identifier">host_b</phrase><phrase role="special">,</phrase> <phrase role="special">*</phrase> <phrase role="identifier">host_c</phrase><phrase role="special">;</phrase> 15157 <phrase role="identifier">cudaHostAlloc</phrase><phrase role="special">(</phrase> <phrase role="special">&</phrase> <phrase role="identifier">host_a</phrase><phrase role="special">,</phrase> <phrase role="identifier">full_size</phrase> <phrase role="special">*</phrase> <phrase role="keyword">sizeof</phrase><phrase role="special">(</phrase> <phrase role="keyword">int</phrase><phrase role="special">),</phrase> <phrase role="identifier">cudaHostAllocDefault</phrase><phrase role="special">);</phrase> 15158 <phrase role="identifier">cudaHostAlloc</phrase><phrase role="special">(</phrase> <phrase role="special">&</phrase> <phrase role="identifier">host_b</phrase><phrase role="special">,</phrase> <phrase role="identifier">full_size</phrase> <phrase role="special">*</phrase> <phrase role="keyword">sizeof</phrase><phrase role="special">(</phrase> <phrase role="keyword">int</phrase><phrase role="special">),</phrase> <phrase role="identifier">cudaHostAllocDefault</phrase><phrase role="special">);</phrase> 15159 <phrase role="identifier">cudaHostAlloc</phrase><phrase role="special">(</phrase> <phrase role="special">&</phrase> <phrase role="identifier">host_c</phrase><phrase role="special">,</phrase> <phrase role="identifier">full_size</phrase> <phrase role="special">*</phrase> <phrase role="keyword">sizeof</phrase><phrase role="special">(</phrase> <phrase role="keyword">int</phrase><phrase role="special">),</phrase> <phrase role="identifier">cudaHostAllocDefault</phrase><phrase role="special">);</phrase> 15160 <phrase role="keyword">int</phrase> <phrase role="special">*</phrase> <phrase role="identifier">dev_a</phrase><phrase role="special">,</phrase> <phrase role="special">*</phrase> <phrase role="identifier">dev_b</phrase><phrase role="special">,</phrase> <phrase role="special">*</phrase> <phrase role="identifier">dev_c</phrase><phrase role="special">;</phrase> 15161 <phrase role="identifier">cudaMalloc</phrase><phrase role="special">(</phrase> <phrase role="special">&</phrase> <phrase role="identifier">dev_a</phrase><phrase role="special">,</phrase> <phrase role="identifier">size</phrase> <phrase role="special">*</phrase> <phrase role="keyword">sizeof</phrase><phrase role="special">(</phrase> <phrase role="keyword">int</phrase><phrase role="special">)</phrase> <phrase role="special">);</phrase> 15162 <phrase role="identifier">cudaMalloc</phrase><phrase role="special">(</phrase> <phrase role="special">&</phrase> <phrase role="identifier">dev_b</phrase><phrase role="special">,</phrase> <phrase role="identifier">size</phrase> <phrase role="special">*</phrase> <phrase role="keyword">sizeof</phrase><phrase role="special">(</phrase> <phrase role="keyword">int</phrase><phrase role="special">)</phrase> <phrase role="special">);</phrase> 15163 <phrase role="identifier">cudaMalloc</phrase><phrase role="special">(</phrase> <phrase role="special">&</phrase> <phrase role="identifier">dev_c</phrase><phrase role="special">,</phrase> <phrase role="identifier">size</phrase> <phrase role="special">*</phrase> <phrase role="keyword">sizeof</phrase><phrase role="special">(</phrase> <phrase role="keyword">int</phrase><phrase role="special">)</phrase> <phrase role="special">);</phrase> 15164 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">minstd_rand</phrase> <phrase role="identifier">generator</phrase><phrase role="special">;</phrase> 15165 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">uniform_int_distribution</phrase><phrase role="special"><></phrase> <phrase role="identifier">distribution</phrase><phrase role="special">(</phrase><phrase role="number">1</phrase><phrase role="special">,</phrase> <phrase role="number">6</phrase><phrase role="special">);</phrase> 15166 <phrase role="keyword">for</phrase> <phrase role="special">(</phrase> <phrase role="keyword">int</phrase> <phrase role="identifier">i</phrase> <phrase role="special">=</phrase> <phrase role="number">0</phrase><phrase role="special">;</phrase> <phrase role="identifier">i</phrase> <phrase role="special"><</phrase> <phrase role="identifier">full_size</phrase><phrase role="special">;</phrase> <phrase role="special">++</phrase><phrase role="identifier">i</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase> 15167 <phrase role="identifier">host_a</phrase><phrase role="special">[</phrase><phrase role="identifier">i</phrase><phrase role="special">]</phrase> <phrase role="special">=</phrase> <phrase role="identifier">distribution</phrase><phrase role="special">(</phrase> <phrase role="identifier">generator</phrase><phrase role="special">);</phrase> 15168 <phrase role="identifier">host_b</phrase><phrase role="special">[</phrase><phrase role="identifier">i</phrase><phrase role="special">]</phrase> <phrase role="special">=</phrase> <phrase role="identifier">distribution</phrase><phrase role="special">(</phrase> <phrase role="identifier">generator</phrase><phrase role="special">);</phrase> 15169 <phrase role="special">}</phrase> 15170 <phrase role="keyword">for</phrase> <phrase role="special">(</phrase> <phrase role="keyword">int</phrase> <phrase role="identifier">i</phrase> <phrase role="special">=</phrase> <phrase role="number">0</phrase><phrase role="special">;</phrase> <phrase role="identifier">i</phrase> <phrase role="special"><</phrase> <phrase role="identifier">full_size</phrase><phrase role="special">;</phrase> <phrase role="identifier">i</phrase> <phrase role="special">+=</phrase> <phrase role="identifier">size</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase> 15171 <phrase role="identifier">cudaMemcpyAsync</phrase><phrase role="special">(</phrase> <phrase role="identifier">dev_a</phrase><phrase role="special">,</phrase> <phrase role="identifier">host_a</phrase> <phrase role="special">+</phrase> <phrase role="identifier">i</phrase><phrase role="special">,</phrase> <phrase role="identifier">size</phrase> <phrase role="special">*</phrase> <phrase role="keyword">sizeof</phrase><phrase role="special">(</phrase> <phrase role="keyword">int</phrase><phrase role="special">),</phrase> <phrase role="identifier">cudaMemcpyHostToDevice</phrase><phrase role="special">,</phrase> <phrase role="identifier">stream</phrase><phrase role="special">);</phrase> 15172 <phrase role="identifier">cudaMemcpyAsync</phrase><phrase role="special">(</phrase> <phrase role="identifier">dev_b</phrase><phrase role="special">,</phrase> <phrase role="identifier">host_b</phrase> <phrase role="special">+</phrase> <phrase role="identifier">i</phrase><phrase role="special">,</phrase> <phrase role="identifier">size</phrase> <phrase role="special">*</phrase> <phrase role="keyword">sizeof</phrase><phrase role="special">(</phrase> <phrase role="keyword">int</phrase><phrase role="special">),</phrase> <phrase role="identifier">cudaMemcpyHostToDevice</phrase><phrase role="special">,</phrase> <phrase role="identifier">stream</phrase><phrase role="special">);</phrase> 15173 <phrase role="identifier">kernel</phrase><phrase role="special"><<<</phrase> <phrase role="identifier">size</phrase> <phrase role="special">/</phrase> <phrase role="number">256</phrase><phrase role="special">,</phrase> <phrase role="number">256</phrase><phrase role="special">,</phrase> <phrase role="number">0</phrase><phrase role="special">,</phrase> <phrase role="identifier">stream</phrase> <phrase role="special">>>>(</phrase> <phrase role="identifier">size</phrase><phrase role="special">,</phrase> <phrase role="identifier">dev_a</phrase><phrase role="special">,</phrase> <phrase role="identifier">dev_b</phrase><phrase role="special">,</phrase> <phrase role="identifier">dev_c</phrase><phrase role="special">);</phrase> 15174 <phrase role="identifier">cudaMemcpyAsync</phrase><phrase role="special">(</phrase> <phrase role="identifier">host_c</phrase> <phrase role="special">+</phrase> <phrase role="identifier">i</phrase><phrase role="special">,</phrase> <phrase role="identifier">dev_c</phrase><phrase role="special">,</phrase> <phrase role="identifier">size</phrase> <phrase role="special">*</phrase> <phrase role="keyword">sizeof</phrase><phrase role="special">(</phrase> <phrase role="keyword">int</phrase><phrase role="special">),</phrase> <phrase role="identifier">cudaMemcpyDeviceToHost</phrase><phrase role="special">,</phrase> <phrase role="identifier">stream</phrase><phrase role="special">);</phrase> 15175 <phrase role="special">}</phrase> 15176 <phrase role="keyword">auto</phrase> <phrase role="identifier">result</phrase> <phrase role="special">=</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">cuda</phrase><phrase role="special">::</phrase><phrase role="identifier">waitfor_all</phrase><phrase role="special">(</phrase> <phrase role="identifier">stream</phrase><phrase role="special">);</phrase> <phrase role="comment">// suspend fiber till CUDA stream has finished</phrase> 15177 <phrase role="identifier">BOOST_ASSERT</phrase><phrase role="special">(</phrase> <phrase role="identifier">stream</phrase> <phrase role="special">==</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">get</phrase><phrase role="special"><</phrase> <phrase role="number">0</phrase> <phrase role="special">>(</phrase> <phrase role="identifier">result</phrase><phrase role="special">)</phrase> <phrase role="special">);</phrase> 15178 <phrase role="identifier">BOOST_ASSERT</phrase><phrase role="special">(</phrase> <phrase role="identifier">cudaSuccess</phrase> <phrase role="special">==</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">get</phrase><phrase role="special"><</phrase> <phrase role="number">1</phrase> <phrase role="special">>(</phrase> <phrase role="identifier">result</phrase><phrase role="special">)</phrase> <phrase role="special">);</phrase> 15179 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cout</phrase> <phrase role="special"><<</phrase> <phrase role="string">"f1: GPU computation finished"</phrase> <phrase role="special"><<</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">endl</phrase><phrase role="special">;</phrase> 15180 <phrase role="identifier">cudaFreeHost</phrase><phrase role="special">(</phrase> <phrase role="identifier">host_a</phrase><phrase role="special">);</phrase> 15181 <phrase role="identifier">cudaFreeHost</phrase><phrase role="special">(</phrase> <phrase role="identifier">host_b</phrase><phrase role="special">);</phrase> 15182 <phrase role="identifier">cudaFreeHost</phrase><phrase role="special">(</phrase> <phrase role="identifier">host_c</phrase><phrase role="special">);</phrase> 15183 <phrase role="identifier">cudaFree</phrase><phrase role="special">(</phrase> <phrase role="identifier">dev_a</phrase><phrase role="special">);</phrase> 15184 <phrase role="identifier">cudaFree</phrase><phrase role="special">(</phrase> <phrase role="identifier">dev_b</phrase><phrase role="special">);</phrase> 15185 <phrase role="identifier">cudaFree</phrase><phrase role="special">(</phrase> <phrase role="identifier">dev_c</phrase><phrase role="special">);</phrase> 15186 <phrase role="identifier">cudaStreamDestroy</phrase><phrase role="special">(</phrase> <phrase role="identifier">stream</phrase><phrase role="special">);</phrase> 15187<phrase role="special">});</phrase> 15188<phrase role="identifier">f</phrase><phrase role="special">.</phrase><phrase role="identifier">join</phrase><phrase role="special">();</phrase> 15189</programlisting> 15190 <bridgehead renderas="sect4" id="fiber.gpu_computing.cuda.h1"> 15191 <phrase id="fiber.gpu_computing.cuda.synopsis"/><link linkend="fiber.gpu_computing.cuda.synopsis">Synopsis</link> 15192 </bridgehead> 15193<programlisting><phrase role="preprocessor">#include</phrase> <phrase role="special"><</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">fiber</phrase><phrase role="special">/</phrase><phrase role="identifier">cuda</phrase><phrase role="special">/</phrase><phrase role="identifier">waitfor</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">></phrase> 15194 15195<phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase> 15196<phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase> 15197<phrase role="keyword">namespace</phrase> <phrase role="identifier">cuda</phrase> <phrase role="special">{</phrase> 15198 15199<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">tuple</phrase><phrase role="special"><</phrase> <phrase role="identifier">cudaStream_t</phrase><phrase role="special">,</phrase> <phrase role="identifier">cudaError_t</phrase> <phrase role="special">></phrase> <phrase role="identifier">waitfor_all</phrase><phrase role="special">(</phrase> <phrase role="identifier">cudaStream_t</phrase> <phrase role="identifier">st</phrase><phrase role="special">);</phrase> 15200<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">vector</phrase><phrase role="special"><</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">tuple</phrase><phrase role="special"><</phrase> <phrase role="identifier">cudaStream_t</phrase><phrase role="special">,</phrase> <phrase role="identifier">cudaError_t</phrase> <phrase role="special">></phrase> <phrase role="special">></phrase> <phrase role="identifier">waitfor_all</phrase><phrase role="special">(</phrase> <phrase role="identifier">cudaStream_t</phrase> <phrase role="special">...</phrase> <phrase role="identifier">st</phrase><phrase role="special">);</phrase> 15201 15202<phrase role="special">}}}</phrase> 15203</programlisting> 15204 <para> 15205 <bridgehead renderas="sect4" id="cuda_waitfor_bridgehead"> 15206 <phrase id="cuda_waitfor"/> 15207 <link linkend="cuda_waitfor">Non-member function <code>cuda::waitfor()</code></link> 15208</bridgehead> 15209 </para> 15210<programlisting><phrase role="preprocessor">#include</phrase> <phrase role="special"><</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">fiber</phrase><phrase role="special">/</phrase><phrase role="identifier">cuda</phrase><phrase role="special">/</phrase><phrase role="identifier">waitfor</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">></phrase> 15211 15212<phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase> 15213<phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase> 15214<phrase role="keyword">namespace</phrase> <phrase role="identifier">cuda</phrase> <phrase role="special">{</phrase> 15215 15216<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">tuple</phrase><phrase role="special"><</phrase> <phrase role="identifier">cudaStream_t</phrase><phrase role="special">,</phrase> <phrase role="identifier">cudaError_t</phrase> <phrase role="special">></phrase> <phrase role="identifier">waitfor_all</phrase><phrase role="special">(</phrase> <phrase role="identifier">cudaStream_t</phrase> <phrase role="identifier">st</phrase><phrase role="special">);</phrase> 15217<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">vector</phrase><phrase role="special"><</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">tuple</phrase><phrase role="special"><</phrase> <phrase role="identifier">cudaStream_t</phrase><phrase role="special">,</phrase> <phrase role="identifier">cudaError_t</phrase> <phrase role="special">></phrase> <phrase role="special">></phrase> <phrase role="identifier">waitfor_all</phrase><phrase role="special">(</phrase> <phrase role="identifier">cudaStream_t</phrase> <phrase role="special">...</phrase> <phrase role="identifier">st</phrase><phrase role="special">);</phrase> 15218 15219<phrase role="special">}}}</phrase> 15220</programlisting> 15221 <variablelist> 15222 <title></title> 15223 <varlistentry> 15224 <term>Effects:</term> 15225 <listitem> 15226 <para> 15227 Suspends active fiber till CUDA stream has finished its operations. 15228 </para> 15229 </listitem> 15230 </varlistentry> 15231 <varlistentry> 15232 <term>Returns:</term> 15233 <listitem> 15234 <para> 15235 tuple of stream reference and the CUDA stream status 15236 </para> 15237 </listitem> 15238 </varlistentry> 15239 </variablelist> 15240 </section> 15241 <section id="fiber.gpu_computing.hip"> 15242 <title><anchor id="hip"/><link linkend="fiber.gpu_computing.hip">ROCm/HIP</link></title> 15243 <para> 15244 <ulink url="http://github.com/ROCm-Developer-Tools/HIP/tree/roc-1.6.0/">HIP</ulink> 15245 is part of the <ulink url="http://rocm.github.io/">ROC (Radeon Open Compute)</ulink> 15246 platform for parallel computing on AMD and NVIDIA GPUs. The application programming 15247 interface of HIP gives access to GPU's instruction set and computation resources 15248 (Execution of compute kernels). 15249 </para> 15250 <bridgehead renderas="sect4" id="fiber.gpu_computing.hip.h0"> 15251 <phrase id="fiber.gpu_computing.hip.synchronization_with_rocm_hip_streams"/><link 15252 linkend="fiber.gpu_computing.hip.synchronization_with_rocm_hip_streams">Synchronization 15253 with ROCm/HIP streams</link> 15254 </bridgehead> 15255 <para> 15256 HIP operation such as compute kernels or memory transfer (between host and 15257 device) can be grouped/queued by HIP streams. are executed on the GPUs. Boost.Fiber 15258 enables a fiber to sleep (suspend) till a HIP stream has completed its operations. 15259 This enables applications to run other fibers on the CPU without the need 15260 to spawn an additional OS-threads. And resume the fiber when the HIP streams 15261 has finished. 15262 </para> 15263<programlisting><phrase role="identifier">__global__</phrase> 15264<phrase role="keyword">void</phrase> <phrase role="identifier">kernel</phrase><phrase role="special">(</phrase> <phrase role="keyword">int</phrase> <phrase role="identifier">size</phrase><phrase role="special">,</phrase> <phrase role="keyword">int</phrase> <phrase role="special">*</phrase> <phrase role="identifier">a</phrase><phrase role="special">,</phrase> <phrase role="keyword">int</phrase> <phrase role="special">*</phrase> <phrase role="identifier">b</phrase><phrase role="special">,</phrase> <phrase role="keyword">int</phrase> <phrase role="special">*</phrase> <phrase role="identifier">c</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase> 15265 <phrase role="keyword">int</phrase> <phrase role="identifier">idx</phrase> <phrase role="special">=</phrase> <phrase role="identifier">threadIdx</phrase><phrase role="special">.</phrase><phrase role="identifier">x</phrase> <phrase role="special">+</phrase> <phrase role="identifier">blockIdx</phrase><phrase role="special">.</phrase><phrase role="identifier">x</phrase> <phrase role="special">*</phrase> <phrase role="identifier">blockDim</phrase><phrase role="special">.</phrase><phrase role="identifier">x</phrase><phrase role="special">;</phrase> 15266 <phrase role="keyword">if</phrase> <phrase role="special">(</phrase> <phrase role="identifier">idx</phrase> <phrase role="special"><</phrase> <phrase role="identifier">size</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase> 15267 <phrase role="keyword">int</phrase> <phrase role="identifier">idx1</phrase> <phrase role="special">=</phrase> <phrase role="special">(</phrase><phrase role="identifier">idx</phrase> <phrase role="special">+</phrase> <phrase role="number">1</phrase><phrase role="special">)</phrase> <phrase role="special">%</phrase> <phrase role="number">256</phrase><phrase role="special">;</phrase> 15268 <phrase role="keyword">int</phrase> <phrase role="identifier">idx2</phrase> <phrase role="special">=</phrase> <phrase role="special">(</phrase><phrase role="identifier">idx</phrase> <phrase role="special">+</phrase> <phrase role="number">2</phrase><phrase role="special">)</phrase> <phrase role="special">%</phrase> <phrase role="number">256</phrase><phrase role="special">;</phrase> 15269 <phrase role="keyword">float</phrase> <phrase role="identifier">as</phrase> <phrase role="special">=</phrase> <phrase role="special">(</phrase><phrase role="identifier">a</phrase><phrase role="special">[</phrase><phrase role="identifier">idx</phrase><phrase role="special">]</phrase> <phrase role="special">+</phrase> <phrase role="identifier">a</phrase><phrase role="special">[</phrase><phrase role="identifier">idx1</phrase><phrase role="special">]</phrase> <phrase role="special">+</phrase> <phrase role="identifier">a</phrase><phrase role="special">[</phrase><phrase role="identifier">idx2</phrase><phrase role="special">])</phrase> <phrase role="special">/</phrase> <phrase role="number">3.0f</phrase><phrase role="special">;</phrase> 15270 <phrase role="keyword">float</phrase> <phrase role="identifier">bs</phrase> <phrase role="special">=</phrase> <phrase role="special">(</phrase><phrase role="identifier">b</phrase><phrase role="special">[</phrase><phrase role="identifier">idx</phrase><phrase role="special">]</phrase> <phrase role="special">+</phrase> <phrase role="identifier">b</phrase><phrase role="special">[</phrase><phrase role="identifier">idx1</phrase><phrase role="special">]</phrase> <phrase role="special">+</phrase> <phrase role="identifier">b</phrase><phrase role="special">[</phrase><phrase role="identifier">idx2</phrase><phrase role="special">])</phrase> <phrase role="special">/</phrase> <phrase role="number">3.0f</phrase><phrase role="special">;</phrase> 15271 <phrase role="identifier">c</phrase><phrase role="special">[</phrase><phrase role="identifier">idx</phrase><phrase role="special">]</phrase> <phrase role="special">=</phrase> <phrase role="special">(</phrase><phrase role="identifier">as</phrase> <phrase role="special">+</phrase> <phrase role="identifier">bs</phrase><phrase role="special">)</phrase> <phrase role="special">/</phrase> <phrase role="number">2</phrase><phrase role="special">;</phrase> 15272 <phrase role="special">}</phrase> 15273<phrase role="special">}</phrase> 15274 15275<phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">fiber</phrase> <phrase role="identifier">f</phrase><phrase role="special">([&</phrase><phrase role="identifier">done</phrase><phrase role="special">]{</phrase> 15276 <phrase role="identifier">hipStream_t</phrase> <phrase role="identifier">stream</phrase><phrase role="special">;</phrase> 15277 <phrase role="identifier">hipStreamCreate</phrase><phrase role="special">(</phrase> <phrase role="special">&</phrase> <phrase role="identifier">stream</phrase><phrase role="special">);</phrase> 15278 <phrase role="keyword">int</phrase> <phrase role="identifier">size</phrase> <phrase role="special">=</phrase> <phrase role="number">1024</phrase> <phrase role="special">*</phrase> <phrase role="number">1024</phrase><phrase role="special">;</phrase> 15279 <phrase role="keyword">int</phrase> <phrase role="identifier">full_size</phrase> <phrase role="special">=</phrase> <phrase role="number">20</phrase> <phrase role="special">*</phrase> <phrase role="identifier">size</phrase><phrase role="special">;</phrase> 15280 <phrase role="keyword">int</phrase> <phrase role="special">*</phrase> <phrase role="identifier">host_a</phrase><phrase role="special">,</phrase> <phrase role="special">*</phrase> <phrase role="identifier">host_b</phrase><phrase role="special">,</phrase> <phrase role="special">*</phrase> <phrase role="identifier">host_c</phrase><phrase role="special">;</phrase> 15281 <phrase role="identifier">hipHostMalloc</phrase><phrase role="special">(</phrase> <phrase role="special">&</phrase> <phrase role="identifier">host_a</phrase><phrase role="special">,</phrase> <phrase role="identifier">full_size</phrase> <phrase role="special">*</phrase> <phrase role="keyword">sizeof</phrase><phrase role="special">(</phrase> <phrase role="keyword">int</phrase><phrase role="special">),</phrase> <phrase role="identifier">hipHostMallocDefault</phrase><phrase role="special">);</phrase> 15282 <phrase role="identifier">hipHostMalloc</phrase><phrase role="special">(</phrase> <phrase role="special">&</phrase> <phrase role="identifier">host_b</phrase><phrase role="special">,</phrase> <phrase role="identifier">full_size</phrase> <phrase role="special">*</phrase> <phrase role="keyword">sizeof</phrase><phrase role="special">(</phrase> <phrase role="keyword">int</phrase><phrase role="special">),</phrase> <phrase role="identifier">hipHostMallocDefault</phrase><phrase role="special">);</phrase> 15283 <phrase role="identifier">hipHostMalloc</phrase><phrase role="special">(</phrase> <phrase role="special">&</phrase> <phrase role="identifier">host_c</phrase><phrase role="special">,</phrase> <phrase role="identifier">full_size</phrase> <phrase role="special">*</phrase> <phrase role="keyword">sizeof</phrase><phrase role="special">(</phrase> <phrase role="keyword">int</phrase><phrase role="special">),</phrase> <phrase role="identifier">hipHostMallocDefault</phrase><phrase role="special">);</phrase> 15284 <phrase role="keyword">int</phrase> <phrase role="special">*</phrase> <phrase role="identifier">dev_a</phrase><phrase role="special">,</phrase> <phrase role="special">*</phrase> <phrase role="identifier">dev_b</phrase><phrase role="special">,</phrase> <phrase role="special">*</phrase> <phrase role="identifier">dev_c</phrase><phrase role="special">;</phrase> 15285 <phrase role="identifier">hipMalloc</phrase><phrase role="special">(</phrase> <phrase role="special">&</phrase> <phrase role="identifier">dev_a</phrase><phrase role="special">,</phrase> <phrase role="identifier">size</phrase> <phrase role="special">*</phrase> <phrase role="keyword">sizeof</phrase><phrase role="special">(</phrase> <phrase role="keyword">int</phrase><phrase role="special">)</phrase> <phrase role="special">);</phrase> 15286 <phrase role="identifier">hipMalloc</phrase><phrase role="special">(</phrase> <phrase role="special">&</phrase> <phrase role="identifier">dev_b</phrase><phrase role="special">,</phrase> <phrase role="identifier">size</phrase> <phrase role="special">*</phrase> <phrase role="keyword">sizeof</phrase><phrase role="special">(</phrase> <phrase role="keyword">int</phrase><phrase role="special">)</phrase> <phrase role="special">);</phrase> 15287 <phrase role="identifier">hipMalloc</phrase><phrase role="special">(</phrase> <phrase role="special">&</phrase> <phrase role="identifier">dev_c</phrase><phrase role="special">,</phrase> <phrase role="identifier">size</phrase> <phrase role="special">*</phrase> <phrase role="keyword">sizeof</phrase><phrase role="special">(</phrase> <phrase role="keyword">int</phrase><phrase role="special">)</phrase> <phrase role="special">);</phrase> 15288 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">minstd_rand</phrase> <phrase role="identifier">generator</phrase><phrase role="special">;</phrase> 15289 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">uniform_int_distribution</phrase><phrase role="special"><></phrase> <phrase role="identifier">distribution</phrase><phrase role="special">(</phrase><phrase role="number">1</phrase><phrase role="special">,</phrase> <phrase role="number">6</phrase><phrase role="special">);</phrase> 15290 <phrase role="keyword">for</phrase> <phrase role="special">(</phrase> <phrase role="keyword">int</phrase> <phrase role="identifier">i</phrase> <phrase role="special">=</phrase> <phrase role="number">0</phrase><phrase role="special">;</phrase> <phrase role="identifier">i</phrase> <phrase role="special"><</phrase> <phrase role="identifier">full_size</phrase><phrase role="special">;</phrase> <phrase role="special">++</phrase><phrase role="identifier">i</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase> 15291 <phrase role="identifier">host_a</phrase><phrase role="special">[</phrase><phrase role="identifier">i</phrase><phrase role="special">]</phrase> <phrase role="special">=</phrase> <phrase role="identifier">distribution</phrase><phrase role="special">(</phrase> <phrase role="identifier">generator</phrase><phrase role="special">);</phrase> 15292 <phrase role="identifier">host_b</phrase><phrase role="special">[</phrase><phrase role="identifier">i</phrase><phrase role="special">]</phrase> <phrase role="special">=</phrase> <phrase role="identifier">distribution</phrase><phrase role="special">(</phrase> <phrase role="identifier">generator</phrase><phrase role="special">);</phrase> 15293 <phrase role="special">}</phrase> 15294 <phrase role="keyword">for</phrase> <phrase role="special">(</phrase> <phrase role="keyword">int</phrase> <phrase role="identifier">i</phrase> <phrase role="special">=</phrase> <phrase role="number">0</phrase><phrase role="special">;</phrase> <phrase role="identifier">i</phrase> <phrase role="special"><</phrase> <phrase role="identifier">full_size</phrase><phrase role="special">;</phrase> <phrase role="identifier">i</phrase> <phrase role="special">+=</phrase> <phrase role="identifier">size</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase> 15295 <phrase role="identifier">hipMemcpyAsync</phrase><phrase role="special">(</phrase> <phrase role="identifier">dev_a</phrase><phrase role="special">,</phrase> <phrase role="identifier">host_a</phrase> <phrase role="special">+</phrase> <phrase role="identifier">i</phrase><phrase role="special">,</phrase> <phrase role="identifier">size</phrase> <phrase role="special">*</phrase> <phrase role="keyword">sizeof</phrase><phrase role="special">(</phrase> <phrase role="keyword">int</phrase><phrase role="special">),</phrase> <phrase role="identifier">hipMemcpyHostToDevice</phrase><phrase role="special">,</phrase> <phrase role="identifier">stream</phrase><phrase role="special">);</phrase> 15296 <phrase role="identifier">hipMemcpyAsync</phrase><phrase role="special">(</phrase> <phrase role="identifier">dev_b</phrase><phrase role="special">,</phrase> <phrase role="identifier">host_b</phrase> <phrase role="special">+</phrase> <phrase role="identifier">i</phrase><phrase role="special">,</phrase> <phrase role="identifier">size</phrase> <phrase role="special">*</phrase> <phrase role="keyword">sizeof</phrase><phrase role="special">(</phrase> <phrase role="keyword">int</phrase><phrase role="special">),</phrase> <phrase role="identifier">hipMemcpyHostToDevice</phrase><phrase role="special">,</phrase> <phrase role="identifier">stream</phrase><phrase role="special">);</phrase> 15297 <phrase role="identifier">hipLaunchKernel</phrase><phrase role="special">(</phrase><phrase role="identifier">kernel</phrase><phrase role="special">,</phrase> <phrase role="identifier">dim3</phrase><phrase role="special">(</phrase><phrase role="identifier">size</phrase> <phrase role="special">/</phrase> <phrase role="number">256</phrase><phrase role="special">),</phrase> <phrase role="identifier">dim3</phrase><phrase role="special">(</phrase><phrase role="number">256</phrase><phrase role="special">),</phrase> <phrase role="number">0</phrase><phrase role="special">,</phrase> <phrase role="identifier">stream</phrase><phrase role="special">,</phrase> <phrase role="identifier">size</phrase><phrase role="special">,</phrase> <phrase role="identifier">dev_a</phrase><phrase role="special">,</phrase> <phrase role="identifier">dev_b</phrase><phrase role="special">,</phrase> <phrase role="identifier">dev_c</phrase><phrase role="special">);</phrase> 15298 <phrase role="identifier">hipMemcpyAsync</phrase><phrase role="special">(</phrase> <phrase role="identifier">host_c</phrase> <phrase role="special">+</phrase> <phrase role="identifier">i</phrase><phrase role="special">,</phrase> <phrase role="identifier">dev_c</phrase><phrase role="special">,</phrase> <phrase role="identifier">size</phrase> <phrase role="special">*</phrase> <phrase role="keyword">sizeof</phrase><phrase role="special">(</phrase> <phrase role="keyword">int</phrase><phrase role="special">),</phrase> <phrase role="identifier">hipMemcpyDeviceToHost</phrase><phrase role="special">,</phrase> <phrase role="identifier">stream</phrase><phrase role="special">);</phrase> 15299 <phrase role="special">}</phrase> 15300 <phrase role="keyword">auto</phrase> <phrase role="identifier">result</phrase> <phrase role="special">=</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">hip</phrase><phrase role="special">::</phrase><phrase role="identifier">waitfor_all</phrase><phrase role="special">(</phrase> <phrase role="identifier">stream</phrase><phrase role="special">);</phrase> <phrase role="comment">// suspend fiber till HIP stream has finished</phrase> 15301 <phrase role="identifier">BOOST_ASSERT</phrase><phrase role="special">(</phrase> <phrase role="identifier">stream</phrase> <phrase role="special">==</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">get</phrase><phrase role="special"><</phrase> <phrase role="number">0</phrase> <phrase role="special">>(</phrase> <phrase role="identifier">result</phrase><phrase role="special">)</phrase> <phrase role="special">);</phrase> 15302 <phrase role="identifier">BOOST_ASSERT</phrase><phrase role="special">(</phrase> <phrase role="identifier">hipSuccess</phrase> <phrase role="special">==</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">get</phrase><phrase role="special"><</phrase> <phrase role="number">1</phrase> <phrase role="special">>(</phrase> <phrase role="identifier">result</phrase><phrase role="special">)</phrase> <phrase role="special">);</phrase> 15303 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cout</phrase> <phrase role="special"><<</phrase> <phrase role="string">"f1: GPU computation finished"</phrase> <phrase role="special"><<</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">endl</phrase><phrase role="special">;</phrase> 15304 <phrase role="identifier">hipHostFree</phrase><phrase role="special">(</phrase> <phrase role="identifier">host_a</phrase><phrase role="special">);</phrase> 15305 <phrase role="identifier">hipHostFree</phrase><phrase role="special">(</phrase> <phrase role="identifier">host_b</phrase><phrase role="special">);</phrase> 15306 <phrase role="identifier">hipHostFree</phrase><phrase role="special">(</phrase> <phrase role="identifier">host_c</phrase><phrase role="special">);</phrase> 15307 <phrase role="identifier">hipFree</phrase><phrase role="special">(</phrase> <phrase role="identifier">dev_a</phrase><phrase role="special">);</phrase> 15308 <phrase role="identifier">hipFree</phrase><phrase role="special">(</phrase> <phrase role="identifier">dev_b</phrase><phrase role="special">);</phrase> 15309 <phrase role="identifier">hipFree</phrase><phrase role="special">(</phrase> <phrase role="identifier">dev_c</phrase><phrase role="special">);</phrase> 15310 <phrase role="identifier">hipStreamDestroy</phrase><phrase role="special">(</phrase> <phrase role="identifier">stream</phrase><phrase role="special">);</phrase> 15311<phrase role="special">});</phrase> 15312<phrase role="identifier">f</phrase><phrase role="special">.</phrase><phrase role="identifier">join</phrase><phrase role="special">();</phrase> 15313</programlisting> 15314 <bridgehead renderas="sect4" id="fiber.gpu_computing.hip.h1"> 15315 <phrase id="fiber.gpu_computing.hip.synopsis"/><link linkend="fiber.gpu_computing.hip.synopsis">Synopsis</link> 15316 </bridgehead> 15317<programlisting><phrase role="preprocessor">#include</phrase> <phrase role="special"><</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">fiber</phrase><phrase role="special">/</phrase><phrase role="identifier">hip</phrase><phrase role="special">/</phrase><phrase role="identifier">waitfor</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">></phrase> 15318 15319<phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase> 15320<phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase> 15321<phrase role="keyword">namespace</phrase> <phrase role="identifier">hip</phrase> <phrase role="special">{</phrase> 15322 15323<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">tuple</phrase><phrase role="special"><</phrase> <phrase role="identifier">hipStream_t</phrase><phrase role="special">,</phrase> <phrase role="identifier">hipError_t</phrase> <phrase role="special">></phrase> <phrase role="identifier">waitfor_all</phrase><phrase role="special">(</phrase> <phrase role="identifier">hipStream_t</phrase> <phrase role="identifier">st</phrase><phrase role="special">);</phrase> 15324<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">vector</phrase><phrase role="special"><</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">tuple</phrase><phrase role="special"><</phrase> <phrase role="identifier">hipStream_t</phrase><phrase role="special">,</phrase> <phrase role="identifier">hipError_t</phrase> <phrase role="special">></phrase> <phrase role="special">></phrase> <phrase role="identifier">waitfor_all</phrase><phrase role="special">(</phrase> <phrase role="identifier">hipStream_t</phrase> <phrase role="special">...</phrase> <phrase role="identifier">st</phrase><phrase role="special">);</phrase> 15325 15326<phrase role="special">}}}</phrase> 15327</programlisting> 15328 <para> 15329 <bridgehead renderas="sect4" id="hip_waitfor_bridgehead"> 15330 <phrase id="hip_waitfor"/> 15331 <link linkend="hip_waitfor">Non-member function <code>hip::waitfor()</code></link> 15332</bridgehead> 15333 </para> 15334<programlisting><phrase role="preprocessor">#include</phrase> <phrase role="special"><</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">fiber</phrase><phrase role="special">/</phrase><phrase role="identifier">hip</phrase><phrase role="special">/</phrase><phrase role="identifier">waitfor</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">></phrase> 15335 15336<phrase role="keyword">namespace</phrase> <phrase role="identifier">boost</phrase> <phrase role="special">{</phrase> 15337<phrase role="keyword">namespace</phrase> <phrase role="identifier">fibers</phrase> <phrase role="special">{</phrase> 15338<phrase role="keyword">namespace</phrase> <phrase role="identifier">hip</phrase> <phrase role="special">{</phrase> 15339 15340<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">tuple</phrase><phrase role="special"><</phrase> <phrase role="identifier">hipStream_t</phrase><phrase role="special">,</phrase> <phrase role="identifier">hipError_t</phrase> <phrase role="special">></phrase> <phrase role="identifier">waitfor_all</phrase><phrase role="special">(</phrase> <phrase role="identifier">hipStream_t</phrase> <phrase role="identifier">st</phrase><phrase role="special">);</phrase> 15341<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">vector</phrase><phrase role="special"><</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">tuple</phrase><phrase role="special"><</phrase> <phrase role="identifier">hipStream_t</phrase><phrase role="special">,</phrase> <phrase role="identifier">hipError_t</phrase> <phrase role="special">></phrase> <phrase role="special">></phrase> <phrase role="identifier">waitfor_all</phrase><phrase role="special">(</phrase> <phrase role="identifier">hipStream_t</phrase> <phrase role="special">...</phrase> <phrase role="identifier">st</phrase><phrase role="special">);</phrase> 15342 15343<phrase role="special">}}}</phrase> 15344</programlisting> 15345 <variablelist> 15346 <title></title> 15347 <varlistentry> 15348 <term>Effects:</term> 15349 <listitem> 15350 <para> 15351 Suspends active fiber till HIP stream has finished its operations. 15352 </para> 15353 </listitem> 15354 </varlistentry> 15355 <varlistentry> 15356 <term>Returns:</term> 15357 <listitem> 15358 <para> 15359 tuple of stream reference and the HIP stream status 15360 </para> 15361 </listitem> 15362 </varlistentry> 15363 </variablelist> 15364 </section> 15365 </section> 15366 <section id="fiber.worker"> 15367 <title><anchor id="worker"/><link linkend="fiber.worker">Running with worker 15368 threads</link></title> 15369 <bridgehead renderas="sect3" id="fiber.worker.h0"> 15370 <phrase id="fiber.worker.keep_workers_running"/><link linkend="fiber.worker.keep_workers_running">Keep 15371 workers running</link> 15372 </bridgehead> 15373 <para> 15374 If a worker thread is used but no fiber is created or parts of the framework 15375 (like <link linkend="this_fiber_yield"><code>this_fiber::yield()</code></link>) are touched, then no fiber scheduler 15376 is instantiated. 15377 </para> 15378<programlisting><phrase role="keyword">auto</phrase> <phrase role="identifier">worker</phrase> <phrase role="special">=</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">thread</phrase><phrase role="special">(</phrase> 15379 <phrase role="special">[]{</phrase> 15380 <phrase role="comment">// fiber scheduler not instantiated</phrase> 15381 <phrase role="special">});</phrase> 15382<phrase role="identifier">worker</phrase><phrase role="special">.</phrase><phrase role="identifier">join</phrase><phrase role="special">();</phrase> 15383</programlisting> 15384 <para> 15385 If <emphasis>use_scheduling_algorithm<>()</emphasis> is invoked, the 15386 fiber scheduler is created. If the worker thread simply returns, destroys the 15387 scheduler and terminates. 15388 </para> 15389<programlisting><phrase role="keyword">auto</phrase> <phrase role="identifier">worker</phrase> <phrase role="special">=</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">thread</phrase><phrase role="special">(</phrase> 15390 <phrase role="special">[]{</phrase> 15391 <phrase role="comment">// fiber scheduler created</phrase> 15392 <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">use_scheduling_algorithm</phrase><phrase role="special"><</phrase><phrase role="identifier">my_fiber_scheduler</phrase><phrase role="special">>();</phrase> 15393 <phrase role="special">});</phrase> 15394<phrase role="identifier">worker</phrase><phrase role="special">.</phrase><phrase role="identifier">join</phrase><phrase role="special">();</phrase> 15395</programlisting> 15396 <para> 15397 In order to keep the worker thread running, the fiber associated with the thread 15398 stack (which is called <quote>main</quote> fiber) is blocked. For instance 15399 the <quote>main</quote> fiber might wait on a <link linkend="class_condition_variable"><code>condition_variable</code></link>. 15400 For a gracefully shutdown <link linkend="class_condition_variable"><code>condition_variable</code></link> is signalled 15401 and the <quote>main</quote> fiber returns. The scheduler gets destructed if 15402 all fibers of the worker thread have been terminated. 15403 </para> 15404<programlisting><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">mutex</phrase> <phrase role="identifier">mtx</phrase><phrase role="special">;</phrase> 15405<phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">condition_variable_any</phrase> <phrase role="identifier">cv</phrase><phrase role="special">;</phrase> 15406<phrase role="keyword">auto</phrase> <phrase role="identifier">worker</phrase> <phrase role="special">=</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">thread</phrase><phrase role="special">(</phrase> 15407 <phrase role="special">[&</phrase><phrase role="identifier">mtx</phrase><phrase role="special">,&</phrase><phrase role="identifier">cv</phrase><phrase role="special">]{</phrase> 15408 <phrase role="identifier">mtx</phrase><phrase role="special">.</phrase><phrase role="identifier">lock</phrase><phrase role="special">();</phrase> 15409 <phrase role="comment">// suspend till signalled</phrase> 15410 <phrase role="identifier">cv</phrase><phrase role="special">.</phrase><phrase role="identifier">wait</phrase><phrase role="special">(</phrase><phrase role="identifier">mtx</phrase><phrase role="special">);</phrase> 15411 <phrase role="identifier">mtx</phrase><phrase role="special">.</phrase><phrase role="identifier">unlock</phrase><phrase role="special">();</phrase> 15412 <phrase role="special">});</phrase> 15413<phrase role="comment">// signal termination</phrase> 15414<phrase role="identifier">cv</phrase><phrase role="special">.</phrase><phrase role="identifier">notify_all</phrase><phrase role="special">();</phrase> 15415<phrase role="identifier">worker</phrase><phrase role="special">.</phrase><phrase role="identifier">join</phrase><phrase role="special">();</phrase> 15416</programlisting> 15417 <bridgehead renderas="sect3" id="fiber.worker.h1"> 15418 <phrase id="fiber.worker.processing_tasks"/><link linkend="fiber.worker.processing_tasks">Processing 15419 tasks</link> 15420 </bridgehead> 15421 <para> 15422 Tasks can be transferred via channels. The worker thread runs a pool of fibers 15423 that dequeue and executed tasks from the channel. The termination is signalled 15424 via closing the channel. 15425 </para> 15426<programlisting><phrase role="keyword">using</phrase> <phrase role="identifier">task</phrase> <phrase role="special">=</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">function</phrase><phrase role="special"><</phrase><phrase role="keyword">void</phrase><phrase role="special">()>;</phrase> 15427<phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">buffered_channel</phrase><phrase role="special"><</phrase><phrase role="identifier">task</phrase><phrase role="special">></phrase> <phrase role="identifier">ch</phrase><phrase role="special">{</phrase><phrase role="number">1024</phrase><phrase role="special">};</phrase> 15428<phrase role="keyword">auto</phrase> <phrase role="identifier">worker</phrase> <phrase role="special">=</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">thread</phrase><phrase role="special">(</phrase> 15429 <phrase role="special">[&</phrase><phrase role="identifier">ch</phrase><phrase role="special">]{</phrase> 15430 <phrase role="comment">// create pool of fibers</phrase> 15431 <phrase role="keyword">for</phrase> <phrase role="special">(</phrase><phrase role="keyword">int</phrase> <phrase role="identifier">i</phrase><phrase role="special">=</phrase><phrase role="number">0</phrase><phrase role="special">;</phrase> <phrase role="identifier">i</phrase><phrase role="special"><</phrase><phrase role="number">10</phrase><phrase role="special">;</phrase> <phrase role="special">++</phrase><phrase role="identifier">i</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase> 15432 <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">fiber</phrase><phrase role="special">{</phrase> 15433 <phrase role="special">[&</phrase><phrase role="identifier">ch</phrase><phrase role="special">]{</phrase> 15434 <phrase role="identifier">task</phrase> <phrase role="identifier">tsk</phrase><phrase role="special">;</phrase> 15435 <phrase role="comment">// dequeue and process tasks</phrase> 15436 <phrase role="keyword">while</phrase> <phrase role="special">(</phrase><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">channel_op_status</phrase><phrase role="special">::</phrase><phrase role="identifier">closed</phrase><phrase role="special">!=</phrase><phrase role="identifier">ch</phrase><phrase role="special">.</phrase><phrase role="identifier">pop</phrase><phrase role="special">(</phrase><phrase role="identifier">tsk</phrase><phrase role="special">)){</phrase> 15437 <phrase role="identifier">tsk</phrase><phrase role="special">();</phrase> 15438 <phrase role="special">}</phrase> 15439 <phrase role="special">}}.</phrase><phrase role="identifier">detach</phrase><phrase role="special">();</phrase> 15440 <phrase role="special">}</phrase> 15441 <phrase role="identifier">task</phrase> <phrase role="identifier">tsk</phrase><phrase role="special">;</phrase> 15442 <phrase role="comment">// dequeue and process tasks</phrase> 15443 <phrase role="keyword">while</phrase> <phrase role="special">(</phrase><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">channel_op_status</phrase><phrase role="special">::</phrase><phrase role="identifier">closed</phrase><phrase role="special">!=</phrase><phrase role="identifier">ch</phrase><phrase role="special">.</phrase><phrase role="identifier">pop</phrase><phrase role="special">(</phrase><phrase role="identifier">tsk</phrase><phrase role="special">)){</phrase> 15444 <phrase role="identifier">tsk</phrase><phrase role="special">();</phrase> 15445 <phrase role="special">}</phrase> 15446 <phrase role="special">});</phrase> 15447<phrase role="comment">// feed channel with tasks</phrase> 15448<phrase role="identifier">ch</phrase><phrase role="special">.</phrase><phrase role="identifier">push</phrase><phrase role="special">([]{</phrase> <phrase role="special">...</phrase> <phrase role="special">});</phrase> 15449<phrase role="special">...</phrase> 15450<phrase role="comment">// signal termination</phrase> 15451<phrase role="identifier">ch</phrase><phrase role="special">.</phrase><phrase role="identifier">close</phrase><phrase role="special">();</phrase> 15452<phrase role="identifier">worker</phrase><phrase role="special">.</phrase><phrase role="identifier">join</phrase><phrase role="special">();</phrase> 15453</programlisting> 15454 <para> 15455 An alternative is to use a work-stealing scheduler. This kind of scheduling 15456 algorithm a worker thread steals fibers from the ready-queue of other worker 15457 threads if its own ready-queue is empty. 15458 </para> 15459 <note> 15460 <para> 15461 Wait till all worker threads have registered the work-stealing scheduling 15462 algorithm. 15463 </para> 15464 </note> 15465<programlisting><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">mutex</phrase> <phrase role="identifier">mtx</phrase><phrase role="special">;</phrase> 15466<phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">condition_variable_any</phrase> <phrase role="identifier">cv</phrase><phrase role="special">;</phrase> 15467<phrase role="comment">// start wotrker-thread first</phrase> 15468<phrase role="keyword">auto</phrase> <phrase role="identifier">worker</phrase> <phrase role="special">=</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">thread</phrase><phrase role="special">(</phrase> 15469 <phrase role="special">[&</phrase><phrase role="identifier">mtx</phrase><phrase role="special">,&</phrase><phrase role="identifier">cv</phrase><phrase role="special">]{</phrase> 15470 <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">use_scheduling_algorithm</phrase><phrase role="special"><</phrase><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">algo</phrase><phrase role="special">::</phrase><phrase role="identifier">work_stealing</phrase><phrase role="special">>(</phrase><phrase role="number">2</phrase><phrase role="special">);</phrase> 15471 <phrase role="identifier">mtx</phrase><phrase role="special">.</phrase><phrase role="identifier">lock</phrase><phrase role="special">();</phrase> 15472 <phrase role="comment">// suspend main-fiber from the worker thread</phrase> 15473 <phrase role="identifier">cv</phrase><phrase role="special">.</phrase><phrase role="identifier">wait</phrase><phrase role="special">(</phrase><phrase role="identifier">mtx</phrase><phrase role="special">);</phrase> 15474 <phrase role="identifier">mtx</phrase><phrase role="special">.</phrase><phrase role="identifier">unlock</phrase><phrase role="special">();</phrase> 15475 <phrase role="special">});</phrase> 15476<phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">use_scheduling_algorithm</phrase><phrase role="special"><</phrase><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">algo</phrase><phrase role="special">::</phrase><phrase role="identifier">work_stealing</phrase><phrase role="special">>(</phrase><phrase role="number">2</phrase><phrase role="special">);</phrase> 15477<phrase role="comment">// create fibers with tasks</phrase> 15478<phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">fiber</phrase> <phrase role="identifier">f</phrase><phrase role="special">{[]{</phrase> <phrase role="special">...</phrase> <phrase role="special">}};</phrase> 15479<phrase role="special">...</phrase> 15480<phrase role="comment">// signal termination</phrase> 15481<phrase role="identifier">cv</phrase><phrase role="special">.</phrase><phrase role="identifier">notify_all</phrase><phrase role="special">();</phrase> 15482<phrase role="identifier">worker</phrase><phrase role="special">.</phrase><phrase role="identifier">join</phrase><phrase role="special">();</phrase> 15483</programlisting> 15484 <important> 15485 <para> 15486 Because the TIB (thread information block on Windows) is not fully described 15487 in the MSDN, it might be possible that not all required TIB-parts are swapped. 15488 Using WinFiber implementation might be an alternative (see documentation 15489 about <ulink url="http://www.boost.org/doc/libs/1_65_1/libs/context/doc/html/context/cc/implementations__fcontext_t__ucontext_t_and_winfiber.html"><emphasis>implementations 15490 fcontext_t, ucontext_t and WinFiber of boost.context</emphasis></ulink>). 15491 </para> 15492 </important> 15493 </section> 15494 <section id="fiber.performance"> 15495 <title><link linkend="fiber.performance">Performance</link></title> 15496 <para> 15497 Performance measurements were taken using <code><phrase role="identifier">std</phrase><phrase 15498 role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase 15499 role="special">::</phrase><phrase role="identifier">highresolution_clock</phrase></code>, 15500 with overhead corrections. The code was compiled with gcc-6.3.1, using build 15501 options: variant = release, optimization = speed. Tests were executed on dual 15502 Intel XEON E5 2620v4 2.2GHz, 16C/32T, 64GB RAM, running Linux (x86_64). 15503 </para> 15504 <para> 15505 Measurements headed 1C/1T were run in a single-threaded process. 15506 </para> 15507 <para> 15508 The <ulink url="https://github.com/atemerev/skynet">microbenchmark <emphasis>syknet</emphasis></ulink> 15509 from Alexander Temerev was ported and used for performance measurements. At 15510 the root the test spawns 10 threads-of-execution (ToE), e.g. actor/goroutine/fiber 15511 etc.. Each spawned ToE spawns additional 10 ToEs ... until <emphasis role="bold">1,000,000</emphasis> 15512 ToEs are created. ToEs return back their ordinal numbers (0 ... 999,999), which 15513 are summed on the previous level and sent back upstream, until reaching the 15514 root. The test was run 10-20 times, producing a range of values for each measurement. 15515 </para> 15516 <table frame="all" id="fiber.performance.time_per_actor_erlang_process_goroutine__other_languages___average_over_1_000_000_"> 15517 <title>time per actor/erlang process/goroutine (other languages) (average over 15518 1,000,000)</title> 15519 <tgroup cols="3"> 15520 <thead> 15521 <row> 15522 <entry> 15523 <para> 15524 Haskell | stack-1.4.0/ghc-8.0.1 15525 </para> 15526 </entry> 15527 <entry> 15528 <para> 15529 Go | go1.8.1 15530 </para> 15531 </entry> 15532 <entry> 15533 <para> 15534 Erlang | erts-8.3 15535 </para> 15536 </entry> 15537 </row> 15538 </thead> 15539 <tbody> 15540 <row> 15541 <entry> 15542 <para> 15543 0.05 µs - 0.06 µs 15544 </para> 15545 </entry> 15546 <entry> 15547 <para> 15548 0.42 µs - 0.49 µs 15549 </para> 15550 </entry> 15551 <entry> 15552 <para> 15553 0.63 µs - 0.73 µs 15554 </para> 15555 </entry> 15556 </row> 15557 </tbody> 15558 </tgroup> 15559 </table> 15560 <para> 15561 Pthreads are created with a stack size of 8kB while <code><phrase role="identifier">std</phrase><phrase 15562 role="special">::</phrase><phrase role="identifier">thread</phrase></code>'s 15563 use the system default (1MB - 2MB). The microbenchmark could <emphasis role="bold">not</emphasis> 15564 be <emphasis role="bold">run</emphasis> with 1,000,000 threads because of 15565 <emphasis role="bold">resource exhaustion</emphasis> (pthread and std::thread). 15566 Instead the test runs only at <emphasis role="bold">10,000</emphasis> threads. 15567 </para> 15568 <table frame="all" id="fiber.performance.time_per_thread__average_over_10_000___unable_to_spawn_1_000_000_threads_"> 15569 <title>time per thread (average over 10,000 - unable to spawn 1,000,000 threads)</title> 15570 <tgroup cols="3"> 15571 <thead> 15572 <row> 15573 <entry> 15574 <para> 15575 pthread 15576 </para> 15577 </entry> 15578 <entry> 15579 <para> 15580 <code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase 15581 role="identifier">thread</phrase></code> 15582 </para> 15583 </entry> 15584 <entry> 15585 <para> 15586 <code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase 15587 role="identifier">async</phrase></code> 15588 </para> 15589 </entry> 15590 </row> 15591 </thead> 15592 <tbody> 15593 <row> 15594 <entry> 15595 <para> 15596 54 µs - 73 µs 15597 </para> 15598 </entry> 15599 <entry> 15600 <para> 15601 52 µs - 73 µs 15602 </para> 15603 </entry> 15604 <entry> 15605 <para> 15606 106 µs - 122 µs 15607 </para> 15608 </entry> 15609 </row> 15610 </tbody> 15611 </tgroup> 15612 </table> 15613 <para> 15614 The test utilizes 16 cores with Symmetric MultiThreading enabled (32 logical 15615 CPUs). The fiber stacks are allocated by <link linkend="class_fixedsize_stack"><code>fixedsize_stack</code></link>. 15616 </para> 15617 <para> 15618 As the benchmark shows, the memory allocation algorithm is significant for 15619 performance in a multithreaded environment. The tests use glibc’s memory allocation 15620 algorithm (based on ptmalloc2) as well as Google’s <ulink url="http://goog-perftools.sourceforge.net/doc/tcmalloc.html">TCmalloc</ulink> 15621 (via linkflags="-ltcmalloc").<footnote id="fiber.performance.f0"> 15622 <para> 15623 Tais B. Ferreira, Rivalino Matias, Autran Macedo, Lucio B. Araujo <quote>An 15624 Experimental Study on Memory Allocators in Multicore and Multithreaded Applications</quote>, 15625 PDCAT ’11 Proceedings of the 2011 12th International Conference on Parallel 15626 and Distributed Computing, Applications and Technologies, pages 92-98 15627 </para> 15628 </footnote> 15629 </para> 15630 <para> 15631 In the <link linkend="class_work_stealing"><code>work_stealing</code></link> scheduling algorithm, each thread has 15632 its own local queue. Fibers that are ready to run are pushed to and popped 15633 from the local queue. If the queue runs out of ready fibers, fibers are stolen 15634 from the local queues of other participating threads. 15635 </para> 15636 <table frame="all" id="fiber.performance.time_per_fiber__average_over_1_000_000_"> 15637 <title>time per fiber (average over 1.000.000)</title> 15638 <tgroup cols="2"> 15639 <thead> 15640 <row> 15641 <entry> 15642 <para> 15643 fiber (16C/32T, work stealing, tcmalloc) 15644 </para> 15645 </entry> 15646 <entry> 15647 <para> 15648 fiber (1C/1T, round robin, tcmalloc) 15649 </para> 15650 </entry> 15651 </row> 15652 </thead> 15653 <tbody> 15654 <row> 15655 <entry> 15656 <para> 15657 0.05 µs - 0.09 µs 15658 </para> 15659 </entry> 15660 <entry> 15661 <para> 15662 1.69 µs - 1.79 µs 15663 </para> 15664 </entry> 15665 </row> 15666 </tbody> 15667 </tgroup> 15668 </table> 15669 </section> 15670 <section id="fiber.tuning"> 15671 <title><anchor id="tuning"/><link linkend="fiber.tuning">Tuning</link></title> 15672 <bridgehead renderas="sect3" id="fiber.tuning.h0"> 15673 <phrase id="fiber.tuning.disable_synchronization"/><link linkend="fiber.tuning.disable_synchronization">Disable 15674 synchronization</link> 15675 </bridgehead> 15676 <para> 15677 With <link linkend="cross_thread_sync"><code><phrase role="identifier">BOOST_FIBERS_NO_ATOMICS</phrase></code></link> 15678 defined at the compiler’s command line, synchronization between fibers (in different 15679 threads) is disabled. This is acceptable if the application is single threaded 15680 and/or fibers are not synchronized between threads. 15681 </para> 15682 <bridgehead renderas="sect3" id="fiber.tuning.h1"> 15683 <phrase id="fiber.tuning.memory_allocation"/><link linkend="fiber.tuning.memory_allocation">Memory 15684 allocation</link> 15685 </bridgehead> 15686 <para> 15687 Memory allocation algorithm is significant for performance in a multithreaded 15688 environment, especially for <emphasis role="bold">Boost.Fiber</emphasis> where 15689 fiber stacks are allocated on the heap. The default user-level memory allocator 15690 (UMA) of glibc is ptmalloc2 but it can be replaced by another UMA that fit 15691 better for the concret work-load For instance Google’s <ulink url="http://goog-perftools.sourceforge.net/doc/tcmalloc.html">TCmalloc</ulink> 15692 enables a better performance at the <emphasis>skynet</emphasis> microbenchmark 15693 than glibc’s default memory allocator. 15694 </para> 15695 <bridgehead renderas="sect3" id="fiber.tuning.h2"> 15696 <phrase id="fiber.tuning.scheduling_strategies"/><link linkend="fiber.tuning.scheduling_strategies">Scheduling 15697 strategies</link> 15698 </bridgehead> 15699 <para> 15700 The fibers in a thread are coordinated by a fiber manager. Fibers trade control 15701 cooperatively, rather than preemptively. Depending on the work-load several 15702 strategies of scheduling the fibers are possible <footnote id="fiber.tuning.f0"> 15703 <para> 15704 1024cores.net: <ulink url="http://www.1024cores.net/home/scalable-architecture/task-scheduling-strategies">Task 15705 Scheduling Strategies</ulink> 15706 </para> 15707 </footnote> that can be implmented on behalf of <link linkend="class_algorithm"><code>algorithm</code></link>. 15708 </para> 15709 <itemizedlist> 15710 <listitem> 15711 <simpara> 15712 work-stealing: ready fibers are hold in a local queue, when the fiber-scheduler's 15713 local queue runs out of ready fibers, it randomly selects another fiber-scheduler 15714 and tries to steal a ready fiber from the victim (implemented in <link linkend="class_work_stealing"><code>work_stealing</code></link> and 15715 <link linkend="class_numa_work_stealing"><code>numa::work_stealing</code></link>) 15716 </simpara> 15717 </listitem> 15718 <listitem> 15719 <simpara> 15720 work-requesting: ready fibers are hold in a local queue, when the fiber-scheduler's 15721 local queue runs out of ready fibers, it randomly selects another fiber-scheduler 15722 and requests for a ready fibers, the victim fiber-scheduler sends a ready-fiber 15723 back 15724 </simpara> 15725 </listitem> 15726 <listitem> 15727 <simpara> 15728 work-sharing: ready fibers are hold in a global queue, fiber-scheduler 15729 concurrently push and pop ready fibers to/from the global queue (implemented 15730 in <link linkend="class_shared_work"><code>shared_work</code></link>) 15731 </simpara> 15732 </listitem> 15733 <listitem> 15734 <simpara> 15735 work-distribution: fibers that became ready are proactivly distributed 15736 to idle fiber-schedulers or fiber-schedulers with low load 15737 </simpara> 15738 </listitem> 15739 <listitem> 15740 <simpara> 15741 work-balancing: a dedicated (helper) fiber-scheduler periodically collects 15742 informations about all fiber-scheduler running in other threads and re-distributes 15743 ready fibers among them 15744 </simpara> 15745 </listitem> 15746 </itemizedlist> 15747 <bridgehead renderas="sect3" id="fiber.tuning.h3"> 15748 <phrase id="fiber.tuning.ttas_locks"/><link linkend="fiber.tuning.ttas_locks">TTAS 15749 locks</link> 15750 </bridgehead> 15751 <para> 15752 Boost.Fiber uses internally spinlocks to protect critical regions if fibers 15753 running on different threads interact. Spinlocks are implemented as TTAS (test-test-and-set) 15754 locks, i.e. the spinlock tests the lock before calling an atomic exchange. 15755 This strategy helps to reduce the cache line invalidations triggered by acquiring/releasing 15756 the lock. 15757 </para> 15758 <bridgehead renderas="sect3" id="fiber.tuning.h4"> 15759 <phrase id="fiber.tuning.spin_wait_loop"/><link linkend="fiber.tuning.spin_wait_loop">Spin-wait 15760 loop</link> 15761 </bridgehead> 15762 <para> 15763 A lock is considered under contention, if a thread repeatedly fails to acquire 15764 the lock because some other thread was faster. Waiting for a short time lets 15765 other threads finish before trying to enter the critical section again. While 15766 busy waiting on the lock, relaxing the CPU (via pause/yield mnemonic) gives 15767 the CPU a hint that the code is in a spin-wait loop. 15768 </para> 15769 <itemizedlist> 15770 <listitem> 15771 <simpara> 15772 prevents expensive pipeline flushes (speculatively executed load and compare 15773 instructions are not pushed to pipeline) 15774 </simpara> 15775 </listitem> 15776 <listitem> 15777 <simpara> 15778 another hardware thread (simultaneous multithreading) can get time slice 15779 </simpara> 15780 </listitem> 15781 <listitem> 15782 <simpara> 15783 it does delay a few CPU cycles, but this is necessary to prevent starvation 15784 </simpara> 15785 </listitem> 15786 </itemizedlist> 15787 <para> 15788 It is obvious that this strategy is useless on single core systems because 15789 the lock can only released if the thread gives up its time slice in order to 15790 let other threads run. The macro BOOST_FIBERS_SPIN_SINGLE_CORE replaces the 15791 CPU hints (pause/yield mnemonic) by informing the operating system (via <code><phrase 15792 role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">this_thread_yield</phrase><phrase 15793 role="special">()</phrase></code>) that the thread gives up its time slice 15794 and the operating system switches to another thread. 15795 </para> 15796 <bridgehead renderas="sect3" id="fiber.tuning.h5"> 15797 <phrase id="fiber.tuning.exponential_back_off"/><link linkend="fiber.tuning.exponential_back_off">Exponential 15798 back-off</link> 15799 </bridgehead> 15800 <para> 15801 The macro BOOST_FIBERS_RETRY_THRESHOLD determines how many times the CPU iterates 15802 in the spin-wait loop before yielding the thread or blocking in futex-wait. 15803 The spinlock tracks how many times the thread failed to acquire the lock. The 15804 higher the contention, the longer the thread should back-off. A <quote>Binary 15805 Exponential Backoff</quote> algorithm together with a randomized contention 15806 window is utilized for this purpose. BOOST_FIBERS_CONTENTION_WINDOW_THRESHOLD 15807 determines the upper limit of the contention window (expressed as the exponent 15808 for basis of two). 15809 </para> 15810 <bridgehead renderas="sect3" id="fiber.tuning.h6"> 15811 <phrase id="fiber.tuning.speculative_execution__hardware_transactional_memory_"/><link 15812 linkend="fiber.tuning.speculative_execution__hardware_transactional_memory_">Speculative 15813 execution (hardware transactional memory)</link> 15814 </bridgehead> 15815 <para> 15816 Boost.Fiber uses spinlocks to protect critical regions that can be used together 15817 with transactional memory (see section <link linkend="speculation">Speculative 15818 execution</link>). 15819 </para> 15820 <note> 15821 <para> 15822 TXS is enabled if property <code><phrase role="identifier">htm</phrase><phrase 15823 role="special">=</phrase><phrase role="identifier">tsx</phrase></code> is 15824 specified at b2 command-line and <code><phrase role="identifier">BOOST_USE_TSX</phrase></code> 15825 is applied to the compiler. 15826 </para> 15827 </note> 15828 <note> 15829 <para> 15830 A TSX-transaction will be aborted if the floating point state is modified 15831 inside a critical region. As a consequence floating point operations, e.g. 15832 tore/load of floating point related registers during a fiber (context) switch 15833 are disabled. 15834 </para> 15835 </note> 15836 <bridgehead renderas="sect3" id="fiber.tuning.h7"> 15837 <phrase id="fiber.tuning.numa_systems"/><link linkend="fiber.tuning.numa_systems">NUMA 15838 systems</link> 15839 </bridgehead> 15840 <para> 15841 Modern multi-socket systems are usually designed as <link linkend="numa">NUMA 15842 systems</link>. A suitable fiber scheduler like <link linkend="class_numa_work_stealing"><code>numa::work_stealing</code></link> reduces 15843 remote memory access (latence). 15844 </para> 15845 <bridgehead renderas="sect3" id="fiber.tuning.h8"> 15846 <phrase id="fiber.tuning.parameters"/><link linkend="fiber.tuning.parameters">Parameters</link> 15847 </bridgehead> 15848 <table frame="all" id="fiber.tuning.parameters_that_migh_be_defiend_at_compiler_s_command_line"> 15849 <title>Parameters that migh be defiend at compiler's command line</title> 15850 <tgroup cols="3"> 15851 <thead> 15852 <row> 15853 <entry> 15854 <para> 15855 Parameter 15856 </para> 15857 </entry> 15858 <entry> 15859 <para> 15860 Default value 15861 </para> 15862 </entry> 15863 <entry> 15864 <para> 15865 Effect on Boost.Fiber 15866 </para> 15867 </entry> 15868 </row> 15869 </thead> 15870 <tbody> 15871 <row> 15872 <entry> 15873 <para> 15874 BOOST_FIBERS_NO_ATOMICS 15875 </para> 15876 </entry> 15877 <entry> 15878 <para> 15879 - 15880 </para> 15881 </entry> 15882 <entry> 15883 <para> 15884 no multithreading support, all atomics removed, no synchronization 15885 between fibers running in different threads 15886 </para> 15887 </entry> 15888 </row> 15889 <row> 15890 <entry> 15891 <para> 15892 BOOST_FIBERS_SPINLOCK_STD_MUTEX 15893 </para> 15894 </entry> 15895 <entry> 15896 <para> 15897 - 15898 </para> 15899 </entry> 15900 <entry> 15901 <para> 15902 <code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase 15903 role="identifier">mutex</phrase></code> used inside spinlock 15904 </para> 15905 </entry> 15906 </row> 15907 <row> 15908 <entry> 15909 <para> 15910 BOOST_FIBERS_SPINLOCK_TTAS 15911 </para> 15912 </entry> 15913 <entry> 15914 <para> 15915 + 15916 </para> 15917 </entry> 15918 <entry> 15919 <para> 15920 spinlock with test-test-and-swap on shared variable 15921 </para> 15922 </entry> 15923 </row> 15924 <row> 15925 <entry> 15926 <para> 15927 BOOST_FIBERS_SPINLOCK_TTAS_ADAPTIVE 15928 </para> 15929 </entry> 15930 <entry> 15931 <para> 15932 - 15933 </para> 15934 </entry> 15935 <entry> 15936 <para> 15937 spinlock with test-test-and-swap on shared variable, adaptive retries 15938 while busy waiting 15939 </para> 15940 </entry> 15941 </row> 15942 <row> 15943 <entry> 15944 <para> 15945 BOOST_FIBERS_SPINLOCK_TTAS_FUTEX 15946 </para> 15947 </entry> 15948 <entry> 15949 <para> 15950 - 15951 </para> 15952 </entry> 15953 <entry> 15954 <para> 15955 spinlock with test-test-and-swap on shared variable, suspend on futex 15956 after certain number of retries 15957 </para> 15958 </entry> 15959 </row> 15960 <row> 15961 <entry> 15962 <para> 15963 BOOST_FIBERS_SPINLOCK_TTAS_ADAPTIVE_FUTEX 15964 </para> 15965 </entry> 15966 <entry> 15967 <para> 15968 - 15969 </para> 15970 </entry> 15971 <entry> 15972 <para> 15973 spinlock with test-test-and-swap on shared variable, while busy waiting 15974 adaptive retries, suspend on futex certain amount of retries 15975 </para> 15976 </entry> 15977 </row> 15978 <row> 15979 <entry> 15980 <para> 15981 BOOST_FIBERS_SPINLOCK_TTAS + BOOST_USE_TSX 15982 </para> 15983 </entry> 15984 <entry> 15985 <para> 15986 - 15987 </para> 15988 </entry> 15989 <entry> 15990 <para> 15991 spinlock with test-test-and-swap and speculative execution (Intel 15992 TSX required) 15993 </para> 15994 </entry> 15995 </row> 15996 <row> 15997 <entry> 15998 <para> 15999 BOOST_FIBERS_SPINLOCK_TTAS_ADAPTIVE + BOOST_USE_TSX 16000 </para> 16001 </entry> 16002 <entry> 16003 <para> 16004 - 16005 </para> 16006 </entry> 16007 <entry> 16008 <para> 16009 spinlock with test-test-and-swap on shared variable, adaptive retries 16010 while busy waiting and speculative execution (Intel TSX required) 16011 </para> 16012 </entry> 16013 </row> 16014 <row> 16015 <entry> 16016 <para> 16017 BOOST_FIBERS_SPINLOCK_TTAS_FUTEX + BOOST_USE_TSX 16018 </para> 16019 </entry> 16020 <entry> 16021 <para> 16022 - 16023 </para> 16024 </entry> 16025 <entry> 16026 <para> 16027 spinlock with test-test-and-swap on shared variable, suspend on futex 16028 after certain number of retries and speculative execution (Intel 16029 TSX required) 16030 </para> 16031 </entry> 16032 </row> 16033 <row> 16034 <entry> 16035 <para> 16036 BOOST_FIBERS_SPINLOCK_TTAS_ADAPTIVE_FUTEX + BOOST_USE_TSX 16037 </para> 16038 </entry> 16039 <entry> 16040 <para> 16041 - 16042 </para> 16043 </entry> 16044 <entry> 16045 <para> 16046 spinlock with test-test-and-swap on shared variable, while busy waiting 16047 adaptive retries, suspend on futex certain amount of retries and 16048 speculative execution (Intel TSX required) 16049 </para> 16050 </entry> 16051 </row> 16052 <row> 16053 <entry> 16054 <para> 16055 BOOST_FIBERS_SPIN_SINGLE_CORE 16056 </para> 16057 </entry> 16058 <entry> 16059 <para> 16060 - 16061 </para> 16062 </entry> 16063 <entry> 16064 <para> 16065 on single core machines with multiple threads, yield thread (<code><phrase 16066 role="identifier">std</phrase><phrase role="special">::</phrase><phrase 16067 role="identifier">this_thread</phrase><phrase role="special">::</phrase><phrase 16068 role="identifier">yield</phrase><phrase role="special">()</phrase></code>) 16069 after collisions 16070 </para> 16071 </entry> 16072 </row> 16073 <row> 16074 <entry> 16075 <para> 16076 BOOST_FIBERS_RETRY_THRESHOLD 16077 </para> 16078 </entry> 16079 <entry> 16080 <para> 16081 64 16082 </para> 16083 </entry> 16084 <entry> 16085 <para> 16086 max number of retries while busy spinning, the use fallback 16087 </para> 16088 </entry> 16089 </row> 16090 <row> 16091 <entry> 16092 <para> 16093 BOOST_FIBERS_CONTENTION_WINDOW_THRESHOLD 16094 </para> 16095 </entry> 16096 <entry> 16097 <para> 16098 16 16099 </para> 16100 </entry> 16101 <entry> 16102 <para> 16103 max size of collisions window, expressed as exponent for the basis 16104 of two 16105 </para> 16106 </entry> 16107 </row> 16108 <row> 16109 <entry> 16110 <para> 16111 BOOST_FIBERS_SPIN_BEFORE_SLEEP0 16112 </para> 16113 </entry> 16114 <entry> 16115 <para> 16116 32 16117 </para> 16118 </entry> 16119 <entry> 16120 <para> 16121 max number of retries that relax the processor before the thread 16122 sleeps for 0s 16123 </para> 16124 </entry> 16125 </row> 16126 <row> 16127 <entry> 16128 <para> 16129 BOOST_FIBERS_SPIN_BEFORE_YIELD 16130 </para> 16131 </entry> 16132 <entry> 16133 <para> 16134 64 16135 </para> 16136 </entry> 16137 <entry> 16138 <para> 16139 max number of retries where the thread sleeps for 0s before yield 16140 thread (<code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase 16141 role="identifier">this_thread</phrase><phrase role="special">::</phrase><phrase 16142 role="identifier">yield</phrase><phrase role="special">()</phrase></code>) 16143 </para> 16144 </entry> 16145 </row> 16146 </tbody> 16147 </tgroup> 16148 </table> 16149 </section> 16150 <section id="fiber.custom"> 16151 <title><anchor id="custom"/><link linkend="fiber.custom">Customization</link></title> 16152 <bridgehead renderas="sect3" id="fiber.custom.h0"> 16153 <phrase id="fiber.custom.overview"/><link linkend="fiber.custom.overview">Overview</link> 16154 </bridgehead> 16155 <para> 16156 As noted in the <link linkend="scheduling">Scheduling</link> section, by default 16157 <emphasis role="bold">Boost.Fiber</emphasis> uses its own <link linkend="class_round_robin"><code>round_robin</code></link> scheduler 16158 for each thread. To control the way <emphasis role="bold">Boost.Fiber</emphasis> 16159 schedules ready fibers on a particular thread, in general you must follow several 16160 steps. This section discusses those steps, whereas <link linkend="scheduling">Scheduling</link> 16161 serves as a reference for the classes involved. 16162 </para> 16163 <para> 16164 The library's fiber manager keeps track of suspended (blocked) fibers. Only 16165 when a fiber becomes ready to run is it passed to the scheduler. Of course, 16166 if there are fewer than two ready fibers, the scheduler's job is trivial. Only 16167 when there are two or more ready fibers does the particular scheduler implementation 16168 start to influence the overall sequence of fiber execution. 16169 </para> 16170 <para> 16171 In this section we illustrate a simple custom scheduler that honors an integer 16172 fiber priority. We will implement it such that a fiber with higher priority 16173 is preferred over a fiber with lower priority. Any fibers with equal priority 16174 values are serviced on a round-robin basis. 16175 </para> 16176 <para> 16177 The full source code for the examples below is found in <ulink url="../../examples/priority.cpp">priority.cpp</ulink>. 16178 </para> 16179 <bridgehead renderas="sect3" id="fiber.custom.h1"> 16180 <phrase id="fiber.custom.custom_property_class"/><link linkend="fiber.custom.custom_property_class">Custom 16181 Property Class</link> 16182 </bridgehead> 16183 <para> 16184 The first essential point is that we must associate an integer priority with 16185 each fiber.<footnote id="fiber.custom.f0"> 16186 <para> 16187 A previous version of the Fiber library implicitly tracked an int priority 16188 for each fiber, even though the default scheduler ignored it. This has been 16189 dropped, since the library now supports arbitrary scheduler-specific fiber 16190 properties. 16191 </para> 16192 </footnote> 16193 </para> 16194 <para> 16195 One might suggest deriving a custom <link linkend="class_fiber"><code>fiber</code></link> subclass to store such 16196 properties. There are a couple of reasons for the present mechanism. 16197 </para> 16198 <orderedlist> 16199 <listitem> 16200 <simpara> 16201 <emphasis role="bold">Boost.Fiber</emphasis> provides a number of different 16202 ways to launch a fiber. (Consider <link linkend="fibers_async"><code>fibers::async()</code></link>.) Higher-level 16203 libraries might introduce additional such wrapper functions. A custom scheduler 16204 must associate its custom properties with <emphasis>every</emphasis> fiber 16205 in the thread, not only the ones explicitly launched by instantiating a 16206 custom <code><phrase role="identifier">fiber</phrase></code> subclass. 16207 </simpara> 16208 </listitem> 16209 <listitem> 16210 <simpara> 16211 Consider a large existing program that launches fibers in many different 16212 places in the code. We discover a need to introduce a custom scheduler 16213 for a particular thread. If supporting that scheduler's custom properties 16214 required a particular <code><phrase role="identifier">fiber</phrase></code> 16215 subclass, we would have to hunt down and modify every place that launches 16216 a fiber on that thread. 16217 </simpara> 16218 </listitem> 16219 <listitem> 16220 <simpara> 16221 The <link linkend="class_fiber"><code>fiber</code></link> class is actually just a handle to internal <link linkend="class_context"><code>context</code></link> data. 16222 A subclass of <code><phrase role="identifier">fiber</phrase></code> would 16223 not add data to <code><phrase role="identifier">context</phrase></code>. 16224 </simpara> 16225 </listitem> 16226 </orderedlist> 16227 <para> 16228 The present mechanism allows you to <quote>drop in</quote> a custom scheduler 16229 with its attendant custom properties <emphasis>without</emphasis> altering 16230 the rest of your application. 16231 </para> 16232 <para> 16233 Instead of deriving a custom scheduler fiber properties subclass from <link linkend="class_fiber"><code>fiber</code></link>, 16234 you must instead derive it from <link linkend="class_fiber_properties"><code>fiber_properties</code></link>. 16235 </para> 16236 <para> 16237<programlisting><phrase role="keyword">class</phrase> <phrase role="identifier">priority_props</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">fiber_properties</phrase> <phrase role="special">{</phrase> 16238<phrase role="keyword">public</phrase><phrase role="special">:</phrase> 16239 <phrase role="identifier">priority_props</phrase><phrase role="special">(</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">context</phrase> <phrase role="special">*</phrase> <phrase role="identifier">ctx</phrase><phrase role="special">):</phrase> 16240 <phrase role="identifier">fiber_properties</phrase><phrase role="special">(</phrase> <phrase role="identifier">ctx</phrase><phrase role="special">),</phrase> <co id="fiber.custom.c0" linkends="fiber.custom.c1" /> 16241 <phrase role="identifier">priority_</phrase><phrase role="special">(</phrase> <phrase role="number">0</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase> 16242 <phrase role="special">}</phrase> 16243 16244 <phrase role="keyword">int</phrase> <phrase role="identifier">get_priority</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase> <phrase role="special">{</phrase> 16245 <phrase role="keyword">return</phrase> <phrase role="identifier">priority_</phrase><phrase role="special">;</phrase> <co id="fiber.custom.c2" linkends="fiber.custom.c3" /> 16246 <phrase role="special">}</phrase> 16247 16248 <phrase role="comment">// Call this method to alter priority, because we must notify</phrase> 16249 <phrase role="comment">// priority_scheduler of any change.</phrase> 16250 <phrase role="keyword">void</phrase> <phrase role="identifier">set_priority</phrase><phrase role="special">(</phrase> <phrase role="keyword">int</phrase> <phrase role="identifier">p</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase> <co id="fiber.custom.c4" linkends="fiber.custom.c5" /> 16251 <phrase role="comment">// Of course, it's only worth reshuffling the queue and all if we're</phrase> 16252 <phrase role="comment">// actually changing the priority.</phrase> 16253 <phrase role="keyword">if</phrase> <phrase role="special">(</phrase> <phrase role="identifier">p</phrase> <phrase role="special">!=</phrase> <phrase role="identifier">priority_</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase> 16254 <phrase role="identifier">priority_</phrase> <phrase role="special">=</phrase> <phrase role="identifier">p</phrase><phrase role="special">;</phrase> 16255 <phrase role="identifier">notify</phrase><phrase role="special">();</phrase> 16256 <phrase role="special">}</phrase> 16257 <phrase role="special">}</phrase> 16258 16259 <phrase role="comment">// The fiber name of course is solely for purposes of this example</phrase> 16260 <phrase role="comment">// program; it has nothing to do with implementing scheduler priority.</phrase> 16261 <phrase role="comment">// This is a public data member -- not requiring set/get access methods --</phrase> 16262 <phrase role="comment">// because we need not inform the scheduler of any change.</phrase> 16263 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="identifier">name</phrase><phrase role="special">;</phrase> <co id="fiber.custom.c6" linkends="fiber.custom.c7" /> 16264<phrase role="keyword">private</phrase><phrase role="special">:</phrase> 16265 <phrase role="keyword">int</phrase> <phrase role="identifier">priority_</phrase><phrase role="special">;</phrase> 16266<phrase role="special">};</phrase> 16267</programlisting> 16268 </para> 16269 <calloutlist> 16270 <callout arearefs="fiber.custom.c0" id="fiber.custom.c1"> 16271 <para> 16272 Your subclass constructor must accept a <literal><link linkend="class_context"><code>context</code></link>*</literal> 16273 and pass it to the <code><phrase role="identifier">fiber_properties</phrase></code> 16274 constructor. 16275 </para> 16276 </callout> 16277 <callout arearefs="fiber.custom.c2" id="fiber.custom.c3"> 16278 <para> 16279 Provide read access methods at your own discretion. 16280 </para> 16281 </callout> 16282 <callout arearefs="fiber.custom.c4" id="fiber.custom.c5"> 16283 <para> 16284 It's important to call <code><phrase role="identifier">notify</phrase><phrase 16285 role="special">()</phrase></code> on any change in a property that can 16286 affect the scheduler's behavior. Therefore, such modifications should only 16287 be performed through an access method. 16288 </para> 16289 </callout> 16290 <callout arearefs="fiber.custom.c6" id="fiber.custom.c7"> 16291 <para> 16292 A property that does not affect the scheduler does not need access methods. 16293 </para> 16294 </callout> 16295 </calloutlist> 16296 <bridgehead renderas="sect3" id="fiber.custom.h2"> 16297 <phrase id="fiber.custom.custom_scheduler_class"/><link linkend="fiber.custom.custom_scheduler_class">Custom 16298 Scheduler Class</link> 16299 </bridgehead> 16300 <para> 16301 Now we can derive a custom scheduler from <link linkend="class_algorithm_with_properties"><code>algorithm_with_properties<></code></link>, 16302 specifying our custom property class <code><phrase role="identifier">priority_props</phrase></code> 16303 as the template parameter. 16304 </para> 16305 <para> 16306<programlisting><phrase role="keyword">class</phrase> <phrase role="identifier">priority_scheduler</phrase> <phrase role="special">:</phrase> 16307 <phrase role="keyword">public</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">algo</phrase><phrase role="special">::</phrase><phrase role="identifier">algorithm_with_properties</phrase><phrase role="special"><</phrase> <phrase role="identifier">priority_props</phrase> <phrase role="special">></phrase> <phrase role="special">{</phrase> 16308<phrase role="keyword">private</phrase><phrase role="special">:</phrase> 16309 <phrase role="keyword">typedef</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">scheduler</phrase><phrase role="special">::</phrase><phrase role="identifier">ready_queue_type</phrase><co id="fiber.custom.c8" linkends="fiber.custom.c9" /> <phrase role="identifier">rqueue_t</phrase><phrase role="special">;</phrase> 16310 16311 <phrase role="identifier">rqueue_t</phrase> <phrase role="identifier">rqueue_</phrase><phrase role="special">;</phrase> 16312 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">mutex</phrase> <phrase role="identifier">mtx_</phrase><phrase role="special">{};</phrase> 16313 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">condition_variable</phrase> <phrase role="identifier">cnd_</phrase><phrase role="special">{};</phrase> 16314 <phrase role="keyword">bool</phrase> <phrase role="identifier">flag_</phrase><phrase role="special">{</phrase> <phrase role="keyword">false</phrase> <phrase role="special">};</phrase> 16315 16316<phrase role="keyword">public</phrase><phrase role="special">:</phrase> 16317 <phrase role="identifier">priority_scheduler</phrase><phrase role="special">()</phrase> <phrase role="special">:</phrase> 16318 <phrase role="identifier">rqueue_</phrase><phrase role="special">()</phrase> <phrase role="special">{</phrase> 16319 <phrase role="special">}</phrase> 16320 16321 <phrase role="comment">// For a subclass of algorithm_with_properties<>, it's important to</phrase> 16322 <phrase role="comment">// override the correct awakened() overload.</phrase> 16323 <co id="fiber.custom.c10" linkends="fiber.custom.c11" /><phrase role="keyword">virtual</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">awakened</phrase><phrase role="special">(</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">context</phrase> <phrase role="special">*</phrase> <phrase role="identifier">ctx</phrase><phrase role="special">,</phrase> <phrase role="identifier">priority_props</phrase> <phrase role="special">&</phrase> <phrase role="identifier">props</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase> <phrase role="special">{</phrase> 16324 <phrase role="keyword">int</phrase> <phrase role="identifier">ctx_priority</phrase> <phrase role="special">=</phrase> <phrase role="identifier">props</phrase><phrase role="special">.</phrase><phrase role="identifier">get_priority</phrase><phrase role="special">();</phrase> <co id="fiber.custom.c12" linkends="fiber.custom.c13" /> 16325 <phrase role="comment">// With this scheduler, fibers with higher priority values are</phrase> 16326 <phrase role="comment">// preferred over fibers with lower priority values. But fibers with</phrase> 16327 <phrase role="comment">// equal priority values are processed in round-robin fashion. So when</phrase> 16328 <phrase role="comment">// we're handed a new context*, put it at the end of the fibers</phrase> 16329 <phrase role="comment">// with that same priority. In other words: search for the first fiber</phrase> 16330 <phrase role="comment">// in the queue with LOWER priority, and insert before that one.</phrase> 16331 <phrase role="identifier">rqueue_t</phrase><phrase role="special">::</phrase><phrase role="identifier">iterator</phrase> <phrase role="identifier">i</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">find_if</phrase><phrase role="special">(</phrase> <phrase role="identifier">rqueue_</phrase><phrase role="special">.</phrase><phrase role="identifier">begin</phrase><phrase role="special">(),</phrase> <phrase role="identifier">rqueue_</phrase><phrase role="special">.</phrase><phrase role="identifier">end</phrase><phrase role="special">(),</phrase> 16332 <phrase role="special">[</phrase><phrase role="identifier">ctx_priority</phrase><phrase role="special">,</phrase><phrase role="keyword">this</phrase><phrase role="special">](</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">context</phrase> <phrase role="special">&</phrase> <phrase role="identifier">c</phrase><phrase role="special">)</phrase> 16333 <phrase role="special">{</phrase> <phrase role="keyword">return</phrase> <phrase role="identifier">properties</phrase><phrase role="special">(</phrase> <phrase role="special">&</phrase><phrase role="identifier">c</phrase> <phrase role="special">).</phrase><phrase role="identifier">get_priority</phrase><phrase role="special">()</phrase> <phrase role="special"><</phrase> <phrase role="identifier">ctx_priority</phrase><phrase role="special">;</phrase> <phrase role="special">}));</phrase> 16334 <phrase role="comment">// Now, whether or not we found a fiber with lower priority,</phrase> 16335 <phrase role="comment">// insert this new fiber here.</phrase> 16336 <phrase role="identifier">rqueue_</phrase><phrase role="special">.</phrase><phrase role="identifier">insert</phrase><phrase role="special">(</phrase> <phrase role="identifier">i</phrase><phrase role="special">,</phrase> <phrase role="special">*</phrase> <phrase role="identifier">ctx</phrase><phrase role="special">);</phrase> 16337 <phrase role="special">}</phrase> 16338 16339 <co id="fiber.custom.c14" linkends="fiber.custom.c15" /><phrase role="keyword">virtual</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">context</phrase> <phrase role="special">*</phrase> <phrase role="identifier">pick_next</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase> <phrase role="special">{</phrase> 16340 <phrase role="comment">// if ready queue is empty, just tell caller</phrase> 16341 <phrase role="keyword">if</phrase> <phrase role="special">(</phrase> <phrase role="identifier">rqueue_</phrase><phrase role="special">.</phrase><phrase role="identifier">empty</phrase><phrase role="special">()</phrase> <phrase role="special">)</phrase> <phrase role="special">{</phrase> 16342 <phrase role="keyword">return</phrase> <phrase role="keyword">nullptr</phrase><phrase role="special">;</phrase> 16343 <phrase role="special">}</phrase> 16344 <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">context</phrase> <phrase role="special">*</phrase> <phrase role="identifier">ctx</phrase><phrase role="special">(</phrase> <phrase role="special">&</phrase> <phrase role="identifier">rqueue_</phrase><phrase role="special">.</phrase><phrase role="identifier">front</phrase><phrase role="special">()</phrase> <phrase role="special">);</phrase> 16345 <phrase role="identifier">rqueue_</phrase><phrase role="special">.</phrase><phrase role="identifier">pop_front</phrase><phrase role="special">();</phrase> 16346 <phrase role="keyword">return</phrase> <phrase role="identifier">ctx</phrase><phrase role="special">;</phrase> 16347 <phrase role="special">}</phrase> 16348 16349 <co id="fiber.custom.c16" linkends="fiber.custom.c17" /><phrase role="keyword">virtual</phrase> <phrase role="keyword">bool</phrase> <phrase role="identifier">has_ready_fibers</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase> <phrase role="keyword">noexcept</phrase> <phrase role="special">{</phrase> 16350 <phrase role="keyword">return</phrase> <phrase role="special">!</phrase> <phrase role="identifier">rqueue_</phrase><phrase role="special">.</phrase><phrase role="identifier">empty</phrase><phrase role="special">();</phrase> 16351 <phrase role="special">}</phrase> 16352 16353 <co id="fiber.custom.c18" linkends="fiber.custom.c19" /><phrase role="keyword">virtual</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">property_change</phrase><phrase role="special">(</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">context</phrase> <phrase role="special">*</phrase> <phrase role="identifier">ctx</phrase><phrase role="special">,</phrase> <phrase role="identifier">priority_props</phrase> <phrase role="special">&</phrase> <phrase role="identifier">props</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase> <phrase role="special">{</phrase> 16354 <phrase role="comment">// Although our priority_props class defines multiple properties, only</phrase> 16355 <phrase role="comment">// one of them (priority) actually calls notify() when changed. The</phrase> 16356 <phrase role="comment">// point of a property_change() override is to reshuffle the ready</phrase> 16357 <phrase role="comment">// queue according to the updated priority value.</phrase> 16358 16359 <phrase role="comment">// 'ctx' might not be in our queue at all, if caller is changing the</phrase> 16360 <phrase role="comment">// priority of (say) the running fiber. If it's not there, no need to</phrase> 16361 <phrase role="comment">// move it: we'll handle it next time it hits awakened().</phrase> 16362 <phrase role="keyword">if</phrase> <phrase role="special">(</phrase> <phrase role="special">!</phrase> <phrase role="identifier">ctx</phrase><phrase role="special">-></phrase><phrase role="identifier">ready_is_linked</phrase><phrase role="special">())</phrase> <phrase role="special">{</phrase> <co id="fiber.custom.c20" linkends="fiber.custom.c21" /> 16363 <phrase role="keyword">return</phrase><phrase role="special">;</phrase> 16364 <phrase role="special">}</phrase> 16365 16366 <phrase role="comment">// Found ctx: unlink it</phrase> 16367 <phrase role="identifier">ctx</phrase><phrase role="special">-></phrase><phrase role="identifier">ready_unlink</phrase><phrase role="special">();</phrase> 16368 16369 <phrase role="comment">// Here we know that ctx was in our ready queue, but we've unlinked</phrase> 16370 <phrase role="comment">// it. We happen to have a method that will (re-)add a context* to the</phrase> 16371 <phrase role="comment">// right place in the ready queue.</phrase> 16372 <phrase role="identifier">awakened</phrase><phrase role="special">(</phrase> <phrase role="identifier">ctx</phrase><phrase role="special">,</phrase> <phrase role="identifier">props</phrase><phrase role="special">);</phrase> 16373 <phrase role="special">}</phrase> 16374 16375 <phrase role="keyword">void</phrase> <phrase role="identifier">suspend_until</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">steady_clock</phrase><phrase role="special">::</phrase><phrase role="identifier">time_point</phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">time_point</phrase><phrase role="special">)</phrase> <phrase role="keyword">noexcept</phrase> <phrase role="special">{</phrase> 16376 <phrase role="keyword">if</phrase> <phrase role="special">(</phrase> <phrase role="special">(</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">chrono</phrase><phrase role="special">::</phrase><phrase role="identifier">steady_clock</phrase><phrase role="special">::</phrase><phrase role="identifier">time_point</phrase><phrase role="special">::</phrase><phrase role="identifier">max</phrase><phrase role="special">)()</phrase> <phrase role="special">==</phrase> <phrase role="identifier">time_point</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase> 16377 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">unique_lock</phrase><phrase role="special"><</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">mutex</phrase> <phrase role="special">></phrase> <phrase role="identifier">lk</phrase><phrase role="special">(</phrase> <phrase role="identifier">mtx_</phrase><phrase role="special">);</phrase> 16378 <phrase role="identifier">cnd_</phrase><phrase role="special">.</phrase><phrase role="identifier">wait</phrase><phrase role="special">(</phrase> <phrase role="identifier">lk</phrase><phrase role="special">,</phrase> <phrase role="special">[</phrase><phrase role="keyword">this</phrase><phrase role="special">](){</phrase> <phrase role="keyword">return</phrase> <phrase role="identifier">flag_</phrase><phrase role="special">;</phrase> <phrase role="special">});</phrase> 16379 <phrase role="identifier">flag_</phrase> <phrase role="special">=</phrase> <phrase role="keyword">false</phrase><phrase role="special">;</phrase> 16380 <phrase role="special">}</phrase> <phrase role="keyword">else</phrase> <phrase role="special">{</phrase> 16381 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">unique_lock</phrase><phrase role="special"><</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">mutex</phrase> <phrase role="special">></phrase> <phrase role="identifier">lk</phrase><phrase role="special">(</phrase> <phrase role="identifier">mtx_</phrase><phrase role="special">);</phrase> 16382 <phrase role="identifier">cnd_</phrase><phrase role="special">.</phrase><phrase role="identifier">wait_until</phrase><phrase role="special">(</phrase> <phrase role="identifier">lk</phrase><phrase role="special">,</phrase> <phrase role="identifier">time_point</phrase><phrase role="special">,</phrase> <phrase role="special">[</phrase><phrase role="keyword">this</phrase><phrase role="special">](){</phrase> <phrase role="keyword">return</phrase> <phrase role="identifier">flag_</phrase><phrase role="special">;</phrase> <phrase role="special">});</phrase> 16383 <phrase role="identifier">flag_</phrase> <phrase role="special">=</phrase> <phrase role="keyword">false</phrase><phrase role="special">;</phrase> 16384 <phrase role="special">}</phrase> 16385 <phrase role="special">}</phrase> 16386 16387 <phrase role="keyword">void</phrase> <phrase role="identifier">notify</phrase><phrase role="special">()</phrase> <phrase role="keyword">noexcept</phrase> <phrase role="special">{</phrase> 16388 <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">unique_lock</phrase><phrase role="special"><</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">mutex</phrase> <phrase role="special">></phrase> <phrase role="identifier">lk</phrase><phrase role="special">(</phrase> <phrase role="identifier">mtx_</phrase><phrase role="special">);</phrase> 16389 <phrase role="identifier">flag_</phrase> <phrase role="special">=</phrase> <phrase role="keyword">true</phrase><phrase role="special">;</phrase> 16390 <phrase role="identifier">lk</phrase><phrase role="special">.</phrase><phrase role="identifier">unlock</phrase><phrase role="special">();</phrase> 16391 <phrase role="identifier">cnd_</phrase><phrase role="special">.</phrase><phrase role="identifier">notify_all</phrase><phrase role="special">();</phrase> 16392 <phrase role="special">}</phrase> 16393<phrase role="special">};</phrase> 16394</programlisting> 16395 </para> 16396 <calloutlist> 16397 <callout arearefs="fiber.custom.c8" id="fiber.custom.c9"> 16398 <para> 16399 See <link linkend="ready_queue_t">ready_queue_t</link>. 16400 </para> 16401 </callout> 16402 <callout arearefs="fiber.custom.c10" id="fiber.custom.c11"> 16403 <para> 16404 You must override the <link linkend="algorithm_with_properties_awakened"><code>algorithm_with_properties::awakened()</code></link> 16405 method. 16406 This is how your scheduler receives notification of a fiber that has become 16407 ready to run. 16408 </para> 16409 </callout> 16410 <callout arearefs="fiber.custom.c12" id="fiber.custom.c13"> 16411 <para> 16412 <code><phrase role="identifier">props</phrase></code> is the instance of 16413 priority_props associated with the passed fiber <code><phrase role="identifier">ctx</phrase></code>. 16414 </para> 16415 </callout> 16416 <callout arearefs="fiber.custom.c14" id="fiber.custom.c15"> 16417 <para> 16418 You must override the <link linkend="algorithm_with_properties_pick_next"><code>algorithm_with_properties::pick_next()</code></link> 16419 method. 16420 This is how your scheduler actually advises the fiber manager of the next 16421 fiber to run. 16422 </para> 16423 </callout> 16424 <callout arearefs="fiber.custom.c16" id="fiber.custom.c17"> 16425 <para> 16426 You must override <link linkend="algorithm_with_properties_has_ready_fibers"><code>algorithm_with_properties::has_ready_fibers()</code></link> 16427 to 16428 inform the fiber manager of the state of your ready queue. 16429 </para> 16430 </callout> 16431 <callout arearefs="fiber.custom.c18" id="fiber.custom.c19"> 16432 <para> 16433 Overriding <link linkend="algorithm_with_properties_property_change"><code>algorithm_with_properties::property_change()</code></link> 16434 is 16435 optional. This override handles the case in which the running fiber changes 16436 the priority of another ready fiber: a fiber already in our queue. In that 16437 case, move the updated fiber within the queue. 16438 </para> 16439 </callout> 16440 <callout arearefs="fiber.custom.c20" id="fiber.custom.c21"> 16441 <para> 16442 Your <code><phrase role="identifier">property_change</phrase><phrase role="special">()</phrase></code> 16443 override must be able to handle the case in which the passed <code><phrase 16444 role="identifier">ctx</phrase></code> is not in your ready queue. It might 16445 be running, or it might be blocked. 16446 </para> 16447 </callout> 16448 </calloutlist> 16449 <para> 16450 Our example <code><phrase role="identifier">priority_scheduler</phrase></code> 16451 doesn't override <link linkend="algorithm_with_properties_new_properties"><code>algorithm_with_properties::new_properties()</code></link>: 16452 we're content with allocating <code><phrase role="identifier">priority_props</phrase></code> 16453 instances on the heap. 16454 </para> 16455 <bridgehead renderas="sect3" id="fiber.custom.h3"> 16456 <phrase id="fiber.custom.replace_default_scheduler"/><link linkend="fiber.custom.replace_default_scheduler">Replace 16457 Default Scheduler</link> 16458 </bridgehead> 16459 <para> 16460 You must call <link linkend="use_scheduling_algorithm"><code>use_scheduling_algorithm()</code></link> at the start 16461 of each thread on which you want <emphasis role="bold">Boost.Fiber</emphasis> 16462 to use your custom scheduler rather than its own default <link linkend="class_round_robin"><code>round_robin</code></link>. 16463 Specifically, you must call <code><phrase role="identifier">use_scheduling_algorithm</phrase><phrase 16464 role="special">()</phrase></code> before performing any other <emphasis role="bold">Boost.Fiber</emphasis> 16465 operations on that thread. 16466 </para> 16467 <para> 16468<programlisting><phrase role="keyword">int</phrase> <phrase role="identifier">main</phrase><phrase role="special">(</phrase> <phrase role="keyword">int</phrase> <phrase role="identifier">argc</phrase><phrase role="special">,</phrase> <phrase role="keyword">char</phrase> <phrase role="special">*</phrase><phrase role="identifier">argv</phrase><phrase role="special">[])</phrase> <phrase role="special">{</phrase> 16469 <phrase role="comment">// make sure we use our priority_scheduler rather than default round_robin</phrase> 16470 <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">use_scheduling_algorithm</phrase><phrase role="special"><</phrase> <phrase role="identifier">priority_scheduler</phrase> <phrase role="special">>();</phrase> 16471 <phrase role="special">...</phrase> 16472<phrase role="special">}</phrase> 16473</programlisting> 16474 </para> 16475 <bridgehead renderas="sect3" id="fiber.custom.h4"> 16476 <phrase id="fiber.custom.use_properties"/><link linkend="fiber.custom.use_properties">Use 16477 Properties</link> 16478 </bridgehead> 16479 <para> 16480 The running fiber can access its own <link linkend="class_fiber_properties"><code>fiber_properties</code></link> subclass 16481 instance by calling <link linkend="this_fiber_properties"><code>this_fiber::properties()</code></link>. Although 16482 <code><phrase role="identifier">properties</phrase><phrase role="special"><>()</phrase></code> 16483 is a nullary function, you must pass, as a template parameter, the <code><phrase 16484 role="identifier">fiber_properties</phrase></code> subclass. 16485 </para> 16486 <para> 16487<programlisting><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">this_fiber</phrase><phrase role="special">::</phrase><phrase role="identifier">properties</phrase><phrase role="special"><</phrase> <phrase role="identifier">priority_props</phrase> <phrase role="special">>().</phrase><phrase role="identifier">name</phrase> <phrase role="special">=</phrase> <phrase role="string">"main"</phrase><phrase role="special">;</phrase> 16488</programlisting> 16489 </para> 16490 <para> 16491 Given a <link linkend="class_fiber"><code>fiber</code></link> instance still connected with a running fiber (that 16492 is, not <link linkend="fiber_detach"><code>fiber::detach()</code></link>ed), you may access that fiber's properties 16493 using <link linkend="fiber_properties"><code>fiber::properties()</code></link>. As with <code><phrase role="identifier">boost</phrase><phrase 16494 role="special">::</phrase><phrase role="identifier">this_fiber</phrase><phrase 16495 role="special">::</phrase><phrase role="identifier">properties</phrase><phrase 16496 role="special"><>()</phrase></code>, you must pass your <code><phrase 16497 role="identifier">fiber_properties</phrase></code> subclass as the template 16498 parameter. 16499 </para> 16500 <para> 16501<programlisting><phrase role="keyword">template</phrase><phrase role="special"><</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Fn</phrase> <phrase role="special">></phrase> 16502<phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">fiber</phrase> <phrase role="identifier">launch</phrase><phrase role="special">(</phrase> <phrase role="identifier">Fn</phrase> <phrase role="special">&&</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">&</phrase> <phrase role="identifier">name</phrase><phrase role="special">,</phrase> <phrase role="keyword">int</phrase> <phrase role="identifier">priority</phrase><phrase role="special">)</phrase> <phrase role="special">{</phrase> 16503 <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">fibers</phrase><phrase role="special">::</phrase><phrase role="identifier">fiber</phrase> <phrase role="identifier">fiber</phrase><phrase role="special">(</phrase> <phrase role="identifier">func</phrase><phrase role="special">);</phrase> 16504 <phrase role="identifier">priority_props</phrase> <phrase role="special">&</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"><</phrase> <phrase role="identifier">priority_props</phrase> <phrase role="special">>()</phrase> <phrase role="special">);</phrase> 16505 <phrase role="identifier">props</phrase><phrase role="special">.</phrase><phrase role="identifier">name</phrase> <phrase role="special">=</phrase> <phrase role="identifier">name</phrase><phrase role="special">;</phrase> 16506 <phrase role="identifier">props</phrase><phrase role="special">.</phrase><phrase role="identifier">set_priority</phrase><phrase role="special">(</phrase> <phrase role="identifier">priority</phrase><phrase role="special">);</phrase> 16507 <phrase role="keyword">return</phrase> <phrase role="identifier">fiber</phrase><phrase role="special">;</phrase> 16508<phrase role="special">}</phrase> 16509</programlisting> 16510 </para> 16511 <para> 16512 Launching a new fiber schedules that fiber as ready, but does <emphasis>not</emphasis> 16513 immediately enter its <emphasis>fiber-function</emphasis>. The current fiber 16514 retains control until it blocks (or yields, or terminates) for some other reason. 16515 As shown in the <code><phrase role="identifier">launch</phrase><phrase role="special">()</phrase></code> 16516 function above, it is reasonable to launch a fiber and immediately set relevant 16517 properties -- such as, for instance, its priority. Your custom scheduler can 16518 then make use of this information next time the fiber manager calls <link linkend="algorithm_with_properties_pick_next"><code>algorithm_with_properties::pick_next()</code></link>. 16519 </para> 16520 </section> 16521 <section id="fiber.rationale"> 16522 <title><link linkend="fiber.rationale">Rationale</link></title> 16523 <bridgehead renderas="sect3" id="fiber.rationale.h0"> 16524 <phrase id="fiber.rationale.preprocessor_defines"/><link linkend="fiber.rationale.preprocessor_defines">preprocessor 16525 defines</link> 16526 </bridgehead> 16527 <table frame="all" id="fiber.rationale.preopcessor_defines"> 16528 <title>preopcessor defines</title> 16529 <tgroup cols="2"> 16530 <thead> 16531 <row> 16532 <entry> 16533 </entry> 16534 <entry> 16535 </entry> 16536 </row> 16537 </thead> 16538 <tbody> 16539 <row> 16540 <entry> 16541 <para> 16542 BOOST_FIBERS_NO_ATOMICS 16543 </para> 16544 </entry> 16545 <entry> 16546 <para> 16547 no <code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase 16548 role="identifier">atomic</phrase><phrase role="special"><></phrase></code> 16549 used, inter-thread synchronization disabled 16550 </para> 16551 </entry> 16552 </row> 16553 <row> 16554 <entry> 16555 <para> 16556 BOOST_FIBERS_SPINLOCK_STD_MUTEX 16557 </para> 16558 </entry> 16559 <entry> 16560 <para> 16561 use <code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase 16562 role="identifier">mutex</phrase></code> as spinlock instead of default 16563 <code><phrase role="identifier">XCHG</phrase></code>-sinlock with 16564 backoff 16565 </para> 16566 </entry> 16567 </row> 16568 <row> 16569 <entry> 16570 <para> 16571 BOOST_FIBERS_SPIN_BACKOFF 16572 </para> 16573 </entry> 16574 <entry> 16575 <para> 16576 limit determines when to used <code><phrase role="identifier">std</phrase><phrase 16577 role="special">::</phrase><phrase role="identifier">this_thread</phrase><phrase 16578 role="special">::</phrase><phrase role="identifier">yield</phrase><phrase 16579 role="special">()</phrase></code> instead of mnemonic <code><phrase 16580 role="identifier">pause</phrase><phrase role="special">/</phrase><phrase 16581 role="identifier">yield</phrase></code> during busy wait (apllies 16582 on to <code><phrase role="identifier">XCHG</phrase></code>-spinlock) 16583 </para> 16584 </entry> 16585 </row> 16586 <row> 16587 <entry> 16588 <para> 16589 BOOST_FIBERS_SINGLE_CORE 16590 </para> 16591 </entry> 16592 <entry> 16593 <para> 16594 allways call <code><phrase role="identifier">std</phrase><phrase 16595 role="special">::</phrase><phrase role="identifier">this_thread</phrase><phrase 16596 role="special">::</phrase><phrase role="identifier">yield</phrase><phrase 16597 role="special">()</phrase></code> without backoff during busy wait 16598 (apllies on to <code><phrase role="identifier">XCHG</phrase></code>-spinlock) 16599 </para> 16600 </entry> 16601 </row> 16602 </tbody> 16603 </tgroup> 16604 </table> 16605 <bridgehead renderas="sect3" id="fiber.rationale.h1"> 16606 <phrase id="fiber.rationale.distinction_between_coroutines_and_fibers"/><link 16607 linkend="fiber.rationale.distinction_between_coroutines_and_fibers">distinction 16608 between coroutines and fibers</link> 16609 </bridgehead> 16610 <para> 16611 The fiber library extends the coroutine library by adding a scheduler and synchronization 16612 mechanisms. 16613 </para> 16614 <itemizedlist> 16615 <listitem> 16616 <simpara> 16617 a coroutine yields 16618 </simpara> 16619 </listitem> 16620 <listitem> 16621 <simpara> 16622 a fiber blocks 16623 </simpara> 16624 </listitem> 16625 </itemizedlist> 16626 <para> 16627 When a coroutine yields, it passes control directly to its caller (or, in the 16628 case of symmetric coroutines, a designated other coroutine). When a fiber blocks, 16629 it implicitly passes control to the fiber scheduler. Coroutines have no scheduler 16630 because they need no scheduler.<footnote id="fiber.rationale.f0"> 16631 <para> 16632 <ulink url="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4024.pdf">'N4024: 16633 Distinguishing coroutines and fibers'</ulink> 16634 </para> 16635 </footnote>. 16636 </para> 16637 <bridgehead renderas="sect3" id="fiber.rationale.h2"> 16638 <phrase id="fiber.rationale.what_about_transactional_memory"/><link linkend="fiber.rationale.what_about_transactional_memory">what 16639 about transactional memory</link> 16640 </bridgehead> 16641 <para> 16642 GCC supports transactional memory since version 4.7. Unfortunately tests show 16643 that transactional memory is slower (ca. 4x) than spinlocks using atomics. 16644 Once transactional memory is improved (supporting hybrid tm), spinlocks will 16645 be replaced by __transaction_atomic{} statements surrounding the critical sections. 16646 </para> 16647 <bridgehead renderas="sect3" id="fiber.rationale.h3"> 16648 <phrase id="fiber.rationale.synchronization_between_fibers_running_in_different_threads"/><link 16649 linkend="fiber.rationale.synchronization_between_fibers_running_in_different_threads">synchronization 16650 between fibers running in different threads</link> 16651 </bridgehead> 16652 <para> 16653 Synchronization classes from <ulink url="http://www.boost.org/doc/libs/release/libs/thread/index.html">Boost.Thread</ulink> 16654 block the entire thread. In contrast, the synchronization classes from <emphasis 16655 role="bold">Boost.Fiber</emphasis> block only specific fibers, so that the 16656 scheduler can still keep the thread busy running other fibers in the meantime. 16657 The synchronization classes from <emphasis role="bold">Boost.Fiber</emphasis> 16658 are designed to be thread-safe, i.e. it is possible to synchronize fibers running 16659 in different threads as well as fibers running in the same thread. (However, 16660 there is a build option to disable cross-thread fiber synchronization support; 16661 see <link linkend="cross_thread_sync">this description</link>.) 16662 </para> 16663 <anchor id="spurious_wakeup"/> 16664 <bridgehead renderas="sect3" id="fiber.rationale.h4"> 16665 <phrase id="fiber.rationale.spurious_wakeup"/><link linkend="fiber.rationale.spurious_wakeup">spurious 16666 wakeup</link> 16667 </bridgehead> 16668 <para> 16669 Spurious wakeup can happen when using <ulink url="http://en.cppreference.com/w/cpp/thread/condition_variable"><code><phrase 16670 role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">condition_variable</phrase></code></ulink>: 16671 the condition variable appears to be have been signaled while the awaited condition 16672 may still be false. Spurious wakeup can happen repeatedly and is caused on 16673 some multiprocessor systems where making <code><phrase role="identifier">std</phrase><phrase 16674 role="special">::</phrase><phrase role="identifier">condition_variable</phrase></code> 16675 wakeup completely predictable would slow down all <code><phrase role="identifier">std</phrase><phrase 16676 role="special">::</phrase><phrase role="identifier">condition_variable</phrase></code> 16677 operations.<footnote id="fiber.rationale.f1"> 16678 <para> 16679 David R. Butenhof <quote>Programming with POSIX Threads</quote> 16680 </para> 16681 </footnote> 16682 </para> 16683 <para> 16684 <link linkend="class_condition_variable"><code>condition_variable</code></link> is not subject to spurious wakeup. 16685 Nonetheless it is prudent to test the business-logic condition in a <code><phrase 16686 role="identifier">wait</phrase><phrase role="special">()</phrase></code> loop 16687 — or, equivalently, use one of the <code><phrase role="identifier">wait</phrase><phrase 16688 role="special">(</phrase> <phrase role="identifier">lock</phrase><phrase role="special">,</phrase> 16689 <phrase role="identifier">predicate</phrase> <phrase role="special">)</phrase></code> 16690 overloads. 16691 </para> 16692 <para> 16693 See also <link linkend="condition_variable_spurious_wakeups">No Spurious Wakeups</link>. 16694 </para> 16695 <bridgehead renderas="sect3" id="fiber.rationale.h5"> 16696 <phrase id="fiber.rationale.migrating_fibers_between_threads"/><link linkend="fiber.rationale.migrating_fibers_between_threads">migrating 16697 fibers between threads</link> 16698 </bridgehead> 16699 <para> 16700 Support for migrating fibers between threads has been integrated. The user-defined 16701 scheduler must call <link linkend="context_detach"><code>context::detach()</code></link> on a fiber-context on the 16702 source thread and <link linkend="context_attach"><code>context::attach()</code></link> on the destination thread, 16703 passing the fiber-context to migrate. (For more information about custom schedulers, 16704 see <link linkend="custom">Customization</link>.) Examples <code><phrase role="identifier">work_sharing</phrase></code> 16705 and <code><phrase role="identifier">work_stealing</phrase></code> in directory 16706 <code><phrase role="identifier">examples</phrase></code> might be used as a 16707 blueprint. 16708 </para> 16709 <para> 16710 See also <link linkend="migration">Migrating fibers between threads</link>. 16711 </para> 16712 <bridgehead renderas="sect3" id="fiber.rationale.h6"> 16713 <phrase id="fiber.rationale.support_for_boost_asio"/><link linkend="fiber.rationale.support_for_boost_asio">support 16714 for Boost.Asio</link> 16715 </bridgehead> 16716 <para> 16717 Support for <ulink url="http://www.boost.org/doc/libs/release/libs/asio/index.html">Boost.Asio</ulink>’s 16718 <emphasis>async-result</emphasis> is not part of the official API. However, 16719 to integrate with a <ulink url="http://www.boost.org/doc/libs/release/doc/html/boost_asio/reference/io_service.html"><code><phrase 16720 role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">asio</phrase><phrase 16721 role="special">::</phrase><phrase role="identifier">io_service</phrase></code></ulink>, 16722 see <link linkend="integration">Sharing a Thread with Another Main Loop</link>. 16723 To interface smoothly with an arbitrary Asio async I/O operation, see <link 16724 linkend="callbacks_asio">Then There’s <ulink url="http://www.boost.org/doc/libs/release/libs/asio/index.html">Boost.Asio</ulink></link>. 16725 </para> 16726 <bridgehead renderas="sect3" id="fiber.rationale.h7"> 16727 <phrase id="fiber.rationale.tested_compilers"/><link linkend="fiber.rationale.tested_compilers">tested 16728 compilers</link> 16729 </bridgehead> 16730 <para> 16731 The library was tested with GCC-5.1.1, Clang-3.6.0 and MSVC-14.0 in c++11-mode. 16732 </para> 16733 <bridgehead renderas="sect3" id="fiber.rationale.h8"> 16734 <phrase id="fiber.rationale.supported_architectures"/><link linkend="fiber.rationale.supported_architectures">supported 16735 architectures</link> 16736 </bridgehead> 16737 <para> 16738 <emphasis role="bold">Boost.Fiber</emphasis> depends on <ulink url="http://www.boost.org/doc/libs/release/libs/context/index.html">Boost.Context</ulink> 16739 - the list of supported architectures can be found <ulink url="http://www.boost.org/doc/libs/release/libs/context/doc/html/context/architectures.html">here</ulink>. 16740 </para> 16741 </section> 16742 <section id="fiber.acknowledgements"> 16743 <title><link linkend="fiber.acknowledgements">Acknowledgments</link></title> 16744 <para> 16745 I'd like to thank Agustín Bergé, Eugene Yakubovich, Giovanni Piero Deretta 16746 and especially Nat Goodspeed. 16747 </para> 16748 </section> 16749</library> 16750